aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4codegen.cpp55
-rw-r--r--src/qml/compiler/qv4codegen_p.h3
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h2
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp23
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h16
-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
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)