diff options
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 55 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 3 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 23 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 16 | ||||
-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 |
12 files changed, 152 insertions, 102 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 706f211ae0..331132de3b 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1256,42 +1256,49 @@ bool Codegen::visit(CallExpression *ast) Instruction::CallPropertyLookup call; call.base = base.propertyBase.stackSlot(); call.lookupIndex = registerGetterLookup(base.propertyNameIndex); - call.callData = calldata; + call.argc = calldata.argc; + call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); } else { Instruction::CallProperty call; call.base = base.propertyBase.stackSlot(); call.name = base.propertyNameIndex; - call.callData = calldata; + call.argc = calldata.argc; + call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); } } else if (base.type == Reference::Subscript) { Instruction::CallElement call; call.base = base.elementBase; call.index = base.elementSubscript.stackSlot(); - call.callData = calldata; + call.argc = calldata.argc; + call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); } else if (base.type == Reference::Name) { if (base.name == QStringLiteral("eval")) { Instruction::CallPossiblyDirectEval call; - call.callData = calldata; + call.argc = calldata.argc; + call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); } else if (useFastLookups && base.global) { Instruction::CallGlobalLookup call; call.index = registerGlobalGetterLookup(base.nameAsIndex()); - call.callData = calldata; + call.argc = calldata.argc; + call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); } else { Instruction::CallName call; call.name = base.nameAsIndex(); - call.callData = calldata; + call.argc = calldata.argc; + call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); } } else { base.loadInAccumulator(); Instruction::CallValue call; - call.callData = calldata; + call.argc = calldata.argc; + call.argv = calldata.argv; bytecodeGenerator->addInstruction(call); } @@ -1299,21 +1306,16 @@ bool Codegen::visit(CallExpression *ast) return false; } -Moth::StackSlot Codegen::pushArgs(ArgumentList *args) +Codegen::Arguments Codegen::pushArgs(ArgumentList *args) { int argc = 0; for (ArgumentList *it = args; it; it = it->next) ++argc; - int calldata = bytecodeGenerator->newRegisterArray(sizeof(CallData)/sizeof(Value) - 1 + argc); -#ifndef QT_NO_DEBUG - (void) Reference::fromConst(this, QV4::Encode::undefined()).storeOnStack(calldata + CallData::Function); - (void) Reference::fromConst(this, QV4::Encode::undefined()).storeOnStack(calldata + CallData::Context); - (void) Reference::fromConst(this, QV4::Encode::undefined()).storeOnStack(calldata + CallData::Accumulator); - (void) Reference::fromConst(this, QV4::Encode::undefined()).storeOnStack(calldata + CallData::This); -#endif - (void) Reference::fromConst(this, QV4::Encode(argc)).storeOnStack(calldata + CallData::Argc); - Q_STATIC_ASSERT(sizeof(CallData) == 6 * sizeof(Value)); + if (!argc) + return { 0, 0 }; + + int calldata = bytecodeGenerator->newRegisterArray(argc); argc = 0; for (ArgumentList *it = args; it; it = it->next) { @@ -1321,11 +1323,16 @@ Moth::StackSlot Codegen::pushArgs(ArgumentList *args) Reference e = expression(it->expression); if (hasError) break; - (void) e.storeOnStack(calldata + sizeof(CallData)/sizeof(Value) - 1 + argc); + if (!argc && !it->next) { + // avoid copy for functions taking a single argument + if (e.isStackSlot()) + return { 1, e.stackSlot() }; + } + (void) e.storeOnStack(calldata + argc); ++argc; } - return Moth::StackSlot::createRegister(calldata); + return { argc, calldata }; } bool Codegen::visit(ConditionalExpression *ast) @@ -1581,11 +1588,10 @@ bool Codegen::visit(NewExpression *ast) //### Maybe create a ConstructA that takes an accumulator? base = base.storeOnStack(); - auto calldata = pushArgs(0); - Instruction::Construct create; create.func = base.stackSlot(); - create.callData = calldata; + create.argc = 0; + create.argv = 0; bytecodeGenerator->addInstruction(create); _expr.setResult(Reference::fromAccumulator(this)); return false; @@ -1609,7 +1615,8 @@ bool Codegen::visit(NewMemberExpression *ast) Instruction::Construct create; create.func = base.stackSlot(); - create.callData = calldata; + create.argc = calldata.argc; + create.argv = calldata.argv; bytecodeGenerator->addInstruction(create); _expr.setResult(Reference::fromAccumulator(this)); return false; @@ -2024,8 +2031,6 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, _context->functionIndex = _module->functions.count() - 1; _context->hasDirectEval |= (_context->compilationMode == EvalCode || _context->compilationMode == GlobalCode || _module->debugMode); // Conditional breakpoints are like eval in the function - // ### still needed? - _context->maxNumberOfArguments = qMax(_context->maxNumberOfArguments, (int)QV4::Global::ReservedArgumentCount); BytecodeGenerator bytecode(_context->line, _module->debugMode); BytecodeGenerator *savedBytecodeGenerator; diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 881fa08ff8..89c887d46d 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -624,7 +624,8 @@ public: Reference binopHelper(QSOperator::Op oper, Reference &left, Reference &right); Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right); - Moth::StackSlot pushArgs(AST::ArgumentList *args); + struct Arguments { int argc; int argv; }; + Arguments pushArgs(AST::ArgumentList *args); void setUseFastLookups(bool b) { useFastLookups = b; } diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h index f35125e719..0b7ac1fb0c 100644 --- a/src/qml/compiler/qv4compilercontext_p.h +++ b/src/qml/compiler/qv4compilercontext_p.h @@ -216,7 +216,7 @@ struct Context { bool canUseSimpleCall() const { return nestedContexts.isEmpty() && - locals.isEmpty() && arguments.size() <= QV4::Global::ReservedArgumentCount && + locals.isEmpty() && !hasTry && !hasWith && usesArgumentsObject == ArgumentsObjectNotUsed && !hasDirectEval; } diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index ea19233a3d..9cfde99e6b 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -159,6 +159,13 @@ QString dumpRegister(int reg, int nFormals) } +QString dumpArguments(int argc, int argv, int nFormals) +{ + if (!argc) + return QStringLiteral("()"); + return QStringLiteral("(") + dumpRegister(argv, nFormals) + QStringLiteral(", ") + QString::number(argc) + QStringLiteral(")"); +} + void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*startLine*/, const QVector<CompiledData::CodeOffsetToLine> &lineNumberMapping) { @@ -335,31 +342,31 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st MOTH_END_INSTR(LoadIdObject) MOTH_BEGIN_INSTR(CallValue) - d << "(" << dumpRegister(callData, nFormals) << ")"; + d << dumpArguments(argc, argv, nFormals); MOTH_END_INSTR(CallValue) MOTH_BEGIN_INSTR(CallProperty) - d << dumpRegister(base, nFormals) << "." << name << "(" << dumpRegister(callData, nFormals) << ")"; + d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals); MOTH_END_INSTR(CallProperty) MOTH_BEGIN_INSTR(CallPropertyLookup) - d << dumpRegister(base, nFormals) << "." << lookupIndex << "(" << dumpRegister(callData, nFormals) << ")"; + d << dumpRegister(base, nFormals) << "." << lookupIndex << dumpArguments(argc, argv, nFormals); MOTH_END_INSTR(CallPropertyLookup) MOTH_BEGIN_INSTR(CallElement) - d << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]" << "(" << dumpRegister(callData, nFormals) << ")"; + d << dumpRegister(base, nFormals) << "[" << dumpRegister(index, nFormals) << "]" << dumpArguments(argc, argv, nFormals); MOTH_END_INSTR(CallElement) MOTH_BEGIN_INSTR(CallName) - d << name << "(" << dumpRegister(callData, nFormals) << ")"; + d << name << dumpArguments(argc, argv, nFormals); MOTH_END_INSTR(CallName) MOTH_BEGIN_INSTR(CallPossiblyDirectEval) - d << "(" << dumpRegister(callData, nFormals) << ")"; + d << dumpArguments(argc, argv, nFormals); MOTH_END_INSTR(CallPossiblyDirectEval) MOTH_BEGIN_INSTR(CallGlobalLookup) - d << index << "(" << dumpRegister(callData, nFormals) << ")"; + d << index << dumpArguments(argc, argv, nFormals); MOTH_END_INSTR(CallGlobalLookup) MOTH_BEGIN_INSTR(SetExceptionHandler) @@ -443,7 +450,7 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st MOTH_END_INSTR(ConvertThisToObject) MOTH_BEGIN_INSTR(Construct) - d << "new" << dumpRegister(func, nFormals) << "(" << dumpRegister(callData, nFormals) << ")"; + d << "new" << dumpRegister(func, nFormals) << dumpArguments(argc, argv, nFormals); MOTH_END_INSTR(Construct) MOTH_BEGIN_INSTR(Jump) diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index d81762f25b..58d3edf2c4 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -109,13 +109,13 @@ QT_BEGIN_NAMESPACE #define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 2, base, index) #define INSTR_LoadElementA(op) INSTRUCTION(op, LoadElementA, 1, base) #define INSTR_StoreElement(op) INSTRUCTION(op, StoreElement, 2, base, index) -#define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 1, callData) -#define INSTR_CallProperty(op) INSTRUCTION(op, CallProperty, 3, name, callData, base) -#define INSTR_CallPropertyLookup(op) INSTRUCTION(op, CallPropertyLookup, 3, lookupIndex, callData, base) -#define INSTR_CallElement(op) INSTRUCTION(op, CallElement, 3, base, index, callData) -#define INSTR_CallName(op) INSTRUCTION(op, CallName, 2, name, callData) -#define INSTR_CallPossiblyDirectEval(op) INSTRUCTION(op, CallPossiblyDirectEval, 1, callData) -#define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 2, index, callData) +#define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 2, 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) +#define INSTR_CallName(op) INSTRUCTION(op, CallName, 3, name, argc, argv) +#define INSTR_CallPossiblyDirectEval(op) INSTRUCTION(op, CallPossiblyDirectEval, 2, argc, argv) +#define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 3, index, argc, argv) #define INSTR_SetExceptionHandler(op) INSTRUCTION(op, SetExceptionHandler, 1, offset) #define INSTR_ThrowException(op) INSTRUCTION(op, ThrowException, 0) #define INSTR_GetException(op) INSTRUCTION(op, GetException, 0) @@ -138,7 +138,7 @@ QT_BEGIN_NAMESPACE #define INSTR_CreateMappedArgumentsObject(op) INSTRUCTION(op, CreateMappedArgumentsObject, 0) #define INSTR_CreateUnmappedArgumentsObject(op) INSTRUCTION(op, CreateUnmappedArgumentsObject, 0) #define INSTR_ConvertThisToObject(op) INSTRUCTION(op, ConvertThisToObject, 0) -#define INSTR_Construct(op) INSTRUCTION(op, Construct, 2, callData, func) +#define INSTR_Construct(op) INSTRUCTION(op, Construct, 3, func, argc, argv) #define INSTR_Jump(op) INSTRUCTION(op, Jump, 1, offset) #define INSTR_JumpTrue(op) INSTRUCTION(op, JumpTrue, 1, offset) #define INSTR_JumpFalse(op) INSTRUCTION(op, JumpFalse, 1, offset) 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) |