aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-04-05 15:57:26 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2013-04-05 20:33:50 +0200
commit8da2e2af2634fbba0920a6296ad470c491ae00f7 (patch)
treef04bf3d2c7aac45c538ad1a79861bd12fa7a1715 /src
parentab4b03969c13f9ba4825848a2bcc4d86c98eb3a0 (diff)
Move activation out of ExecutionContext
Have an activation object (for now) in CallContext, and a global object in the GlobalContext. Change-Id: I02b1e6a2e976d914acfcc3d35cd8abda08dfd298 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/v4/qv4context.cpp187
-rw-r--r--src/v4/qv4context.h5
-rw-r--r--src/v4/qv4engine.cpp2
-rw-r--r--src/v4/qv4v8.cpp5
4 files changed, 113 insertions, 86 deletions
diff --git a/src/v4/qv4context.cpp b/src/v4/qv4context.cpp
index 0fac836858..1ce278860d 100644
--- a/src/v4/qv4context.cpp
+++ b/src/v4/qv4context.cpp
@@ -81,8 +81,20 @@ String *DiagnosticMessage::buildFullMessage(ExecutionContext *ctx) const
void ExecutionContext::createMutableBinding(String *name, bool deletable)
{
- if (!activation)
- activation = engine->newObject();
+
+ // find the right context to create the binding on
+ Object *activation = engine->globalObject.objectValue();
+ ExecutionContext *ctx = this;
+ while (ctx) {
+ if (ctx->type == Type_CallContext || ctx->type == Type_QmlContext) {
+ CallContext *c = static_cast<CallContext *>(ctx);
+ if (!c->activation)
+ c->activation = engine->newObject();
+ activation = c->activation;
+ break;
+ }
+ ctx = ctx->outer;
+ }
if (activation->__hasProperty__(this, name))
return;
@@ -95,31 +107,6 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
activation->__defineOwnProperty__(this, name, &desc);
}
-bool ExecutionContext::setMutableBinding(ExecutionContext *scope, String *name, const Value &value)
-{
- // ### throw if scope->strict is true, and it would change an immutable binding
- if (type == Type_CallContext) {
- CallContext *c = static_cast<CallContext *>(this);
- for (unsigned int i = 0; i < c->function->varCount; ++i)
- if (c->function->varList[i]->isEqualTo(name)) {
- c->locals[i] = value;
- return true;
- }
- for (int i = (int)c->function->formalParameterCount - 1; i >= 0; --i)
- if (c->function->formalParameterList[i]->isEqualTo(name)) {
- c->arguments[i] = value;
- return true;
- }
- }
-
- if (activation && (type == Type_QmlContext || activation->__hasProperty__(scope, name))) {
- activation->put(scope, name, value);
- return true;
- }
-
- return false;
-}
-
String * const *ExecutionContext::formals() const
{
return type == Type_CallContext ? static_cast<const CallContext *>(this)->function->formalParameterList : 0;
@@ -150,11 +137,11 @@ void GlobalContext::init(ExecutionEngine *eng)
engine = eng;
outer = 0;
lookups = 0;
+ global = 0;
// ### remove
arguments = 0;
argumentCount = 0;
- activation = 0;
}
void WithContext::init(ExecutionContext *p, Object *with)
@@ -172,7 +159,6 @@ void WithContext::init(ExecutionContext *p, Object *with)
// ### remove
arguments = 0;
argumentCount = 0;
- activation = 0;
}
void CatchContext::init(ExecutionContext *p, String *exceptionVarName, const Value &exceptionValue)
@@ -191,7 +177,6 @@ void CatchContext::init(ExecutionContext *p, String *exceptionVarName, const Val
// ### remove
arguments = 0;
argumentCount = 0;
- activation = 0;
}
void CallContext::initCallContext(ExecutionEngine *engine)
@@ -231,8 +216,14 @@ void CallContext::initCallContext(ExecutionEngine *engine)
ArgumentsObject *args = new (engine->memoryManager) ArgumentsObject(this, function->formalParameterCount, argc);
args->prototype = engine->objectPrototype;
Value arguments = Value::fromObject(args);
- createMutableBinding(engine->id_arguments, false);
- setMutableBinding(this, engine->id_arguments, arguments);
+ activation = engine->newObject();
+ PropertyDescriptor desc;
+ desc.value = Value::fromObject(args);
+ desc.type = PropertyDescriptor::Data;
+ desc.configurable = PropertyDescriptor::Disabled;
+ desc.writable = PropertyDescriptor::Enabled;
+ desc.enumerable = PropertyDescriptor::Enabled;
+ activation->__defineOwnProperty__(this, engine->id_arguments, &desc);
}
if (engine->debugger)
@@ -249,16 +240,11 @@ bool ExecutionContext::deleteProperty(String *name)
WithContext *w = static_cast<WithContext *>(ctx);
if (w->withObject->__hasProperty__(this, name))
return w->withObject->deleteProperty(this, name);
- } else {
- if (ctx->activation && ctx->activation->__hasProperty__(this, name))
- return ctx->activation->deleteProperty(this, name);
- }
- if (ctx->type == Type_CatchContext) {
+ } else if (ctx->type == Type_CatchContext) {
CatchContext *c = static_cast<CatchContext *>(ctx);
if (c->exceptionVarName->isEqualTo(name))
return false;
- }
- if (ctx->type == Type_CallContext) {
+ } else if (ctx->type == Type_CallContext || ctx->type == Type_QmlContext) {
CallContext *c = static_cast<CallContext *>(ctx);
FunctionObject *f = c->function;
if (f->needsActivation || hasWith) {
@@ -269,8 +255,15 @@ bool ExecutionContext::deleteProperty(String *name)
if (f->formalParameterList[i]->isEqualTo(name))
return false;
}
+ if (c->activation && c->activation->__hasProperty__(this, name))
+ return c->activation->deleteProperty(this, name);
+ } else if (ctx->type == Type_GlobalContext) {
+ GlobalContext *g = static_cast<GlobalContext *>(ctx);
+ if (g->global->__hasProperty__(this, name))
+ return g->global->deleteProperty(this, name);
}
}
+
if (strictMode)
throwSyntaxError(0);
return true;
@@ -294,24 +287,24 @@ void ExecutionContext::mark()
for (unsigned arg = 0, lastArg = argumentCount; arg < lastArg; ++arg)
arguments[arg].mark();
- if (type == Type_CallContext) {
+ if (type == Type_CallContext || type == Type_QmlContext) {
VM::CallContext *c = static_cast<CallContext *>(this);
for (unsigned local = 0, lastLocal = c->variableCount(); local < lastLocal; ++local)
c->locals[local].mark();
c->function->mark();
- }
-
- if (activation)
- activation->mark();
- if (type == Type_WithContext) {
+ if (c->activation)
+ c->activation->mark();
+ } else if (type == Type_WithContext) {
WithContext *w = static_cast<WithContext *>(this);
w->withObject->mark();
- }
- if (type == Type_CatchContext) {
+ } else if (type == Type_CatchContext) {
CatchContext *c = static_cast<CatchContext *>(this);
if (c->exceptionVarName)
c->exceptionVarName->mark();
c->exceptionValue.mark();
+ } else if (type == Type_GlobalContext) {
+ GlobalContext *g = static_cast<GlobalContext *>(this);
+ g->global->mark();
}
}
@@ -328,8 +321,28 @@ void ExecutionContext::setProperty(String *name, const Value& value)
static_cast<CatchContext *>(ctx)->exceptionValue = value;
return;
} else {
- if (ctx->setMutableBinding(this, name, value))
+ Object *activation = 0;
+ if (ctx->type == Type_CallContext || ctx->type == Type_QmlContext) {
+ CallContext *c = static_cast<CallContext *>(ctx);
+ for (unsigned int i = 0; i < c->function->varCount; ++i)
+ if (c->function->varList[i]->isEqualTo(name)) {
+ c->locals[i] = value;
+ return;
+ }
+ for (int i = (int)c->function->formalParameterCount - 1; i >= 0; --i)
+ if (c->function->formalParameterList[i]->isEqualTo(name)) {
+ c->arguments[i] = value;
+ return;
+ }
+ activation = c->activation;
+ } else if (ctx->type == Type_GlobalContext) {
+ activation = static_cast<GlobalContext *>(ctx)->global;
+ }
+
+ if (activation && (ctx->type == Type_QmlContext || activation->__hasProperty__(this, name))) {
+ activation->put(this, name, value);
return;
+ }
}
}
if (strictMode || name->isEqualTo(engine->id_this))
@@ -358,14 +371,14 @@ Value ExecutionContext::getProperty(String *name)
continue;
}
- if (ctx->type == Type_CatchContext) {
+ else if (ctx->type == Type_CatchContext) {
hasCatchScope = true;
CatchContext *c = static_cast<CatchContext *>(ctx);
if (c->exceptionVarName->isEqualTo(name))
return c->exceptionValue;
}
- if (ctx->type == Type_CallContext) {
+ else if (ctx->type == Type_CallContext || ctx->type == Type_QmlContext) {
VM::CallContext *c = static_cast<CallContext *>(ctx);
FunctionObject *f = c->function;
if (f->needsActivation || hasWith || hasCatchScope) {
@@ -376,20 +389,24 @@ Value ExecutionContext::getProperty(String *name)
if (f->formalParameterList[i]->isEqualTo(name))
return c->arguments[i];
}
+ if (c->activation) {
+ bool hasProperty = false;
+ Value v = c->activation->get(c, name, &hasProperty);
+ if (hasProperty)
+ return v;
+ }
+ if (f->function && f->function->isNamedExpression
+ && name->isEqualTo(f->function->name))
+ return Value::fromObject(c->function);
}
- if (ctx->activation) {
+
+ else if (ctx->type == Type_GlobalContext) {
+ GlobalContext *g = static_cast<GlobalContext *>(ctx);
bool hasProperty = false;
- Value v = ctx->activation->get(ctx, name, &hasProperty);
+ Value v = g->global->get(g, name, &hasProperty);
if (hasProperty)
return v;
}
- if (ctx->type == Type_CallContext) {
- CallContext *c = static_cast<CallContext *>(ctx);
- FunctionObject *f = c->function;
- if (f->function && f->function->isNamedExpression
- && name->isEqualTo(f->function->name))
- return Value::fromObject(c->function);
- }
}
throwReferenceError(Value::fromString(name));
return Value::undefinedValue();
@@ -416,14 +433,14 @@ Value ExecutionContext::getPropertyNoThrow(String *name)
continue;
}
- if (ctx->type == Type_CatchContext) {
+ else if (ctx->type == Type_CatchContext) {
hasCatchScope = true;
CatchContext *c = static_cast<CatchContext *>(ctx);
if (c->exceptionVarName->isEqualTo(name))
return c->exceptionValue;
}
- if (ctx->type == Type_CallContext) {
+ else if (ctx->type == Type_CallContext || ctx->type == Type_QmlContext) {
VM::CallContext *c = static_cast<CallContext *>(ctx);
FunctionObject *f = c->function;
if (f->needsActivation || hasWith || hasCatchScope) {
@@ -434,20 +451,24 @@ Value ExecutionContext::getPropertyNoThrow(String *name)
if (f->formalParameterList[i]->isEqualTo(name))
return c->arguments[i];
}
+ if (c->activation) {
+ bool hasProperty = false;
+ Value v = c->activation->get(c, name, &hasProperty);
+ if (hasProperty)
+ return v;
+ }
+ if (f->function && f->function->isNamedExpression
+ && name->isEqualTo(f->function->name))
+ return Value::fromObject(c->function);
}
- if (ctx->activation) {
+
+ else if (ctx->type == Type_GlobalContext) {
+ GlobalContext *g = static_cast<GlobalContext *>(ctx);
bool hasProperty = false;
- Value v = ctx->activation->get(ctx, name, &hasProperty);
+ Value v = g->global->get(g, name, &hasProperty);
if (hasProperty)
return v;
}
- if (ctx->type == Type_CallContext) {
- CallContext *c = static_cast<CallContext *>(ctx);
- FunctionObject *f = c->function;
- if (f->function && f->function->isNamedExpression
- && name->isEqualTo(f->function->name))
- return Value::fromObject(c->function);
- }
}
return Value::undefinedValue();
}
@@ -475,14 +496,14 @@ Value ExecutionContext::getPropertyAndBase(String *name, Object **base)
continue;
}
- if (ctx->type == Type_CatchContext) {
+ else if (ctx->type == Type_CatchContext) {
hasCatchScope = true;
CatchContext *c = static_cast<CatchContext *>(ctx);
if (c->exceptionVarName->isEqualTo(name))
return c->exceptionValue;
}
- if (ctx->type == Type_CallContext) {
+ else if (ctx->type == Type_CallContext || ctx->type == Type_QmlContext) {
VM::CallContext *c = static_cast<CallContext *>(ctx);
FunctionObject *f = c->function;
if (f->needsActivation || hasWith || hasCatchScope) {
@@ -493,20 +514,24 @@ Value ExecutionContext::getPropertyAndBase(String *name, Object **base)
if (f->formalParameterList[i]->isEqualTo(name))
return c->arguments[i];
}
+ if (c->activation) {
+ bool hasProperty = false;
+ Value v = c->activation->get(c, name, &hasProperty);
+ if (hasProperty)
+ return v;
+ }
+ if (f->function && f->function->isNamedExpression
+ && name->isEqualTo(f->function->name))
+ return Value::fromObject(c->function);
}
- if (ctx->activation) {
+
+ else if (ctx->type == Type_GlobalContext) {
+ GlobalContext *g = static_cast<GlobalContext *>(ctx);
bool hasProperty = false;
- Value v = ctx->activation->get(ctx, name, &hasProperty);
+ Value v = g->global->get(g, name, &hasProperty);
if (hasProperty)
return v;
}
- if (ctx->type == Type_CallContext) {
- CallContext *c = static_cast<CallContext *>(ctx);
- FunctionObject *f = c->function;
- if (f->function && f->function->isNamedExpression
- && name->isEqualTo(f->function->name))
- return Value::fromObject(c->function);
- }
}
throwReferenceError(Value::fromString(name));
return Value::undefinedValue();
diff --git a/src/v4/qv4context.h b/src/v4/qv4context.h
index 7e6156a6ff..b2d644d39c 100644
--- a/src/v4/qv4context.h
+++ b/src/v4/qv4context.h
@@ -100,7 +100,6 @@ struct ExecutionContext
// ### move to CallContext
Value *arguments;
unsigned int argumentCount;
- Object *activation;
String * const *formals() const;
unsigned int formalCount() const;
@@ -108,7 +107,6 @@ struct ExecutionContext
unsigned int variableCount() const;
void createMutableBinding(String *name, bool deletable);
- bool setMutableBinding(ExecutionContext *scope, String *name, const Value &value);
void Q_NORETURN throwError(const Value &value);
void Q_NORETURN throwError(const QString &message);
@@ -140,11 +138,14 @@ struct CallContext : public ExecutionContext
FunctionObject *function;
Value *locals;
+ Object *activation;
};
struct GlobalContext : public ExecutionContext
{
void init(ExecutionEngine *e);
+
+ Object *global;
};
struct CatchContext : public ExecutionContext
diff --git a/src/v4/qv4engine.cpp b/src/v4/qv4engine.cpp
index 105dd6ce59..f22e9a9161 100644
--- a/src/v4/qv4engine.cpp
+++ b/src/v4/qv4engine.cpp
@@ -199,7 +199,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
//
VM::Object *glo = newObject(/*rootContext*/);
globalObject = Value::fromObject(glo);
- rootContext->activation = glo;
+ rootContext->global = glo;
rootContext->thisObject = Value::fromObject(glo);
glo->defineDefaultProperty(rootContext, QStringLiteral("Object"), objectCtor);
diff --git a/src/v4/qv4v8.cpp b/src/v4/qv4v8.cpp
index 4adc706f77..835c825dfb 100644
--- a/src/v4/qv4v8.cpp
+++ b/src/v4/qv4v8.cpp
@@ -2108,10 +2108,11 @@ Local<Object> Context::GetCallingQmlGlobal()
while (ctx && ctx->outer != engine->rootContext)
ctx = ctx->outer;
- if (!ctx)
+ assert(ctx);
+ if (!ctx->type == ExecutionContext::Type_QmlContext)
return Local<Object>();
- return Local<Object>::New(Value::fromVmValue(VM::Value::fromObject(ctx->activation)));
+ return Local<Object>::New(Value::fromVmValue(VM::Value::fromObject(static_cast<CallContext *>(ctx)->activation)));
}
Local<Value> Context::GetCallingScriptData()