diff options
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qv4bytecodehandler.cpp | 3 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 56 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 4 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 2 |
5 files changed, 57 insertions, 10 deletions
diff --git a/src/qml/compiler/qv4bytecodehandler.cpp b/src/qml/compiler/qv4bytecodehandler.cpp index 181594010d..3a3f4a6adb 100644 --- a/src/qml/compiler/qv4bytecodehandler.cpp +++ b/src/qml/compiler/qv4bytecodehandler.cpp @@ -246,6 +246,9 @@ std::vector<int> ByteCodeHandler::collectLabelsInBytecode(const char *code, uint COLLECTOR_BEGIN_INSTR(CallValue) COLLECTOR_END_INSTR(CallValue) + COLLECTOR_BEGIN_INSTR(CallWithReceiver) + COLLECTOR_END_INSTR(CallWithReceiver) + COLLECTOR_BEGIN_INSTR(CallProperty) COLLECTOR_END_INSTR(CallProperty) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 412d787d11..62dbcdaa7d 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1826,6 +1826,8 @@ bool Codegen::visit(CallExpression *ast) case Reference::Super: handleConstruct(base, ast->arguments); return false; + case Reference::SuperProperty: + break; default: base = base.storeOnStack(); break; @@ -1861,11 +1863,11 @@ bool Codegen::visit(CallExpression *ast) } - handleCall(base, calldata); + handleCall(base, calldata, functionObject, thisObject); return false; } -void Codegen::handleCall(Reference &base, Arguments calldata) +void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject) { //### Do we really need all these call instructions? can's we load the callee in a temp? if (base.type == Reference::QmlScopeObject) { @@ -1924,6 +1926,22 @@ void Codegen::handleCall(Reference &base, Arguments calldata) call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); } + } else if (base.type == Reference::SuperProperty) { + Reference receiver = base.baseObject(); + if (!base.isStackSlot()) { + base.storeOnStack(slotForFunction); + base = Reference::fromStackSlot(this, slotForFunction); + } + if (!receiver.isStackSlot()) { + receiver.storeOnStack(slotForThisObject); + receiver = Reference::fromStackSlot(this, slotForThisObject); + } + Instruction::CallWithReceiver call; + call.name = base.stackSlot(); + call.thisObject = receiver.stackSlot(); + call.argc = calldata.argc; + call.argv = calldata.argv; + bytecodeGenerator->addInstruction(call); } else { Q_ASSERT(base.isStackSlot()); Instruction::CallValue call; @@ -2157,6 +2175,8 @@ bool Codegen::visit(TaggedTemplate *ast) RegisterScope scope(this); + int functionObject = -1, thisObject = -1; + Reference base = expression(ast->base); if (hasError) return false; @@ -2167,6 +2187,10 @@ bool Codegen::visit(TaggedTemplate *ast) break; case Reference::Name: break; + case Reference::SuperProperty: + thisObject = bytecodeGenerator->newRegister(); + functionObject = bytecodeGenerator->newRegister(); + break; default: base = base.storeOnStack(); break; @@ -2181,7 +2205,7 @@ bool Codegen::visit(TaggedTemplate *ast) Q_ASSERT(calldata.argv == arrayTemp + 1); --calldata.argv; - handleCall(base, calldata); + handleCall(base, calldata, functionObject, thisObject); return false; } @@ -2450,7 +2474,7 @@ bool Codegen::visit(ObjectPattern *ast) for (; it; it = it->next) { PatternProperty *p = it->property; AST::ComputedPropertyName *cname = AST::cast<AST::ComputedPropertyName *>(p->name); - if (cname || p->type == PatternProperty::Getter || p->type == PatternProperty::Setter) + if (cname || p->type != PatternProperty::Literal) break; QString name = p->name->asString(); uint arrayIndex = QV4::String::toArrayIndex(name); @@ -2477,7 +2501,9 @@ bool Codegen::visit(ObjectPattern *ast) PatternProperty *p = it->property; AST::ComputedPropertyName *cname = AST::cast<AST::ComputedPropertyName *>(p->name); ObjectLiteralArgument argType = ObjectLiteralArgument::Value; - if (p->type == PatternProperty::Getter) + if (p->type == PatternProperty::Method) + argType = ObjectLiteralArgument::Method; + else if (p->type == PatternProperty::Getter) argType = ObjectLiteralArgument::Getter; else if (p->type == PatternProperty::Setter) argType = ObjectLiteralArgument::Setter; @@ -2508,10 +2534,20 @@ bool Codegen::visit(ObjectPattern *ast) push(Reference::fromAccumulator(this)); { RegisterScope innerScope(this); - Reference value = expression(p->initializer); - if (hasError) - return false; - value.loadInAccumulator(); + if (p->type != PatternProperty::Literal) { + // need to get the closure id for the method + FunctionExpression *f = p->initializer->asFunctionDefinition(); + Q_ASSERT(f); + int function = defineFunction(f->name.toString(), f, f->formals, f->body); + if (hasError) + return false; + Reference::fromConst(this, Encode(function)).loadInAccumulator(); + } else { + Reference value = expression(p->initializer); + if (hasError) + return false; + value.loadInAccumulator(); + } } push(Reference::fromAccumulator(this)); } @@ -3966,6 +4002,8 @@ Codegen::Reference Codegen::Reference::baseObject() const Q_UNREACHABLE(); } else if (type == Reference::Subscript) { return Reference::fromStackSlot(codegen, elementBase.stackSlot()); + } else if (type == Reference::SuperProperty) { + return Reference::fromStackSlot(codegen, CallData::This); } else { return Reference::fromConst(codegen, Encode::undefined()); } diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index adea8b3009..ae3e074e07 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -683,7 +683,7 @@ public: Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right); struct Arguments { int argc; int argv; bool hasSpread; }; Arguments pushArgs(AST::ArgumentList *args); - void handleCall(Reference &base, Arguments calldata); + void handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject); Arguments pushTemplateArgs(AST::TemplateLiteral *args); int createTemplateArray(AST::TemplateLiteral *t); diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index 4653b7217d..e70b246181 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -357,6 +357,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st d << dumpRegister(name, nFormals) << dumpArguments(argc, argv, nFormals); MOTH_END_INSTR(CallValue) + MOTH_BEGIN_INSTR(CallWithReceiver) + d << dumpRegister(name, nFormals) << dumpRegister(thisObject, nFormals) << dumpArguments(argc, argv, nFormals); + MOTH_END_INSTR(CallWithReceiver) + MOTH_BEGIN_INSTR(CallProperty) d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals); MOTH_END_INSTR(CallProperty) diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 7c2cbf717e..2690151a23 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -104,6 +104,7 @@ QT_BEGIN_NAMESPACE #define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 1, base) #define INSTR_StoreElement(op) INSTRUCTION(op, StoreElement, 2, base, index) #define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 3, name, argc, argv) +#define INSTR_CallWithReceiver(op) INSTRUCTION(op, CallWithReceiver, 4, name, thisObject, argc, argv) #define INSTR_CallProperty(op) INSTRUCTION(op, CallProperty, 4, name, base, argc, argv) #define INSTR_CallPropertyLookup(op) INSTRUCTION(op, CallPropertyLookup, 4, lookupIndex, base, argc, argv) #define INSTR_CallElement(op) INSTRUCTION(op, CallElement, 4, base, index, argc, argv) @@ -283,6 +284,7 @@ QT_BEGIN_NAMESPACE F(Mod) \ F(Sub) \ F(CallValue) \ + F(CallWithReceiver) \ F(CallProperty) \ F(CallPropertyLookup) \ F(CallElement) \ |