aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp12
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp14
-rw-r--r--src/qml/jsruntime/qv4global_p.h6
-rw-r--r--src/qml/jsruntime/qv4jscall_p.h18
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp3
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp9
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp93
7 files changed, 96 insertions, 59 deletions
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 5abfe3f8ae..0cf4515cc9 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -791,10 +791,10 @@ ReturnedValue ArrayPrototype::method_every(const BuiltinFunction *b, CallData *c
if (!callback)
THROW_TYPE_ERROR();
- JSCall jsCall(scope, callback, 3);
- jsCall->thisObject = callData->argument(1);
ScopedValue r(scope);
ScopedValue v(scope);
+ JSCall jsCall(scope, callback, 3);
+ jsCall->thisObject = callData->argument(1);
bool ok = true;
for (uint k = 0; ok && k < len; ++k) {
@@ -825,10 +825,10 @@ ReturnedValue ArrayPrototype::method_some(const BuiltinFunction *b, CallData *ca
if (!callback)
THROW_TYPE_ERROR();
- JSCall jsCall(scope, callback, 3);
- jsCall->thisObject = callData->argument(1);
ScopedValue v(scope);
ScopedValue result(scope);
+ JSCall jsCall(scope, callback, 3);
+ jsCall->thisObject = callData->argument(1);
for (uint k = 0; k < len; ++k) {
bool exists;
@@ -859,10 +859,10 @@ ReturnedValue ArrayPrototype::method_forEach(const BuiltinFunction *b, CallData
if (!callback)
THROW_TYPE_ERROR();
+ ScopedValue v(scope);
JSCall jsCall(scope, callback, 3);
jsCall->thisObject = callData->argument(1);
- ScopedValue v(scope);
for (uint k = 0; k < len; ++k) {
bool exists;
v = instance->getIndexed(k, &exists);
@@ -894,11 +894,11 @@ ReturnedValue ArrayPrototype::method_map(const BuiltinFunction *b, CallData *cal
a->arrayReserve(len);
a->setArrayLengthUnchecked(len);
+ ScopedValue v(scope);
ScopedValue mapped(scope);
JSCall jsCall(scope, callback, 3);
jsCall->thisObject = callData->argument(1);
- ScopedValue v(scope);
for (uint k = 0; k < len; ++k) {
bool exists;
v = instance->getIndexed(k, &exists);
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 36c5c4441a..716678d2f8 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -305,6 +305,7 @@ ReturnedValue FunctionPrototype::method_apply(const BuiltinFunction *b, CallData
return v4->throwTypeError();
} else {
callData->setArgc(0);
+ v4->jsStackTop = callData->args;
}
return o->call(callData);
@@ -312,16 +313,19 @@ ReturnedValue FunctionPrototype::method_apply(const BuiltinFunction *b, CallData
ReturnedValue FunctionPrototype::method_call(const BuiltinFunction *b, CallData *callData)
{
- if (!callData->thisObject.isFunctionObject()) {
- ExecutionEngine *e = b->engine();
- return e->throwTypeError();
- }
+ ExecutionEngine *engine = b->engine();
+ if (!callData->thisObject.isFunctionObject())
+ return engine->throwTypeError();
+
+ Q_ASSERT(engine->jsStackTop == callData->args + callData->argc());
+
callData->function = callData->thisObject;
callData->thisObject = callData->argc() ? callData->args[0] : Primitive::undefinedValue();
if (callData->argc()) {
callData->setArgc(callData->argc() - 1);
for (int i = 0, ei = callData->argc(); i < ei; ++i)
callData->args[i] = callData->args[i + 1];
+ --engine->jsStackTop;
}
return static_cast<FunctionObject &>(callData->function).call(callData);
}
@@ -354,12 +358,12 @@ ReturnedValue ScriptFunction::construct(const Managed *that, CallData *callData)
const ScriptFunction *f = static_cast<const ScriptFunction *>(that);
InternalClass *ic = f->classForConstructor();
+ callData->context = f->scope();
callData->thisObject = v4->memoryManager->allocObject<Object>(ic);
QV4::Function *v4Function = f->function();
Q_ASSERT(v4Function);
- callData->context = f->scope();
ReturnedValue result = v4Function->call(callData);
if (Q_UNLIKELY(v4->hasException))
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index 4c5e3c4e5e..6bdeda3313 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -248,12 +248,6 @@ struct IdentifierTable;
class RegExpCache;
class MultiplyWrappedQObjectMap;
-namespace Global {
- enum {
- ReservedArgumentCount = 6
- };
-}
-
enum PropertyFlag {
Attr_Data = 0,
Attr_Accessor = 0x1,
diff --git a/src/qml/jsruntime/qv4jscall_p.h b/src/qml/jsruntime/qv4jscall_p.h
index 8fd6119102..18dfdc102b 100644
--- a/src/qml/jsruntime/qv4jscall_p.h
+++ b/src/qml/jsruntime/qv4jscall_p.h
@@ -63,24 +63,36 @@ namespace QV4 {
struct JSCall {
JSCall(const Scope &scope, std::nullptr_t, int argc = 0)
{
- int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + qMax(argc , int(QV4::Global::ReservedArgumentCount));
+ int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + argc;
ptr = reinterpret_cast<CallData *>(scope.alloc(size));
ptr->setArgc(argc);
}
JSCall(const Scope &scope, const FunctionObject *function, int argc = 0)
{
- int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + qMax(argc , int(QV4::Global::ReservedArgumentCount));
+ int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + argc;
ptr = reinterpret_cast<CallData *>(scope.alloc(size));
ptr->setArgc(argc);
ptr->function = *function;
}
JSCall(const Scope &scope, Heap::FunctionObject *function, int argc = 0)
{
- int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + qMax(argc , int(QV4::Global::ReservedArgumentCount));
+ int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + argc;
ptr = reinterpret_cast<CallData *>(scope.alloc(size));
ptr->setArgc(argc);
ptr->function = function;
}
+ JSCall(const Scope &scope, Value *argv, int argc, Value *thisObject = 0)
+ {
+ int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + argc;
+ ptr = reinterpret_cast<CallData *>(scope.engine->jsStackTop);
+ scope.engine->jsStackTop += size;
+ ptr->function = Encode::undefined();
+ ptr->context = Encode::undefined();
+ ptr->accumulator = Encode::undefined();
+ ptr->thisObject = thisObject ? thisObject->asReturnedValue() : Encode::undefined();
+ ptr->setArgc(argc);
+ memcpy(ptr->args, argv, argc*sizeof(Value));
+ }
CallData *operator->() {
return ptr;
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 97b0c5259f..7bc2315610 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -426,10 +426,11 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(const Object *object, int typeH
qSwap(meth1, meth2);
Scope scope(engine);
+ ScopedValue conv(scope, object->get(meth1));
+
JSCall jsCall(scope, nullptr, 0);
jsCall->thisObject = *object;
- ScopedValue conv(scope, object->get(meth1));
if (FunctionObject *o = conv->as<FunctionObject>()) {
jsCall->function = o;
jsCall->accumulator = jsCall.call();
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 9e03913730..b1ce0b0115 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -405,14 +405,17 @@ ReturnedValue StringPrototype::method_match(const BuiltinFunction *b, CallData *
if (callData->thisObject.isNullOrUndefined())
return v4->throwTypeError();
- Scope scope(v4);
- callData->thisObject = callData->thisObject.toString(scope.engine);
+ callData->thisObject = callData->thisObject.toString(v4);
if (v4->hasException)
return Encode::undefined();
+ Q_ASSERT(v4->jsStackTop == callData->args + callData->argc());
if (!callData->argc())
callData->args[0] = Encode::undefined();
callData->setArgc(1);
+ v4->jsStackTop = callData->args + 1;
+
+ Scope scope(v4);
if (!callData->args[0].as<RegExpObject>()) {
// convert args[0] to a regexp
@@ -579,10 +582,10 @@ ReturnedValue StringPrototype::method_replace(const BuiltinFunction *b, CallData
ScopedFunctionObject searchCallback(scope, replaceValue);
if (!!searchCallback) {
result.reserve(string.length() + 10*numStringMatches);
+ ScopedValue entry(scope);
JSCall jsCall(scope, searchCallback, numCaptures + 2);
jsCall->thisObject = Primitive::undefinedValue();
int lastEnd = 0;
- ScopedValue entry(scope);
for (int i = 0; i < numStringMatches; ++i) {
for (int k = 0; k < numCaptures; ++k) {
int idx = (i * numCaptures + k) * 2;
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index b3b9842ba9..3e9f329c9a 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -54,6 +54,7 @@
#include <private/qv4regexpobject_p.h>
#include <private/qv4string_p.h>
#include <private/qv4profiling_p.h>
+#include <private/qv4jscall_p.h>
#include <private/qqmljavascriptexpression_p.h>
#include <iostream>
@@ -509,14 +510,15 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function)
Value *jsStackTop = engine->jsStackTop;
- Q_ASSERT(engine->jsStackTop >= callData->args + callData->argc() - 1);
- Value *stack = engine->jsStackTop;
- engine->jsStackTop += sizeof(CallData)/sizeof(Value) - 1 + qMax(callData->argc(), int(function->compiledFunction->nRegisters));
- memcpy(stack, callData, sizeof(CallData) - sizeof(Value) + callData->argc()*sizeof(Value));
- // clear out remaining arguments and local registers
- callData = reinterpret_cast<CallData *>(stack);
- for (Value *v = callData->args + callData->argc(); v < engine->jsStackTop; ++v)
- *v = Encode::undefined();
+ Q_ASSERT(engine->jsStackTop == callData->args + callData->argc());
+ Value *stack = reinterpret_cast<Value *>(callData);
+ int stackSpaceToAdd = int(function->compiledFunction->nRegisters) - callData->argc();
+ if (stackSpaceToAdd > 0) {
+ // clear out remaining arguments and local registers
+ for (int i = 0; i < stackSpaceToAdd; ++i)
+ engine->jsStackTop[i] = Encode::undefined();
+ engine->jsStackTop += stackSpaceToAdd;
+ }
CppStackFrame frame;
frame.parent = engine->currentStackFrame;
@@ -743,60 +745,78 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function)
MOTH_BEGIN_INSTR(CallValue)
STORE_IP();
STORE_ACC();
- QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData);
- Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop);
- acc = Runtime::method_callValue(engine, accumulator, cData);
+ {
+ Scope scope(engine);
+ JSCall cData(scope, stack + argv, argc);
+ Q_ASSERT(cData->args + cData->argc() == engine->jsStackTop);
+ acc = Runtime::method_callValue(engine, accumulator, cData);
+ }
CHECK_EXCEPTION;
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallProperty)
STORE_IP();
- QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData);
- Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop);
- cData->thisObject = STACK_VALUE(base);
- acc = Runtime::method_callProperty(engine, name, cData);
+ {
+ Scope scope(engine);
+ JSCall cData(scope, stack + argv, argc, stack + base);
+ Q_ASSERT(cData->args + cData->argc() == engine->jsStackTop);
+ acc = Runtime::method_callProperty(engine, name, cData);
+ }
CHECK_EXCEPTION;
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallPropertyLookup)
STORE_IP();
- QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData);
- Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop);
- cData->thisObject = STACK_VALUE(base);
- acc = Runtime::method_callPropertyLookup(engine, lookupIndex, cData);
+ {
+ Scope scope(engine);
+ JSCall cData(scope, stack + argv, argc, stack + base);
+ Q_ASSERT(cData->args + cData->argc() == engine->jsStackTop);
+ acc = Runtime::method_callPropertyLookup(engine, lookupIndex, cData);
+ }
CHECK_EXCEPTION;
MOTH_END_INSTR(CallPropertyLookup)
MOTH_BEGIN_INSTR(CallElement)
STORE_IP();
- QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData);
- Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop);
- cData->thisObject = STACK_VALUE(base);
- acc = Runtime::method_callElement(engine, STACK_VALUE(index), cData);
+ {
+ Scope scope(engine);
+ JSCall cData(scope, stack + argv, argc, stack + base);
+ Q_ASSERT(cData->args + cData->argc() == engine->jsStackTop);
+ acc = Runtime::method_callElement(engine, STACK_VALUE(index), cData);
+ }
CHECK_EXCEPTION;
MOTH_END_INSTR(CallElement)
MOTH_BEGIN_INSTR(CallName)
STORE_IP();
- QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData);
- Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop);
- acc = Runtime::method_callName(engine, name, cData);
+ {
+ Scope scope(engine);
+ JSCall cData(scope, stack + argv, argc);
+ Q_ASSERT(cData->args + cData->argc() == engine->jsStackTop);
+ acc = Runtime::method_callName(engine, name, cData);
+ }
CHECK_EXCEPTION;
MOTH_END_INSTR(CallName)
MOTH_BEGIN_INSTR(CallPossiblyDirectEval)
STORE_IP();
- QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData);
- Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop);
- acc = Runtime::method_callPossiblyDirectEval(engine, cData);
+ {
+ Scope scope(engine);
+ JSCall cData(scope, stack + argv, argc);
+ Q_ASSERT(cData->args + cData->argc() == engine->jsStackTop);
+ acc = Runtime::method_callPossiblyDirectEval(engine, cData);
+ }
CHECK_EXCEPTION;
MOTH_END_INSTR(CallPossiblyDirectEval)
MOTH_BEGIN_INSTR(CallGlobalLookup)
STORE_IP();
- QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData);
- Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop);
- acc = Runtime::method_callGlobalLookup(engine, index, cData);
+ {
+ Scope scope(engine);
+ JSCall cData(scope, stack + argv, argc);
+ Q_ASSERT(cData->args + cData->argc() == engine->jsStackTop);
+ acc = Runtime::method_callGlobalLookup(engine, index, cData);
+ }
CHECK_EXCEPTION;
MOTH_END_INSTR(CallGlobalLookup)
@@ -943,9 +963,12 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function)
MOTH_BEGIN_INSTR(Construct)
STORE_IP();
- QV4::CallData *cData = reinterpret_cast<QV4::CallData *>(stack + callData);
- Q_ASSERT(cData->args + cData->argc() <= engine->jsStackTop);
- acc = Runtime::method_construct(engine, STACK_VALUE(func), cData);
+ {
+ Scope scope(engine);
+ JSCall cData(scope, stack + argv, argc);
+ Q_ASSERT(cData->args + cData->argc() == engine->jsStackTop);
+ acc = Runtime::method_construct(engine, STACK_VALUE(func), cData);
+ }
CHECK_EXCEPTION;
MOTH_END_INSTR(Construct)