struct instr_callValue {
MOTH_INSTR_HEADER
quint32 argc;
- quint32 args;
+ quint32 callData;
Param dest;
Param result;
};
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param base;
Param result;
};
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 {
struct instr_createValue {
MOTH_INSTR_HEADER
quint32 argc;
- quint32 args;
+ quint32 callData;
Param func;
Param result;
};
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param base;
Param result;
};
MOTH_INSTR_HEADER
int name;
quint32 argc;
- quint32 args;
+ quint32 callData;
Param result;
};
struct instr_jump {
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());
}
}
{
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)
{
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());
}
}
{
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)
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)
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();
public:
StackLayout(V4IR::Function *function, int maxArgCountForBuiltins)
: calleeSavedRegCount(Assembler::calleeSavedRegisterCount + 1)
- , maxOutgoingArgumentCount(qMax(function->maxNumberOfArguments, maxArgCountForBuiltins))
+ , maxOutgoingArgumentCount(function->maxNumberOfArguments)
, localCount(function->tempCount)
, savedConstCount(maxArgCountForBuiltins)
{
+ 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;
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;
}
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;
}
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
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);
_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);
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);
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);
}
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);
}
{
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);
}
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);
}
{
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);
}
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);
++argc;
e = e->next;
}
- } else {
- argc = 0;
- args = 0;
}
}
{
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);
}
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);
}
}
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);
}
}
+ if (!(comparefn.isUndefined() || comparefn.asObject()))
+ context->throwTypeError();
+
ArrayElementLessThan lessThan(context, thisObject, comparefn);
Property *begin = arrayData;
}
-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);
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]");
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;
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)
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);
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);
: 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;
}
#include "qv4runtime_p.h"
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
+#include "qv4scopedvalue_p.h"
#include <stdlib.h>
#ifdef QT_QMAP_DEBUG
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();
}
#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"
}
}
#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)
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)