aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h14
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp87
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h21
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp46
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h9
-rw-r--r--src/qml/jsruntime/qv4object.cpp3
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp134
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h20
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h5
-rw-r--r--src/qml/jsruntime/qv4sparsearray.cpp18
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp65
11 files changed, 232 insertions, 190 deletions
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 8164e439f0..68bc109eb4 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -289,7 +289,7 @@ union Instr
struct instr_callValue {
MOTH_INSTR_HEADER
quint32 argc;
- quint32 args;
+ quint32 callData;
Param dest;
Param result;
};
@@ -297,7 +297,7 @@ union Instr
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param base;
Param result;
};
@@ -306,14 +306,14 @@ union Instr
Param base;
Param index;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param result;
};
struct instr_callActivationProperty {
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param result;
};
struct instr_callBuiltinThrow {
@@ -460,7 +460,7 @@ union Instr
struct instr_createValue {
MOTH_INSTR_HEADER
quint32 argc;
- quint32 args;
+ quint32 callData;
Param func;
Param result;
};
@@ -468,7 +468,7 @@ union Instr
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param base;
Param result;
};
@@ -476,7 +476,7 @@ union Instr
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param result;
};
struct instr_jump {
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index a0462d927f..6850f413e0 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -700,21 +700,19 @@ QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
{
- int argc = prepareVariableArguments(args);
+ int argc = prepareCallData(args, 0);
if (useFastLookups && func->global) {
uint index = registerGlobalGetterLookup(*func->id);
generateFunctionCall(Assembler::Void, __qmljs_call_global_lookup,
Assembler::ContextRegister, Assembler::PointerToValue(result),
Assembler::TrustedImm32(index),
- baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ baseAddressForCallData());
} else {
generateFunctionCall(Assembler::Void, __qmljs_call_activation_property,
Assembler::ContextRegister, Assembler::PointerToValue(result),
Assembler::PointerToString(*func->id),
- baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ baseAddressForCallData());
}
}
@@ -985,11 +983,10 @@ void InstructionSelection::callValue(V4IR::Temp *value, V4IR::ExprList *args, V4
{
Q_ASSERT(value);
- int argc = prepareVariableArguments(args);
- V4IR::Temp* thisObject = 0;
+ int argc = prepareCallData(args, 0);
generateFunctionCall(Assembler::Void, __qmljs_call_value, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::PointerToValue(thisObject),
- Assembler::Reference(value), baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::Reference(value),
+ baseAddressForCallData());
}
void InstructionSelection::loadThisObject(V4IR::Temp *temp)
@@ -1342,19 +1339,19 @@ void InstructionSelection::callProperty(V4IR::Expr *base, const QString &name, V
{
assert(base != 0);
- int argc = prepareVariableArguments(args);
+ int argc = prepareCallData(args, base);
if (useFastLookups) {
uint index = registerGetterLookup(name);
generateFunctionCall(Assembler::Void, __qmljs_call_property_lookup,
Assembler::ContextRegister, Assembler::PointerToValue(result),
- Assembler::PointerToValue(base), Assembler::TrustedImm32(index),
- baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
- } else {
+ Assembler::TrustedImm32(index),
+ baseAddressForCallData());
+ } else
+ {
generateFunctionCall(Assembler::Void, __qmljs_call_property, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::PointerToValue(base), Assembler::PointerToString(name),
- baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::PointerToString(name),
+ baseAddressForCallData());
}
}
@@ -1363,11 +1360,10 @@ void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4
{
assert(base != 0);
- int argc = prepareVariableArguments(args);
+ int argc = prepareCallData(args, base);
generateFunctionCall(Assembler::Void, __qmljs_call_element, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::PointerToValue(base),
- Assembler::PointerToValue(index), baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::PointerToValue(index),
+ baseAddressForCallData());
}
void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
@@ -1568,35 +1564,41 @@ void InstructionSelection::convertTypeToSInt32(V4IR::Temp *source, V4IR::Temp *t
void InstructionSelection::constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result)
{
assert(func != 0);
+ int argc = prepareCallData(args, 0);
if (useFastLookups && func->global) {
- int argc = prepareVariableArguments(args);
uint index = registerGlobalGetterLookup(*func->id);
generateFunctionCall(Assembler::Void, __qmljs_construct_global_lookup,
Assembler::ContextRegister, Assembler::PointerToValue(result),
Assembler::TrustedImm32(index),
- baseAddressForCallArguments(),
- Assembler::TrustedImm32(argc));
+ baseAddressForCallData());
return;
}
- callRuntimeMethod(result, __qmljs_construct_activation_property, func, args);
+ generateFunctionCall(Assembler::Void, __qmljs_construct_activation_property,
+ Assembler::ContextRegister, Assembler::PointerToValue(result),
+ Assembler::PointerToString(*func->id),
+ baseAddressForCallData());
}
+
void InstructionSelection::constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result)
{
- int argc = prepareVariableArguments(args);
+ int argc = prepareCallData(args, 0);
generateFunctionCall(Assembler::Void, __qmljs_construct_property, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::Reference(base), Assembler::PointerToString(name), baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ Assembler::PointerToValue(result), Assembler::Reference(base), Assembler::PointerToString(name),
+ baseAddressForCallData());
}
void InstructionSelection::constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
{
assert(value != 0);
- int argc = prepareVariableArguments(args);
- generateFunctionCall(Assembler::Void, __qmljs_construct_value, Assembler::ContextRegister,
- Assembler::PointerToValue(result), Assembler::Reference(value), baseAddressForCallArguments(), Assembler::TrustedImm32(argc));
+ int argc = prepareCallData(args, 0);
+ generateFunctionCall(Assembler::Void, __qmljs_construct_value,
+ Assembler::ContextRegister, Assembler::PointerToValue(result),
+ Assembler::Reference(value),
+ baseAddressForCallData());
}
void InstructionSelection::visitJump(V4IR::Jump *s)
@@ -1783,6 +1785,33 @@ int InstructionSelection::prepareVariableArguments(V4IR::ExprList* args)
return argc;
}
+int InstructionSelection::prepareCallData(V4IR::ExprList* args, V4IR::Expr *thisObject)
+{
+ int argc = 0;
+ for (V4IR::ExprList *it = args; it; it = it->next) {
+ ++argc;
+ }
+
+ Pointer p = _as->stackLayout().callDataAddress(offsetof(CallData, tag));
+ _as->store32(Assembler::TrustedImm32(0), p);
+ p = _as->stackLayout().callDataAddress(offsetof(CallData, argc));
+ _as->store32(Assembler::TrustedImm32(argc), p);
+ p = _as->stackLayout().callDataAddress(offsetof(CallData, thisObject));
+ if (!thisObject)
+ _as->storeValue(QV4::Value::undefinedValue(), p);
+ else
+ _as->copyValue(p, thisObject);
+
+ int i = 0;
+ for (V4IR::ExprList *it = args; it; it = it->next, ++i) {
+ V4IR::Expr *arg = it->expr;
+ Q_ASSERT(arg != 0);
+ _as->copyValue(_as->stackLayout().argumentAddressForCall(i), arg);
+ }
+ return argc;
+}
+
+
void InstructionSelection::callRuntimeMethodImp(V4IR::Temp *result, const char* name, ActivationMethod method, V4IR::Expr *base, V4IR::ExprList *args)
{
V4IR::Name *baseName = base->asName();
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index 58d37208b9..1119c433a3 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -269,7 +269,7 @@ public:
public:
StackLayout(V4IR::Function *function, int maxArgCountForBuiltins)
: calleeSavedRegCount(Assembler::calleeSavedRegisterCount + 1)
- , maxOutgoingArgumentCount(qMax(function->maxNumberOfArguments, maxArgCountForBuiltins))
+ , maxOutgoingArgumentCount(function->maxNumberOfArguments)
, localCount(function->tempCount)
, savedConstCount(maxArgCountForBuiltins)
{
@@ -295,7 +295,7 @@ public:
+ RegisterSize; // saved StackFrameRegister
// space for the callee saved registers
- int frameSize = RegisterSize * calleeSavedRegisterCount;
+ int frameSize = RegisterSize * (calleeSavedRegisterCount + savedConstCount);
frameSize = WTF::roundUpToMultipleOf(StackAlignment, frameSize + stackSpaceAllocatedOtherwise);
frameSize -= stackSpaceAllocatedOtherwise;
@@ -305,7 +305,7 @@ public:
int calculateJSStackFrameSize() const
{
- const int locals = (maxOutgoingArgumentCount + localCount + savedConstCount) + 1;
+ const int locals = (localCount + sizeof(QV4::CallData)/sizeof(QV4::Value) - 1 + maxOutgoingArgumentCount) + 1;
int frameSize = locals * sizeof(QV4::Value);
return frameSize;
}
@@ -315,7 +315,7 @@ public:
Q_ASSERT(idx >= 0);
Q_ASSERT(idx < localCount);
- Pointer addr = argumentAddressForCall(0);
+ Pointer addr = callDataAddress(0);
addr.offset -= sizeof(QV4::Value) * (idx + 1);
return addr;
}
@@ -328,8 +328,11 @@ public:
Q_ASSERT(argument < maxOutgoingArgumentCount);
const int index = maxOutgoingArgumentCount - argument;
- return Pointer(Assembler::LocalsRegister,
- sizeof(QV4::Value) * (-index) - calleeSavedRegisterSpace());
+ return Pointer(Assembler::LocalsRegister, sizeof(QV4::Value) * (-index));
+ }
+
+ Pointer callDataAddress(int offset = 0) const {
+ return Pointer(Assembler::LocalsRegister, -(sizeof(QV4::CallData) + sizeof(QV4::Value) * (maxOutgoingArgumentCount - 1)) + offset);
}
Address savedRegPointer(int offset) const
@@ -1255,6 +1258,11 @@ protected:
return _as->stackLayout().argumentAddressForCall(0);
}
+ Pointer baseAddressForCallData()
+ {
+ return _as->stackLayout().callDataAddress();
+ }
+
virtual void constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result);
virtual void constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
virtual void constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
@@ -1329,6 +1337,7 @@ private:
_as->generateFunctionCallImp(t, isel_stringIfy(function), function, __VA_ARGS__)
int prepareVariableArguments(V4IR::ExprList* args);
+ int prepareCallData(V4IR::ExprList* args, V4IR::Expr *thisObject);
typedef void (*ActivationMethod)(QV4::ExecutionContext *, QV4::Value *result, QV4::String *name, QV4::Value *args, int argc);
void callRuntimeMethodImp(V4IR::Temp *result, const char* name, ActivationMethod method, V4IR::Expr *base, V4IR::ExprList *args);
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 3e7b1911e9..1546f19ec8 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -311,7 +311,8 @@ QV4::CompiledData::CompilationUnit *InstructionSelection::backendCompileStep()
void InstructionSelection::callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result)
{
Instruction::CallValue call;
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
call.dest = getParam(value);
call.result = getResultParam(result);
addInstruction(call);
@@ -324,7 +325,8 @@ void InstructionSelection::callProperty(V4IR::Expr *base, const QString &name, V
Instruction::CallProperty call;
call.base = getParam(base);
call.name = registerString(name);
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
call.result = getResultParam(result);
addInstruction(call);
}
@@ -336,7 +338,8 @@ void InstructionSelection::callSubscript(V4IR::Expr *base, V4IR::Expr *index, V4
Instruction::CallElement call;
call.base = getParam(base);
call.index = getParam(index);
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
call.result = getResultParam(result);
addInstruction(call);
}
@@ -359,7 +362,8 @@ void InstructionSelection::constructActivationProperty(V4IR::Name *func,
{
Instruction::CreateActivationProperty create;
create.name = registerString(*func->id);
- prepareCallArgs(args, create.argc, create.args);
+ prepareCallArgs(args, create.argc);
+ create.callData = callDataStart();
create.result = getResultParam(result);
addInstruction(create);
}
@@ -369,7 +373,8 @@ void InstructionSelection::constructProperty(V4IR::Temp *base, const QString &na
Instruction::CreateProperty create;
create.base = getParam(base);
create.name = registerString(name);
- prepareCallArgs(args, create.argc, create.args);
+ prepareCallArgs(args, create.argc);
+ create.callData = callDataStart();
create.result = getResultParam(result);
addInstruction(create);
}
@@ -378,7 +383,8 @@ void InstructionSelection::constructValue(V4IR::Temp *value, V4IR::ExprList *arg
{
Instruction::CreateValue create;
create.func = getParam(value);
- prepareCallArgs(args, create.argc, create.args);
+ prepareCallArgs(args, create.argc);
+ create.callData = callDataStart();
create.result = getResultParam(result);
addInstruction(create);
}
@@ -667,23 +673,15 @@ void InstructionSelection::inplaceMemberOp(V4IR::AluOp oper, V4IR::Temp *source,
addInstruction(imo);
}
-void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, quint32 &args)
+void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, quint32 *args)
{
- bool singleArgIsTemp = false;
- if (e && e->next == 0 && e->expr->asTemp()) {
- singleArgIsTemp = e->expr->asTemp()->kind == V4IR::Temp::VirtualRegister;
- }
-
- if (singleArgIsTemp) {
- // We pass single arguments as references to the stack, but only if it's not a local or an argument.
- argc = 1;
- args = getParam(e->expr).index;
- } else if (e) {
+ int argLocation = outgoingArgumentTempStart();
+ argc = 0;
+ if (args)
+ *args = argLocation;
+ if (e) {
// We need to move all the temps into the function arg array
- int argLocation = outgoingArgumentTempStart();
assert(argLocation >= 0);
- argc = 0;
- args = argLocation;
while (e) {
Instruction::MoveTemp move;
move.source = getParam(e->expr);
@@ -693,9 +691,6 @@ void InstructionSelection::prepareCallArgs(V4IR::ExprList *e, quint32 &argc, qui
++argc;
e = e->next;
}
- } else {
- argc = 0;
- args = 0;
}
}
@@ -763,7 +758,8 @@ void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *
{
Instruction::CallActivationProperty call;
call.name = registerString(*func->id);
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc);
+ call.callData = callDataStart();
call.result = getResultParam(result);
addInstruction(call);
}
@@ -980,7 +976,7 @@ void InstructionSelection::callBuiltinDefineProperty(V4IR::Temp *object, const Q
void InstructionSelection::callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args)
{
Instruction::CallBuiltinDefineArray call;
- prepareCallArgs(args, call.argc, call.args);
+ prepareCallArgs(args, call.argc, &call.args);
call.result = getResultParam(result);
addInstruction(call);
}
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index 43e792ccc7..826d559dbc 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -161,11 +161,12 @@ private:
}
void simpleMove(V4IR::Move *);
- void prepareCallArgs(V4IR::ExprList *, quint32 &, quint32 &);
+ void prepareCallArgs(V4IR::ExprList *, quint32 &, quint32 * = 0);
- int outgoingArgumentTempStart() const { return _function->tempCount; }
- int scratchTempIndex() const { return outgoingArgumentTempStart() + _function->maxNumberOfArguments; }
- int frameSize() const { return scratchTempIndex() + 1; }
+ int scratchTempIndex() const { return _function->tempCount; }
+ int callDataStart() const { return scratchTempIndex() + 1; }
+ int outgoingArgumentTempStart() const { return callDataStart() + offsetof(QV4::CallData, args)/sizeof(QV4::Value); }
+ int frameSize() const { return outgoingArgumentTempStart() + _function->maxNumberOfArguments; }
template <int Instr>
inline ptrdiff_t addInstruction(const InstrData<Instr> &data);
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index c99b48191a..fbee25e68b 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -1247,6 +1247,9 @@ void Object::arraySort(ExecutionContext *context, Object *thisObject, const Valu
}
}
+ if (!(comparefn.isUndefined() || comparefn.asObject()))
+ context->throwTypeError();
+
ArrayElementLessThan lessThan(context, thisObject, comparefn);
Property *begin = arrayData;
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 649baaf441..ca6540b920 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -720,8 +720,10 @@ Bool __qmljs_strict_equal(const Value &x, const Value &y)
}
-void __qmljs_call_global_lookup(ExecutionContext *context, Value *result, uint index, Value *args, int argc)
+void __qmljs_call_global_lookup(ExecutionContext *context, Value *result, uint index, CallData *callData)
{
+ Q_ASSERT(callData->thisObject.isUndefined());
+
Lookup *l = context->lookups + index;
Value v;
l->globalGetter(l, context, &v);
@@ -729,28 +731,28 @@ void __qmljs_call_global_lookup(ExecutionContext *context, Value *result, uint i
if (!o)
context->throwTypeError();
- Value thisObject = Value::undefinedValue();
-
if (o == context->engine->evalFunction && l->name->isEqualTo(context->engine->id_eval)) {
- Value res = static_cast<EvalFunction *>(o)->evalCall(thisObject, args, argc, true);
+ Value res = static_cast<EvalFunction *>(o)->evalCall(callData->thisObject, callData->args, callData->argc, true);
if (result)
*result = res;
return;
}
- ScopedCallData d(context->engine, argc);
- d->thisObject = thisObject;
- memcpy(d->args, args, argc*sizeof(Value));
- Value res = o->call(d);
+ Value res = o->call(*callData);
if (result)
*result = res;
}
-void __qmljs_call_activation_property(ExecutionContext *context, Value *result, String *name, Value *args, int argc)
+void __qmljs_call_activation_property(ExecutionContext *context, Value *result, String *name, CallData *callData)
{
+ Q_ASSERT(callData->thisObject.isUndefined());
+
Object *base;
Value func = context->getPropertyAndBase(name, &base);
+ if (base)
+ callData->thisObject = Value::fromObject(base);
+
FunctionObject *o = func.asFunctionObject();
if (!o) {
QString objectAsString = QStringLiteral("[null]");
@@ -760,106 +762,88 @@ void __qmljs_call_activation_property(ExecutionContext *context, Value *result,
context->throwTypeError(msg);
}
- Value thisObject = base ? Value::fromObject(base) : Value::undefinedValue();
-
if (o == context->engine->evalFunction && name->isEqualTo(context->engine->id_eval)) {
- Value res = static_cast<EvalFunction *>(o)->evalCall(thisObject, args, argc, true);
+ Value res = static_cast<EvalFunction *>(o)->evalCall(callData->thisObject, callData->args, callData->argc, true);
if (result)
*result = res;
return;
}
- ScopedCallData d(context->engine, argc);
- d->thisObject = thisObject;
- memcpy(d->args, args, argc*sizeof(Value));
- Value res = o->call(d);
+ Value res = o->call(*callData);
if (result)
*result = res;
}
-void __qmljs_call_property(ExecutionContext *context, Value *result, const Value &thatObject, String *name, Value *args, int argc)
+void __qmljs_call_property(ExecutionContext *context, Value *result, String *name, CallData *callData)
{
- Value thisObject = thatObject;
- Managed *baseObject = thisObject.asManaged();
+ Managed *baseObject = callData->thisObject.asManaged();
if (!baseObject) {
- if (thisObject.isNull() || thisObject.isUndefined()) {
- QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(thisObject.toQString());
+ if (callData->thisObject.isNullOrUndefined()) {
+ QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(callData->thisObject.toQString());
context->throwTypeError(message);
}
- baseObject = __qmljs_convert_to_object(context, thisObject);
- thisObject = Value::fromObject(static_cast<Object *>(baseObject));
+ baseObject = __qmljs_convert_to_object(context, callData->thisObject);
+ callData->thisObject = Value::fromObject(static_cast<Object *>(baseObject));
}
- Value func = baseObject->get(name);
- FunctionObject *o = func.asFunctionObject();
+ FunctionObject *o = baseObject->get(name).asFunctionObject();
if (!o) {
- QString error = QString("Property '%1' of object %2 is not a function").arg(name->toQString(), thisObject.toQString());
+ QString error = QString("Property '%1' of object %2 is not a function").arg(name->toQString(), callData->thisObject.toQString());
context->throwTypeError(error);
}
- ScopedCallData d(context->engine, argc);
- d->thisObject = thisObject;
- memcpy(d->args, args, argc*sizeof(Value));
- Value res = o->call(d);
+ Value res = o->call(*callData);
if (result)
*result = res;
}
-void __qmljs_call_property_lookup(ExecutionContext *context, Value *result, const Value &thisObject, uint index, Value *args, int argc)
+void __qmljs_call_property_lookup(ExecutionContext *context, Value *result, uint index, CallData *callData)
{
Value func;
Lookup *l = context->lookups + index;
- l->getter(l, &func, thisObject);
+ l->getter(l, &func, callData->thisObject);
Object *o = func.asObject();
if (!o)
context->throwTypeError();
- ScopedCallData d(context->engine, argc);
- d->thisObject = thisObject;
- memcpy(d->args, args, argc*sizeof(Value));
- Value res = o->call(d);
+ Value res = o->call(*callData);
if (result)
*result = res;
}
-void __qmljs_call_element(ExecutionContext *context, Value *result, const Value &that, const Value &index, Value *args, int argc)
+void __qmljs_call_element(ExecutionContext *context, Value *result, const Value &index, CallData *callData)
{
- Object *baseObject = that.toObject(context);
- Value thisObject = Value::fromObject(baseObject);
+ Object *baseObject = callData->thisObject.toObject(context);
+ callData->thisObject = Value::fromObject(baseObject);
- Value func = baseObject->get(index.toString(context));
- Object *o = func.asObject();
+ Object *o = baseObject->get(index.toString(context)).asObject();
if (!o)
context->throwTypeError();
- ScopedCallData d(context->engine, argc);
- d->thisObject = thisObject;
- memcpy(d->args, args, argc*sizeof(Value));
- Value res = o->call(d);
+ Value res = o->call(*callData);
if (result)
*result = res;
}
-void __qmljs_call_value(ExecutionContext *context, Value *result, const Value *thisObject, const Value &func, Value *args, int argc)
+void __qmljs_call_value(ExecutionContext *context, Value *result, const Value &func, CallData *callData)
{
Object *o = func.asObject();
if (!o)
context->throwTypeError();
- ScopedCallData d(context->engine, argc);
- d->thisObject = thisObject ? *thisObject : Value::undefinedValue();
- memcpy(d->args, args, argc*sizeof(Value));
- Value res = o->call(d);
+ Value res = o->call(*callData);
if (result)
*result = res;
}
-void __qmljs_construct_global_lookup(ExecutionContext *context, Value *result, uint index, Value *args, int argc)
+void __qmljs_construct_global_lookup(ExecutionContext *context, Value *result, uint index, CallData *callData)
{
+ Q_ASSERT(callData->thisObject.isUndefined());
+
Value func;
Lookup *l = context->lookups + index;
@@ -869,49 +853,47 @@ void __qmljs_construct_global_lookup(ExecutionContext *context, Value *result, u
if (!f)
context->throwTypeError();
- ScopedCallData callData(context->engine, argc);
- memcpy(callData->args, args, argc*sizeof(Value));
- Value res = f->construct(callData);
+ Value res = f->construct(*callData);
if (result)
*result = res;
}
-void __qmljs_construct_activation_property(ExecutionContext *context, Value *result, String *name, Value *args, int argc)
+void __qmljs_construct_activation_property(ExecutionContext *context, Value *result, String *name, CallData *callData)
{
Value func = context->getProperty(name);
- __qmljs_construct_value(context, result, func, args, argc);
+ Object *f = func.asObject();
+ if (!f)
+ context->throwTypeError();
+
+ Value res = f->construct(*callData);
+ if (result)
+ *result = res;
}
-void __qmljs_construct_value(ExecutionContext *context, Value *result, const Value &func, Value *args, int argc)
+void __qmljs_construct_value(ExecutionContext *context, Value *result, const Value &func, CallData *callData)
{
- if (Object *f = func.asObject()) {
- ScopedCallData d(context->engine, argc);
- memcpy(d->args, args, argc*sizeof(Value));
- Value res = f->construct(d);
- if (result)
- *result = res;
- return;
- }
+ Object *f = func.asObject();
+ if (!f)
+ context->throwTypeError();
- context->throwTypeError();
+ Value res = f->construct(*callData);
+ if (result)
+ *result = res;
}
-void __qmljs_construct_property(ExecutionContext *context, Value *result, const Value &base, String *name, Value *args, int argc)
+void __qmljs_construct_property(ExecutionContext *context, Value *result, const Value &base, String *name, CallData *callData)
{
Object *thisObject = base.toObject(context);
Value func = thisObject->get(name);
- if (Object *f = func.asObject()) {
- ScopedCallData d(context->engine, argc);
- memcpy(d->args, args, argc*sizeof(Value));
- Value res = f->construct(d);
- if (result)
- *result = res;
- return;
- }
+ Object *f = func.asObject();
+ if (!f)
+ context->throwTypeError();
- context->throwTypeError();
+ Value res = f->construct(*callData);
+ if (result)
+ *result = res;
}
void __qmljs_throw(ExecutionContext *context, const Value &value)
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index b38f833ad0..c52a79e2f5 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -91,15 +91,15 @@ struct ExecutionEngine;
struct InternalClass;
// context
-void __qmljs_call_activation_property(QV4::ExecutionContext *, QV4::Value *result, QV4::String *name, QV4::Value *args, int argc);
-void __qmljs_call_property(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &that, QV4::String *name, QV4::Value *args, int argc);
-void __qmljs_call_property_lookup(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &thisObject, uint index, QV4::Value *args, int argc);
-void __qmljs_call_element(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &that, const QV4::Value &index, QV4::Value *args, int argc);
-void __qmljs_call_value(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value *thisObject, const QV4::Value &func, QV4::Value *args, int argc);
+void __qmljs_call_activation_property(QV4::ExecutionContext *, QV4::Value *result, QV4::String *name, CallData *callData);
+void __qmljs_call_property(QV4::ExecutionContext *context, QV4::Value *result, QV4::String *name, CallData *callData);
+void __qmljs_call_property_lookup(ExecutionContext *context, Value *result, uint index, CallData *callData);
+void __qmljs_call_element(ExecutionContext *context, Value *result, const Value &index, CallData *callData);
+void __qmljs_call_value(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &func, CallData *callData);
-void __qmljs_construct_activation_property(QV4::ExecutionContext *, QV4::Value *result, QV4::String *name, QV4::Value *args, int argc);
-void __qmljs_construct_property(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, QV4::String *name, QV4::Value *args, int argc);
-void __qmljs_construct_value(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &func, QV4::Value *args, int argc);
+void __qmljs_construct_activation_property(QV4::ExecutionContext *, QV4::Value *result, QV4::String *name, CallData *callData);
+void __qmljs_construct_property(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &base, QV4::String *name, CallData *callData);
+void __qmljs_construct_value(QV4::ExecutionContext *context, QV4::Value *result, const QV4::Value &func, CallData *callData);
void __qmljs_builtin_typeof(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &val);
void __qmljs_builtin_typeof_name(QV4::ExecutionContext *context, QV4::Value* result, QV4::String *name);
@@ -145,8 +145,8 @@ void __qmljs_set_property(QV4::ExecutionContext *ctx, const QV4::Value &object,
void __qmljs_get_property(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value &object, QV4::String *name);
void __qmljs_get_activation_property(QV4::ExecutionContext *ctx, QV4::Value *result, QV4::String *name);
-void __qmljs_call_global_lookup(QV4::ExecutionContext *context, QV4::Value *result, uint index, QV4::Value *args, int argc);
-void __qmljs_construct_global_lookup(QV4::ExecutionContext *context, QV4::Value *result, uint index, QV4::Value *args, int argc);
+void __qmljs_call_global_lookup(QV4::ExecutionContext *context, QV4::Value *result, uint index, CallData *callData);
+void __qmljs_construct_global_lookup(QV4::ExecutionContext *context, QV4::Value *result, uint index, CallData *callData);
void __qmljs_get_element(QV4::ExecutionContext *ctx, QV4::Value *retval, const QV4::Value &object, const QV4::Value &index);
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 4218065768..5998fd92a1 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -140,11 +140,10 @@ struct ScopedCallData {
: engine(e)
// ### this check currently won't work because of exceptions
#if 0 //ndef QT_NO_DEBUG
- , size(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + 2)
+ , size(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + offsetof(QV4::CallData, args)/sizeof(QV4::Value))
#endif
{
- Q_ASSERT(sizeof(CallData) == 3*sizeof(Value));
- ptr = reinterpret_cast<CallData *>(e->stackPush(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + 2));
+ ptr = reinterpret_cast<CallData *>(e->stackPush(qMax(argc, (int)QV4::Global::ReservedArgumentCount) + offsetof(QV4::CallData, args)/sizeof(QV4::Value)));
ptr->tag = 0;
ptr->argc = argc;
}
diff --git a/src/qml/jsruntime/qv4sparsearray.cpp b/src/qml/jsruntime/qv4sparsearray.cpp
index 835a0d004f..5b720d2fef 100644
--- a/src/qml/jsruntime/qv4sparsearray.cpp
+++ b/src/qml/jsruntime/qv4sparsearray.cpp
@@ -43,6 +43,7 @@
#include "qv4runtime_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
+#include "qv4scopedvalue_p.h"
#include <stdlib.h>
#ifdef QT_QMAP_DEBUG
@@ -54,20 +55,21 @@ using namespace QV4;
bool ArrayElementLessThan::operator()(const Property &p1, const Property &p2) const
{
- Value v1 = p1.value;
- Value v2 = p2.value;
- if (v1.isUndefined())
+ if (p1.value.isUndefined())
return false;
- if (v2.isUndefined())
+ if (p2.value.isUndefined())
return true;
- if (!m_comparefn.isUndefined()) {
- Value args[] = { v1, v2 };
+ if (Object *o = m_comparefn.asObject()) {
+ ScopedCallData callData(o->engine(), 2);
+ callData->thisObject = Value::undefinedValue();
+ callData->args[0] = p1.value;
+ callData->args[1] = p2.value;
Value result = Value::undefinedValue();
- __qmljs_call_value(m_context, &result, /*thisObject*/0, m_comparefn, args, 2);
+ __qmljs_call_value(m_context, &result, m_comparefn, callData.ptr);
return result.toNumber() <= 0;
}
- return v1.toString(m_context)->toQString() < v2.toString(m_context)->toQString();
+ return p1.value.toString(m_context)->toQString() < p2.value.toString(m_context)->toQString();
}
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 10f09a8c82..5fef202cc6 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -45,7 +45,7 @@
#include <private/qv4debugging_p.h>
#include <private/qv4exception_p.h>
#include <private/qv4math_p.h>
-
+#include <private/qv4scopedvalue_p.h>
#include <iostream>
#include "qv4alloca_p.h"
@@ -320,29 +320,41 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
}
}
#endif // DO_TRACE_INSTR
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_call_value(context, VALUEPTR(instr.result), /*thisObject*/0, VALUE(instr.dest), args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_call_value(context, VALUEPTR(instr.result), VALUE(instr.dest), callData);
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallProperty)
TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(instr.name->toQString()), instr.args, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_call_property(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.name], args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ __qmljs_call_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], callData);
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallElement)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_call_element(context, VALUEPTR(instr.result), VALUE(instr.base), VALUE(instr.index), args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = VALUE(instr.base);
+ __qmljs_call_element(context, VALUEPTR(instr.result), VALUE(instr.index), callData);
MOTH_END_INSTR(CallElement)
MOTH_BEGIN_INSTR(CallActivationProperty)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
TRACE(args, "starting at %d, length %d", instr.args, instr.argc);
- QV4::Value *args = stack + instr.args;
- __qmljs_call_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_call_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], callData);
MOTH_END_INSTR(CallActivationProperty)
MOTH_BEGIN_INSTR(CallBuiltinThrow)
@@ -485,22 +497,31 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_END_INSTR(CallBuiltinSetupArgumentsObject)
MOTH_BEGIN_INSTR(CreateValue)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_construct_value(context, VALUEPTR(instr.result), VALUE(instr.func), args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_construct_value(context, VALUEPTR(instr.result), VALUE(instr.func), callData);
MOTH_END_INSTR(CreateValue)
MOTH_BEGIN_INSTR(CreateProperty)
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_construct_property(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.name], args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_construct_property(context, VALUEPTR(instr.result), VALUE(instr.base), runtimeStrings[instr.name], callData);
MOTH_END_INSTR(CreateProperty)
MOTH_BEGIN_INSTR(CreateActivationProperty)
TRACE(inline, "property name = %s, args = %d, argc = %d", instr.name->toQString().toUtf8().constData(), instr.args, instr.argc);
- Q_ASSERT(instr.args + instr.argc <= stackSize);
- QV4::Value *args = stack + instr.args;
- __qmljs_construct_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], args, instr.argc);
+ Q_ASSERT(instr.callData + instr.argc + offsetof(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
+ QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
+ callData->tag = 0;
+ callData->argc = instr.argc;
+ callData->thisObject = QV4::Value::undefinedValue();
+ __qmljs_construct_activation_property(context, VALUEPTR(instr.result), runtimeStrings[instr.name], callData);
MOTH_END_INSTR(CreateActivationProperty)
MOTH_BEGIN_INSTR(Jump)