Fix eval operating on incorrect runtime data
authorSimon Hausmann <simon.hausmann@digia.com>
Sat, 17 Aug 2013 10:08:21 +0000 (12:08 +0200)
committerLars Knoll <lars.knoll@digia.com>
Sun, 18 Aug 2013 10:28:24 +0000 (12:28 +0200)
Moved compilationUnit and compiledFunction into the context and set it also
during eval, along with the runtime strings.

Change-Id: I627b3bea0f7c38ad91bc5e8ee85e1484d08ed3f3
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/jsruntime/qv4context.cpp
src/qml/jsruntime/qv4context_p.h
src/qml/jsruntime/qv4globalobject.cpp
src/qml/jsruntime/qv4runtime.cpp
src/qml/jsruntime/qv4script.cpp
src/qml/jsruntime/qv4vme_moth.cpp

index 3c0dbe3..3067cf0 100644 (file)
@@ -139,6 +139,8 @@ void WithContext::initWithContext(ExecutionContext *p, Object *with)
     outer = p;
     lookups = p->lookups;
     runtimeStrings = p->runtimeStrings;
+    compilationUnit = p->compilationUnit;
+    compiledFunction = p->compiledFunction;
 
     withObject = with;
 }
@@ -151,6 +153,8 @@ void CatchContext::initCatchContext(ExecutionContext *p, String *exceptionVarNam
     outer = p;
     lookups = p->lookups;
     runtimeStrings = p->runtimeStrings;
+    compilationUnit = p->compilationUnit;
+    compiledFunction = p->compiledFunction;
 
     this->exceptionVarName = exceptionVarName;
     this->exceptionValue = exceptionValue;
@@ -175,8 +179,10 @@ void CallContext::initCallContext(ExecutionContext *parentContext, FunctionObjec
     activation = 0;
 
     if (function->function) {
-        lookups = function->function->compilationUnit->runtimeLookups;
-        runtimeStrings = function->function->compilationUnit->runtimeStrings;
+        compilationUnit = function->function->compilationUnit;
+        compiledFunction = function->function->compiledFunction;
+        lookups = compilationUnit->runtimeLookups;
+        runtimeStrings = compilationUnit->runtimeStrings;
     }
 
     uint argc = argumentCount;
@@ -223,8 +229,10 @@ void CallContext::initQmlContext(ExecutionContext *parentContext, Object *qml, F
 
     activation = qml;
 
-    lookups = function->function->compilationUnit->runtimeLookups;
-    runtimeStrings = function->function->compilationUnit->runtimeStrings;
+    compilationUnit = function->function->compilationUnit;
+    compiledFunction = function->function->compiledFunction;
+    lookups = compilationUnit->runtimeLookups;
+    runtimeStrings = compilationUnit->runtimeStrings;
 
     locals = (Value *)(this + 1);
     if (function->varCount)
@@ -610,20 +618,6 @@ void ExecutionContext::throwURIError(Value msg)
     throwError(Value::fromObject(engine->newURIErrorObject(msg)));
 }
 
-const Function *ExecutionContext::runtimeFunction() const
-{
-    const ExecutionContext *ctx = this;
-    if (ctx->type == Type_CatchContext)
-        ctx = ctx->parent;
-    if (ctx->type >= Type_CallContext) {
-        const QV4::FunctionObject *f = ctx->asCallContext()->function;
-        Q_ASSERT(f);
-        return f ? f->function : 0;
-    }
-    Q_ASSERT(ctx->type == Type_GlobalContext);
-    return engine->globalCode;
-}
-
 void SimpleCallContext::initSimpleCallContext(ExecutionEngine *engine)
 {
     initBaseContext(Type_SimpleCallContext, engine, engine->current);
index 7c11113..7690734 100644 (file)
@@ -53,6 +53,11 @@ struct ExecutionEngine;
 struct DeclarativeEnvironment;
 struct Lookup;
 
+namespace CompiledData {
+struct CompilationUnit;
+struct Function;
+};
+
 struct Q_QML_EXPORT DiagnosticMessage
 {
     enum { Error, Warning };
@@ -95,6 +100,8 @@ struct Q_QML_EXPORT ExecutionContext
     ExecutionContext *outer;
     Lookup *lookups;
     String **runtimeStrings;
+    CompiledData::CompilationUnit *compilationUnit;
+    const CompiledData::Function *compiledFunction;
     ExecutionContext *next; // used in the GC
 
     struct EvalCode
@@ -117,6 +124,8 @@ struct Q_QML_EXPORT ExecutionContext
         outer = 0;
         lookups = 0;
         runtimeStrings = 0;
+        compilationUnit = 0;
+        compiledFunction = 0;
         currentEvalCode = 0;
         interpreterInstructionPointer = 0;
     }
@@ -152,8 +161,6 @@ struct Q_QML_EXPORT ExecutionContext
 
     inline CallContext *asCallContext();
     inline const CallContext *asCallContext() const;
-
-    const Function *runtimeFunction() const;
 };
 
 struct SimpleCallContext : public ExecutionContext
index 49085b6..99a266b 100644 (file)
@@ -402,12 +402,22 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d
     bool cstrict = ctx->strictMode;
     ctx->strictMode = strictMode;
 
+    CompiledData::CompilationUnit * const oldCompilationUnit = ctx->compilationUnit;
+    const CompiledData::Function * const oldCompiledFunction = ctx->compiledFunction;
+    String ** const oldRuntimeStrings = ctx->runtimeStrings;
+    ctx->compilationUnit = function->compilationUnit;
+    ctx->compiledFunction = function->compiledFunction;
+    ctx->runtimeStrings = function->compilationUnit->runtimeStrings;
+
     Value result = Value::undefinedValue();
     try {
         result = function->code(ctx, function->codeData);
     } catch (Exception &ex) {
         ctx->strictMode = cstrict;
         ctx->currentEvalCode = evalCode.next;
+        ctx->compilationUnit = oldCompilationUnit;
+        ctx->compiledFunction = oldCompiledFunction;
+        ctx->runtimeStrings = oldRuntimeStrings;
         if (strictMode)
             ex.partiallyUnwindContext(parentContext);
         throw;
@@ -415,6 +425,9 @@ Value EvalFunction::evalCall(Value /*thisObject*/, Value *args, int argc, bool d
 
     ctx->strictMode = cstrict;
     ctx->currentEvalCode = evalCode.next;
+    ctx->compilationUnit = oldCompilationUnit;
+    ctx->compiledFunction = oldCompiledFunction;
+    ctx->runtimeStrings = oldRuntimeStrings;
 
     while (engine->current != parentContext)
         engine->popContext();
index d34e3d5..b262c5e 100644 (file)
@@ -120,8 +120,7 @@ void __qmljs_numberToString(QString *result, double num, int radix)
 
 void __qmljs_init_closure(ExecutionContext *ctx, Value *result, int functionId)
 {
-    const QV4::Function *runtimeFunction = ctx->runtimeFunction();
-    QV4::Function *clos = runtimeFunction->compilationUnit->runtimeFunctions[functionId];
+    QV4::Function *clos = ctx->compilationUnit->runtimeFunctions[functionId];
     assert(clos);
     *result = Value::fromObject(ctx->engine->newScriptFunction(ctx, clos));
 }
@@ -1183,9 +1182,7 @@ void __qmljs_builtin_define_getter_setter(ExecutionContext *ctx, const Value &ob
 
 void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value *args, int classId)
 {
-    const QV4::Function *runtimeFunction = ctx->runtimeFunction();
-    Q_ASSERT(runtimeFunction);
-    QV4::InternalClass *klass = runtimeFunction->compilationUnit->runtimeClasses[classId];
+    QV4::InternalClass *klass = ctx->compilationUnit->runtimeClasses[classId];
     Object *o = ctx->engine->newObject(klass);
 
     for (int i = 0; i < klass->size; ++i) {
@@ -1233,9 +1230,7 @@ void __qmljs_value_from_string(Value *result, String *string)
 
 void __qmljs_lookup_runtime_regexp(ExecutionContext *ctx, Value *result, int id)
 {
-    const QV4::Function *runtimeFunction = ctx->runtimeFunction();
-    Q_ASSERT(runtimeFunction);
-    *result = runtimeFunction->compilationUnit->runtimeRegularExpressions[id];
+    *result = ctx->compilationUnit->runtimeRegularExpressions[id];
 }
 
 } // namespace QV4
index 2997604..d801978 100644 (file)
@@ -202,10 +202,14 @@ Value Script::run()
 
         bool strict = scope->strictMode;
         Lookup *oldLookups = scope->lookups;
-        String **oldRuntimeStrings = scope->runtimeStrings;
+        CompiledData::CompilationUnit * const oldCompilationUnit = scope->compilationUnit;
+        const CompiledData::Function * const oldCompiledFunction = scope->compiledFunction;
+        String ** const oldRuntimeStrings = scope->runtimeStrings;
 
         scope->strictMode = vmFunction->isStrict();
         scope->lookups = vmFunction->compilationUnit->runtimeLookups;
+        scope->compilationUnit = vmFunction->compilationUnit;
+        scope->compiledFunction = vmFunction->compiledFunction;
         scope->runtimeStrings = vmFunction->compilationUnit->runtimeStrings;
 
         QV4::Value result;
@@ -214,10 +218,17 @@ Value Script::run()
         } catch (Exception &e) {
             scope->strictMode = strict;
             scope->lookups = oldLookups;
+            scope->compilationUnit = oldCompilationUnit;
+            scope->compiledFunction = oldCompiledFunction;
             scope->runtimeStrings = oldRuntimeStrings;
             throw;
         }
 
+        scope->lookups = oldLookups;
+        scope->compilationUnit = oldCompilationUnit;
+        scope->compiledFunction = oldCompiledFunction;
+        scope->runtimeStrings = oldRuntimeStrings;
+
         return result;
 
     } else {
index 133d72d..aea7bc6 100644 (file)
@@ -239,7 +239,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
     }
 #endif
 
-    QV4::String ** const runtimeStrings = context->runtimeFunction()->compilationUnit->runtimeStrings;
+    QV4::String ** const runtimeStrings = context->runtimeStrings;
     context->interpreterInstructionPointer = &code;
 
 #ifdef MOTH_THREADED_INTERPRETER
@@ -267,7 +267,7 @@ QV4::Value VME::run(QV4::ExecutionContext *context, const uchar *&code,
 
     MOTH_BEGIN_INSTR(LoadRegExp)
 //        TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData());
-        VALUE(instr.result) = context->runtimeFunction()->compilationUnit->runtimeRegularExpressions[instr.regExpId];
+        VALUE(instr.result) = context->compilationUnit->runtimeRegularExpressions[instr.regExpId];
     MOTH_END_INSTR(LoadRegExp)
 
     MOTH_BEGIN_INSTR(LoadClosure)