aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4bytecodehandler.cpp3
-rw-r--r--src/qml/compiler/qv4codegen.cpp32
-rw-r--r--src/qml/compiler/qv4codegen_p.h2
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp4
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
-rw-r--r--src/qml/jit/qv4baselinejit.cpp13
-rw-r--r--src/qml/jit/qv4baselinejit_p.h1
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp7
-rw-r--r--src/qml/jsruntime/qv4runtimeapi_p.h1
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp11
-rw-r--r--tests/auto/qml/ecmascripttests/TestExpectations4
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