Get rid of variableEnvironment

Found out that the variableEnv is only required
for two use cases: To expose the exception in the
catch statement, and to create temporary
environments for the with() statment. Both can be
better handled differently and don't require the
overhead of two environments.

Change-Id: I149e1fd7bdfc3267544b141b6f94e46e42cf641b
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
This commit is contained in:
Lars Knoll 2012-11-29 22:37:25 +01:00 committed by Erik Verbruggen
parent f00cf7cfae
commit f26d5c36cf
10 changed files with 33 additions and 37 deletions

View File

@ -50,16 +50,16 @@ FunctionState::~FunctionState()
VM::Value *FunctionState::argument(unsigned idx)
{
if (idx < _context->variableEnvironment->argumentCount)
return _context->variableEnvironment->arguments + idx;
if (idx < _context->lexicalEnvironment->argumentCount)
return _context->lexicalEnvironment->arguments + idx;
else
return 0;
}
VM::Value *FunctionState::local(unsigned idx)
{
if (idx < _context->variableEnvironment->varCount)
return _context->variableEnvironment->locals + idx;
if (idx < _context->lexicalEnvironment->varCount)
return _context->lexicalEnvironment->locals + idx;
else
return 0;
}

View File

@ -55,7 +55,7 @@ Value __qmljs_llvm_return(ExecutionContext */*ctx*/, Value *result)
Value *__qmljs_llvm_get_argument(ExecutionContext *ctx, int index)
{
return &ctx->variableEnvironment->arguments[index];
return &ctx->lexicalEnvironment->arguments[index];
}
void __qmljs_llvm_init_undefined(Value *result)

View File

@ -53,7 +53,7 @@ using namespace QQmlJS::Moth;
static inline VM::Value *tempValue(QQmlJS::VM::ExecutionContext *context, QVector<VM::Value> &stack, int index)
{
VM::DeclarativeEnvironment *varEnv = context->variableEnvironment;
VM::DeclarativeEnvironment *varEnv = context->lexicalEnvironment;
#ifdef DO_TRACE_INSTR
const char *kind;
@ -231,21 +231,21 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
}
}
#endif // DO_TRACE_INSTR
quint32 argStart = instr.args - context->variableEnvironment->varCount;
quint32 argStart = instr.args - context->lexicalEnvironment->varCount;
TRACE(Call, "value index = %d, argStart = %d, argc = %d, result temp index = %d", instr.destIndex, argStart, instr.argc, instr.targetTempIndex);
VM::Value *args = stack.data() + argStart;
TEMP(instr.targetTempIndex) = __qmljs_call_value(context, VM::Value::undefinedValue(), TEMP(instr.destIndex), args, instr.argc);
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallProperty)
quint32 argStart = instr.args - context->variableEnvironment->varCount;
quint32 argStart = instr.args - context->lexicalEnvironment->varCount;
VM::Value *args = stack.data() + argStart;
VM::Value base = TEMP(instr.baseTemp);
TEMP(instr.targetTempIndex) = __qmljs_call_property(context, base, instr.name, args, instr.argc);
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallBuiltin)
quint32 argStart = instr.args - context->variableEnvironment->varCount;
quint32 argStart = instr.args - context->lexicalEnvironment->varCount;
VM::Value *args = stack.data() + argStart;
void *buf;
switch (instr.builtin) {
@ -325,20 +325,20 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co
MOTH_END_INSTR(CallBuiltinDeleteValue)
MOTH_BEGIN_INSTR(CreateValue)
quint32 argStart = instr.args - context->variableEnvironment->varCount;
quint32 argStart = instr.args - context->lexicalEnvironment->varCount;
VM::Value *args = stack.data() + argStart;
TEMP(instr.targetTempIndex) = __qmljs_construct_value(context, TEMP(instr.func), args, instr.argc);
MOTH_END_INSTR(CreateValue)
MOTH_BEGIN_INSTR(CreateProperty)
quint32 argStart = instr.args - context->variableEnvironment->varCount;
quint32 argStart = instr.args - context->lexicalEnvironment->varCount;
VM::Value *args = stack.data() + argStart;
TEMP(instr.targetTempIndex) = __qmljs_construct_property(context, TEMP(instr.base), instr.name, args, instr.argc);
MOTH_END_INSTR(CreateProperty)
MOTH_BEGIN_INSTR(CreateActivationProperty)
TRACE(inline, "property name = %s, argc = %d", instr.name->toQString().toUtf8().constData(), instr.argc);
quint32 argStart = instr.args - context->variableEnvironment->varCount;
quint32 argStart = instr.args - context->lexicalEnvironment->varCount;
VM::Value *args = stack.data() + argStart;
TEMP(instr.targetTempIndex) = __qmljs_construct_activation_property(context, instr.name, args, instr.argc);
MOTH_END_INSTR(CreateActivationProperty)

View File

@ -158,7 +158,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
//
VM::Object *glo = newObject(/*rootContext*/);
globalObject = Value::fromObject(glo);
rootContext->variableEnvironment->activation = glo;
rootContext->lexicalEnvironment->activation = glo;
glo->__put__(rootContext, identifier(QStringLiteral("Object")), objectCtor);
glo->__put__(rootContext, identifier(QStringLiteral("String")), stringCtor);

View File

@ -215,9 +215,8 @@ void ExecutionContext::init(ExecutionEngine *eng)
{
engine = eng;
parent = 0;
variableEnvironment = new DeclarativeEnvironment;
variableEnvironment->init(eng);
lexicalEnvironment = variableEnvironment;
lexicalEnvironment = new DeclarativeEnvironment;
lexicalEnvironment->init(eng);
thisObject = Value::nullValue();
eng->exception = Value::undefinedValue();
}
@ -312,9 +311,8 @@ void ExecutionContext::initCallContext(ExecutionContext *parent, const Value tha
engine = parent->engine;
this->parent = parent;
variableEnvironment = new DeclarativeEnvironment;
variableEnvironment->init(f, args, argc);
lexicalEnvironment = variableEnvironment;
lexicalEnvironment = new DeclarativeEnvironment;
lexicalEnvironment->init(f, args, argc);
thisObject = that;
@ -325,13 +323,13 @@ void ExecutionContext::initCallContext(ExecutionContext *parent, const Value tha
void ExecutionContext::leaveCallContext()
{
// ## Should rather be handled by a the activation object having a ref to the environment
if (variableEnvironment->activation) {
delete[] variableEnvironment->locals;
variableEnvironment->locals = 0;
if (lexicalEnvironment->activation) {
delete[] lexicalEnvironment->locals;
lexicalEnvironment->locals = 0;
}
delete variableEnvironment;
variableEnvironment = 0;
delete lexicalEnvironment;
lexicalEnvironment = 0;
if (engine->debugger)
engine->debugger->justLeft(this);

View File

@ -112,7 +112,6 @@ struct ExecutionContext
ExecutionContext *parent;
// ### Should be a general environment
DeclarativeEnvironment *lexicalEnvironment;
DeclarativeEnvironment *variableEnvironment;
Value thisObject;
void init(ExecutionEngine *eng);
@ -135,11 +134,11 @@ struct ExecutionContext
void inplaceBitOp(Value value, String *name, BinOp op);
bool deleteProperty(String *name);
inline uint argumentCount() const { return variableEnvironment->argumentCount; }
inline uint argumentCount() const { return lexicalEnvironment->argumentCount; }
inline Value argument(unsigned int index = 0)
{
if (index < variableEnvironment->argumentCount)
return variableEnvironment->arguments[index];
if (index < lexicalEnvironment->argumentCount)
return lexicalEnvironment->arguments[index];
return Value::undefinedValue();
}
};

View File

@ -499,7 +499,6 @@ Value EvalFunction::call(ExecutionContext *context, Value /*thisObject*/, Value
ctx->parent = context;
ctx->thisObject = context->thisObject;
ctx->lexicalEnvironment = context->lexicalEnvironment;
ctx->variableEnvironment = context->variableEnvironment;
}
Value result = f->code(ctx, f->codeData);
@ -580,11 +579,11 @@ QQmlJS::IR::Function *EvalFunction::parseSource(QQmlJS::VM::ExecutionContext *ct
__qmljs_throw_type_error(ctx);
}
if (!ctx->variableEnvironment->activation)
ctx->variableEnvironment->activation = new QQmlJS::VM::Object();
if (!ctx->lexicalEnvironment->activation)
ctx->lexicalEnvironment->activation = new QQmlJS::VM::Object();
foreach (const QString *local, globalCode->locals) {
ctx->variableEnvironment->activation->__put__(ctx, *local, QQmlJS::VM::Value::undefinedValue());
ctx->lexicalEnvironment->activation->__put__(ctx, *local, QQmlJS::VM::Value::undefinedValue());
}
return globalCode;
}

View File

@ -500,7 +500,7 @@ struct FunctionObject: Object {
bool strictMode;
FunctionObject(ExecutionContext *scope)
: scope(scope->variableEnvironment)
: scope(scope->lexicalEnvironment)
, name(0)
, formalParameterList(0)
, formalParameterCount(0)

View File

@ -1960,8 +1960,8 @@ Value FunctionPrototype::method_call(ExecutionContext *ctx)
Value thisArg = ctx->argument(0);
QVector<Value> args(ctx->argumentCount() ? ctx->argumentCount() - 1 : 0);
if (ctx->argumentCount())
qCopy(ctx->variableEnvironment->arguments + 1,
ctx->variableEnvironment->arguments + ctx->argumentCount(), args.begin());
qCopy(ctx->lexicalEnvironment->arguments + 1,
ctx->lexicalEnvironment->arguments + ctx->argumentCount(), args.begin());
return __qmljs_call_value(ctx, thisArg, ctx->thisObject, args.data(), args.size());
}

View File

@ -191,11 +191,11 @@ InstructionSelection::Pointer InstructionSelection::loadTempAddress(RegisterID r
int32_t offset = 0;
if (t->index < 0) {
const int arg = -t->index - 1;
loadPtr(Address(ContextRegister, offsetof(ExecutionContext, variableEnvironment)), reg);
loadPtr(Address(ContextRegister, offsetof(ExecutionContext, lexicalEnvironment)), reg);
loadPtr(Address(reg, offsetof(DeclarativeEnvironment, arguments)), reg);
offset = arg * sizeof(Value);
} else if (t->index < _function->locals.size()) {
loadPtr(Address(ContextRegister, offsetof(ExecutionContext, variableEnvironment)), reg);
loadPtr(Address(ContextRegister, offsetof(ExecutionContext, lexicalEnvironment)), reg);
loadPtr(Address(reg, offsetof(DeclarativeEnvironment, locals)), reg);
offset = t->index * sizeof(Value);
} else {