diff options
-rw-r--r-- | src/qml/compiler/qv4bytecodehandler.cpp | 3 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 32 | ||||
-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 | ||||
-rw-r--r-- | src/qml/jit/qv4baselinejit.cpp | 13 | ||||
-rw-r--r-- | src/qml/jit/qv4baselinejit_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 7 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtimeapi_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 11 | ||||
-rw-r--r-- | tests/auto/qml/ecmascripttests/TestExpectations | 4 |
11 files changed, 72 insertions, 8 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 b09deb1eaf..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; } @@ -3978,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) \ diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp index 36375461f9..9e9c586982 100644 --- a/src/qml/jit/qv4baselinejit.cpp +++ b/src/qml/jit/qv4baselinejit.cpp @@ -418,6 +418,19 @@ void BaselineJIT::generate_CallValue(int name, int argc, int argv) as->checkException(); } +void BaselineJIT::generate_CallWithReceiver(int name, int thisObject, int argc, int argv) +{ + STORE_IP(); + as->prepareCallWithArgCount(5); + as->passInt32AsArg(argc, 4); + as->passJSSlotAsArg(argv, 3); + as->passJSSlotAsArg(thisObject, 2); + as->passJSSlotAsArg(name, 1); + as->passEngineAsArg(0); + BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callWithReceiver, CallResultDestination::InAccumulator); + as->checkException(); +} + void BaselineJIT::generate_CallProperty(int name, int base, int argc, int argv) { STORE_IP(); diff --git a/src/qml/jit/qv4baselinejit_p.h b/src/qml/jit/qv4baselinejit_p.h index a3cb850fc1..972e9d07b7 100644 --- a/src/qml/jit/qv4baselinejit_p.h +++ b/src/qml/jit/qv4baselinejit_p.h @@ -120,6 +120,7 @@ public: void generate_Resume(int) override; void generate_CallValue(int name, int argc, int argv) override; + void generate_CallWithReceiver(int name, int thisObject, int argc, int argv) override; void generate_CallProperty(int name, int base, int argc, int argv) override; void generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv) override; void generate_CallElement(int base, int index, int argc, int argv) override; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 1a201a5d37..8064e64e93 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1310,6 +1310,13 @@ ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &fu return static_cast<const FunctionObject &>(func).call(&undef, argv, argc); } +ReturnedValue Runtime::method_callWithReceiver(ExecutionEngine *engine, const Value &func, const Value *thisObject, Value *argv, int argc) +{ + if (!func.isFunctionObject()) + return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow())); + return static_cast<const FunctionObject &>(func).call(thisObject, argv, argc); +} + ReturnedValue Runtime::method_callQmlScopeObjectProperty(ExecutionEngine *engine, Value *base, int propertyIndex, Value *argv, int argc) { diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h index 5dafeee6ce..62ba85efde 100644 --- a/src/qml/jsruntime/qv4runtimeapi_p.h +++ b/src/qml/jsruntime/qv4runtimeapi_p.h @@ -98,6 +98,7 @@ struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> { F(ReturnedValue, callPropertyLookup, (ExecutionEngine *engine, Value *base, uint index, Value *argv, int argc)) \ F(ReturnedValue, callElement, (ExecutionEngine *engine, Value *base, const Value &index, Value *argv, int argc)) \ F(ReturnedValue, callValue, (ExecutionEngine *engine, const Value &func, Value *argv, int argc)) \ + F(ReturnedValue, callWithReceiver, (ExecutionEngine *engine, const Value &func, const Value *thisObject, Value *argv, int argc)) \ F(ReturnedValue, callPossiblyDirectEval, (ExecutionEngine *engine, Value *argv, int argc)) \ F(ReturnedValue, callWithSpread, (ExecutionEngine *engine, const Value &func, const Value &thisObject, Value *argv, int argc)) \ \ diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index fd2328beaa..2d1f4c3e91 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -689,6 +689,17 @@ QV4::ReturnedValue VME::interpret(CppStackFrame *frame, ExecutionEngine *engine, CHECK_EXCEPTION; MOTH_END_INSTR(CallValue) + MOTH_BEGIN_INSTR(CallWithReceiver) + STORE_IP(); + Value func = STACK_VALUE(name); + if (Q_UNLIKELY(!func.isFunctionObject())) { + acc = engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow())); + goto handleUnwind; + } + acc = static_cast<const FunctionObject &>(func).call(stack + thisObject, stack + argv, argc); + CHECK_EXCEPTION; + MOTH_END_INSTR(CallWithReceiver) + MOTH_BEGIN_INSTR(CallProperty) STORE_IP(); acc = Runtime::method_callProperty(engine, stack + base, name, stack + argv, argc); diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations index cf132d1349..412fa191d5 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -934,15 +934,11 @@ language/expressions/prefix-increment/S11.4.4_A5_T3.js sloppyFails language/expressions/prefix-increment/S11.4.4_A5_T4.js sloppyFails language/expressions/prefix-increment/S11.4.4_A5_T5.js fails language/expressions/prefix-increment/S11.4.4_A6_T3.js fails -language/expressions/super/prop-dot-cls-ref-this.js fails language/expressions/super/prop-dot-cls-this-uninit.js fails language/expressions/super/prop-dot-cls-val-from-arrow.js fails -language/expressions/super/prop-dot-obj-ref-this.js fails language/expressions/super/prop-dot-obj-val-from-arrow.js fails -language/expressions/super/prop-expr-cls-ref-this.js fails language/expressions/super/prop-expr-cls-this-uninit.js fails language/expressions/super/prop-expr-cls-val-from-arrow.js fails -language/expressions/super/prop-expr-obj-ref-this.js fails language/expressions/super/prop-expr-obj-val-from-arrow.js fails language/expressions/super/realm.js fails language/expressions/tagged-template/cache-different-functions-same-site.js fails |