diff options
Diffstat (limited to 'src/qml/jsruntime')
| -rw-r--r-- | src/qml/jsruntime/qv4arrayobject.cpp | 12 | ||||
| -rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 14 | ||||
| -rw-r--r-- | src/qml/jsruntime/qv4global_p.h | 6 | ||||
| -rw-r--r-- | src/qml/jsruntime/qv4jscall_p.h | 18 | ||||
| -rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 3 | ||||
| -rw-r--r-- | src/qml/jsruntime/qv4stringobject.cpp | 9 | ||||
| -rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 93 |
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) |
