{
return new ArgumentsObject(ctx);
}
+
+void Context::initCallContext(ExecutionEngine *e, const Value *object, FunctionObject *f, Value *args, int argc)
+{
+ engine = e;
+ parent = f->scope;
+
+ if (f->needsActivation)
+ __qmljs_init_object(&activation, engine->newArgumentsObject(this));
+ else
+ __qmljs_init_null(&activation);
+
+ if (object)
+ thisObject = *object;
+ else
+ __qmljs_init_null(&thisObject);
+
+ formals = f->formalParameterList;
+ formalCount = f->formalParameterCount;
+ arguments = args;
+ argumentCount = argc;
+ if (argc && f->needsActivation) {
+ arguments = new Value[argc];
+ std::copy(args, args + argc, arguments);
+ }
+ vars = f->varList;
+ varCount = f->varCount;
+ locals = varCount ? new Value[varCount] : 0;
+ std::fill(locals, locals + varCount, Value::undefinedValue());
+}
+
+void Context::leaveCallContext(FunctionObject *f, Value *returnValue)
+{
+ if (returnValue)
+ __qmljs_copy(returnValue, &result);
+
+ if (! f->needsActivation) {
+ delete[] locals;
+ locals = 0;
+ }
+}
+
+void Context::initConstructorContext(ExecutionEngine *e, const Value *object, FunctionObject *f, Value *args, int argc)
+{
+ initCallContext(e, object, f, args, argc);
+ calledAsConstructor = true;
+}
+
+void Context::leaveConstructorContext(FunctionObject *f, Value *returnValue)
+{
+ assert(thisObject.is(OBJECT_TYPE));
+ result = thisObject;
+
+ Value proto;
+ if (f->get(engine->identifier(QLatin1String("prototype")), &proto)) {
+ if (proto.type == OBJECT_TYPE)
+ thisObject.objectValue->prototype = proto.objectValue;
+ }
+ leaveCallContext(f, returnValue);
+}
void __qmljs_set_property_boolean(Context *ctx, Value *object, String *name, bool number)
{
+ Q_UNUSED(ctx);
Value value;
__qmljs_init_boolean(&value, number);
object->objectValue->put(name, value, /*flag*/ 0);
void __qmljs_set_property_number(Context *ctx, Value *object, String *name, double number)
{
+ Q_UNUSED(ctx);
Value value;
__qmljs_init_number(&value, number);
object->objectValue->put(name, value, /*flag*/ 0);
void __qmljs_set_property_string(Context *ctx, Value *object, String *name, String *s)
{
+ Q_UNUSED(ctx);
Value value;
__qmljs_init_string(&value, s);
object->objectValue->put(name, value, /*flag*/ 0);
void __qmljs_set_activation_property(Context *ctx, String *name, Value *value)
{
- if (Value *prop = ctx->lookup(name))
- __qmljs_copy(prop, value);
- else
+ if (Value *prop = ctx->lookup(name)) {
+ *prop = *value;
+ } else
ctx->activation.objectValue->put(name, *value);
}
if (FunctionObject *f = func.objectValue->asFunctionObject()) {
Context k;
Context *ctx = f->needsActivation ? context->engine->newContext() : &k;
- ctx->init(context->engine);
- ctx->parent = f->scope;
- if (f->needsActivation)
- __qmljs_init_object(&ctx->activation, ctx->engine->newArgumentsObject(ctx));
- else
- __qmljs_init_null(&ctx->activation);
- ctx->thisObject = thisObject;
- ctx->formals = f->formalParameterList;
- ctx->formalCount = f->formalParameterCount;
- ctx->arguments = args;
- ctx->argumentCount = argc;
- if (argc && f->needsActivation) {
- ctx->arguments = new Value[argc];
- std::copy(args, args + argc, ctx->arguments);
- }
+ ctx->initCallContext(context->engine, &thisObject, f, args, argc);
f->call(ctx);
- if (result)
- __qmljs_copy(result, &ctx->result);
+ ctx->leaveCallContext(f, result);
} else {
assert(!"not a function");
}
void __qmljs_call_value(Context *context, Value *result, const Value *func, Value *args, int argc)
{
- Q_UNUSED(context);
-
if (func->type == OBJECT_TYPE) {
if (FunctionObject *f = func->objectValue->asFunctionObject()) {
Context k;
Context *ctx = f->needsActivation ? context->engine->newContext() : &k;
- ctx->init(context->engine);
- ctx->parent = f->scope;
- if (f->needsActivation)
- __qmljs_init_object(&ctx->activation, ctx->engine->newArgumentsObject(ctx));
- else
- __qmljs_init_null(&ctx->activation);
- __qmljs_init_null(&ctx->thisObject);
- ctx->formals = f->formalParameterList;
- ctx->formalCount = f->formalParameterCount;
- ctx->arguments = args;
- ctx->argumentCount = argc;
- if (argc && f->needsActivation) {
- ctx->arguments = new Value[argc];
- std::copy(args, args + argc, ctx->arguments);
- }
- ctx->vars = f->varList;
- ctx->varCount = f->varCount;
- ctx->locals = 0;
+ ctx->initCallContext(context->engine, 0, f, args, argc);
f->call(ctx);
- if (result)
- __qmljs_copy(result, &ctx->result);
+ ctx->leaveCallContext(f, result);
} else {
assert(!"not a function");
}
if (FunctionObject *f = func->objectValue->asFunctionObject()) {
Context k;
Context *ctx = f->needsActivation ? context->engine->newContext() : &k;
- ctx->init(context->engine);
- ctx->parent = f->scope;
- if (f->needsActivation)
- __qmljs_init_object(&ctx->activation, ctx->engine->newArgumentsObject(ctx));
- else
- __qmljs_init_null(&ctx->activation);
- __qmljs_init_null(&ctx->thisObject);
- ctx->formals = f->formalParameterList;
- ctx->formalCount = f->formalParameterCount;
- ctx->arguments = args;
- ctx->argumentCount = argc;
- if (argc && f->needsActivation) {
- ctx->arguments = new Value[argc];
- std::copy(args, args + argc, ctx->arguments);
- }
- ctx->calledAsConstructor = true;
+ ctx->initConstructorContext(context->engine, 0, f, args, argc);
f->construct(ctx);
- assert(ctx->thisObject.is(OBJECT_TYPE));
- ctx->result = ctx->thisObject;
- Value proto;
- if (f->get(ctx->engine->identifier(QLatin1String("prototype")), &proto)) { // ### `prototype' should be a unique symbol
- if (proto.type == OBJECT_TYPE)
- ctx->thisObject.objectValue->prototype = proto.objectValue;
- }
-
- if (result)
- __qmljs_copy(result, &ctx->thisObject);
+ ctx->leaveConstructorContext(f, result);
} else {
assert(!"not a function");
}
if (FunctionObject *f = func.objectValue->asFunctionObject()) {
Context k;
Context *ctx = f->needsActivation ? context->engine->newContext() : &k;
- ctx->init(context->engine);
- ctx->parent = f->scope;
- if (f->needsActivation)
- __qmljs_init_object(&ctx->activation, ctx->engine->newArgumentsObject(ctx));
- else
- __qmljs_init_null(&ctx->activation);
- ctx->thisObject = thisObject;
- ctx->formals = f->formalParameterList;
- ctx->formalCount = f->formalParameterCount;
- ctx->arguments = args;
- ctx->argumentCount = argc;
- if (argc && f->needsActivation) {
- ctx->arguments = new Value[argc];
- std::copy(args, args + argc, ctx->arguments);
- }
+ ctx->initConstructorContext(context->engine, 0, f, args, argc);
ctx->calledAsConstructor = true;
f->construct(ctx);
- assert(ctx->thisObject.is(OBJECT_TYPE));
-
- Value proto;
- if (f->get(ctx->engine->identifier(QLatin1String("prototype")), &proto)) { // ### `prototype' should be a unique symbol
- if (proto.type == OBJECT_TYPE)
- ctx->thisObject.objectValue->prototype = proto.objectValue;
- }
-
- if (result)
- __qmljs_copy(result, &ctx->thisObject);
+ ctx->leaveConstructorContext(f, result);
} else {
assert(!"not a function");
}
_function->code = (void (*)(VM::Context *)) _code;
_codePtr = _code;
- int locals = (_function->tempCount + _function->maxNumberOfArguments) * sizeof(Value);
+ int locals = (_function->tempCount - _function->locals.size() + _function->maxNumberOfArguments) * sizeof(Value);
locals = (locals + 15) & ~15;
amd64_push_reg(_codePtr, AMD64_RBP);
amd64_mov_reg_reg(_codePtr, AMD64_R14, AMD64_RDI, 8);
amd64_alu_reg_imm(_codePtr, X86_SUB, AMD64_RSP, locals);
- amd64_alu_reg_reg(_codePtr, X86_XOR, AMD64_R15, AMD64_R15);
-
- amd64_lea_membase(_codePtr, AMD64_RAX, AMD64_RSP, _function->maxNumberOfArguments * sizeof(Value));
- amd64_mov_membase_reg(_codePtr, AMD64_R14, offsetof(Context, locals), AMD64_RAX, 8);
-
-
foreach (IR::BasicBlock *block, _function->basicBlocks) {
_block = block;
_addrs[block] = _codePtr;
const int arg = -t->index - 1;
amd64_mov_reg_membase(_codePtr, reg, AMD64_R14, offsetof(Context, arguments), 8);
amd64_lea_membase(_codePtr, reg, reg, sizeof(Value) * arg);
+ } else if (t->index < _function->locals.size()) {
+ amd64_mov_reg_membase(_codePtr, reg, AMD64_R14, offsetof(Context, locals), 8);
+ amd64_lea_membase(_codePtr, reg, reg, sizeof(Value) * t->index);
} else {
- amd64_lea_membase(_codePtr, reg, AMD64_RSP, sizeof(Value) * (_function->maxNumberOfArguments + t->index));
+ amd64_lea_membase(_codePtr, reg, AMD64_RSP, sizeof(Value) * (_function->maxNumberOfArguments + t->index - _function->locals.size()));
}
}