Get rid of 'Value ExecutionEngine::exception' member
authorSimon Hausmann <simon.hausmann@digia.com>
Wed, 6 Mar 2013 19:04:39 +0000 (20:04 +0100)
committerLars Knoll <lars.knoll@digia.com>
Wed, 6 Mar 2013 21:19:32 +0000 (22:19 +0100)
Instead the JS exception value is now part of the C++ Exception object.

This also allows getting rid of some run-time functions.

Change-Id: I43ff773cacd5e925ba96601f3633ccf3b62273be
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/v4/llvm_runtime.cpp
src/v4/moth/qv4vme_moth.cpp
src/v4/qmljs_engine.cpp
src/v4/qmljs_engine.h
src/v4/qmljs_environment.cpp
src/v4/qmljs_environment.h
src/v4/qmljs_runtime.cpp
src/v4/qmljs_runtime.h
src/v4/qv4isel_masm.cpp
tools/v4/main.cpp

index c3aede7..c0c5415 100644 (file)
@@ -474,23 +474,11 @@ void __qmljs_llvm_throw(ExecutionContext *context, Value *value)
     __qmljs_throw(context, *value);
 }
 
-void __qmljs_llvm_create_exception_handler(ExecutionContext *context, Value *result)
-{
-    // ### FIXME.
-    __qmljs_create_exception_handler(context);
-    *result = Value::undefinedValue();
-}
-
 void __qmljs_llvm_delete_exception_handler(ExecutionContext *context)
 {
     // ### FIXME.
 }
 
-void __qmljs_llvm_get_exception(ExecutionContext *context, Value *result)
-{
-    __qmljs_get_exception(context, result);
-}
-
 void __qmljs_llvm_foreach_iterator_object(ExecutionContext *context, Value *result, Value *in)
 {
     __qmljs_foreach_iterator_object(context, result, *in);
index a20fdbf..6487efc 100644 (file)
@@ -259,23 +259,23 @@ VM::Value VME::run(QQmlJS::VM::ExecutionContext *context, const uchar *&code,
     MOTH_END_INSTR(CallBuiltinThrow)
 
     MOTH_BEGIN_INSTR(EnterTry)
-        __qmljs_create_exception_handler(context);
+        VALUE(instr.exceptionVar) = VM::Value::undefinedValue();
         try {
             const uchar *tryCode = ((uchar *)&instr.tryOffset) + instr.tryOffset;
             run(context, tryCode, stack, stackSize);
             code = tryCode;
         } catch (VM::Exception &ex) {
             ex.accept(context);
-            __qmljs_get_exception(context, VALUEPTR(instr.exceptionVar));
+            VALUE(instr.exceptionVar) = ex.value();
             try {
-                VM::ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(instr.exceptionVarName, context);
+                VM::ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(instr.exceptionVarName, ex.value(), context);
                 const uchar *catchCode = ((uchar *)&instr.catchOffset) + instr.catchOffset;
                 run(catchContext, catchCode, stack, stackSize);
                 code = catchCode;
                 context = __qmljs_builtin_pop_scope(catchContext);
             } catch (VM::Exception &ex) {
                 ex.accept(context);
-                __qmljs_get_exception(context, VALUEPTR(instr.exceptionVar));
+                VALUE(instr.exceptionVar) = ex.value();
                 const uchar *catchCode = ((uchar *)&instr.catchOffset) + instr.catchOffset;
                 run(context, catchCode, stack, stackSize);
                 code = catchCode;
index bf482ca..900190e 100644 (file)
@@ -69,7 +69,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
     , debugger(0)
     , globalObject(Value::nullValue())
     , globalCode(0)
-    , exception(Value::nullValue())
     , externalResourceComparison(0)
 {
     MemoryManager::GCBlocker gcBlocker(memoryManager);
@@ -431,8 +430,6 @@ void ExecutionEngine::markObjects()
     if (globalCode)
         globalCode->mark();
 
-    exception.mark();
-
     for (int i = 0; i < argumentsAccessors.size(); ++i) {
         const PropertyDescriptor &pd = argumentsAccessors.at(i);
         pd.get->mark();
index 39330fa..056e5bb 100644 (file)
@@ -180,8 +180,6 @@ struct Q_V4_EXPORT ExecutionEngine
     String *id_set;
     String *id_eval;
 
-    Value exception;
-
     QVector<Function *> functions;
 
     ExternalResourceComparison externalResourceComparison;
index f4b2f51..1f55717 100644 (file)
@@ -178,10 +178,10 @@ ExecutionContext *ExecutionContext::createWithScope(Object *with)
     return withCtx;
 }
 
-ExecutionContext *ExecutionContext::createCatchScope(String *exceptionVarName)
+ExecutionContext *ExecutionContext::createCatchScope(String *exceptionVarName, const Value &exceptionValue)
 {
     ExecutionContext *catchCtx = engine->newContext();
-    catchCtx->initForCatch(this, exceptionVarName);
+    catchCtx->initForCatch(this, exceptionVarName, exceptionValue);
     engine->current = catchCtx;
     return catchCtx;
 }
@@ -235,8 +235,6 @@ void ExecutionContext::init(ExecutionEngine *eng)
     strictMode = false;
     activation = 0;
     withObject = 0;
-
-    eng->exception = Value::undefinedValue();
 }
 
 void ExecutionContext::init(ExecutionContext *p, Object *with)
@@ -259,7 +257,7 @@ void ExecutionContext::init(ExecutionContext *p, Object *with)
     withObject = with;
 }
 
-void ExecutionContext::initForCatch(ExecutionContext *p, String *exceptionVarName)
+void ExecutionContext::initForCatch(ExecutionContext *p, String *exceptionVarName, const Value &exceptionValue)
 {
     engine = p->engine;
     parent = p;
@@ -272,7 +270,7 @@ void ExecutionContext::initForCatch(ExecutionContext *p, String *exceptionVarNam
     argumentCount = 0;
     locals = 0;
     this->exceptionVarName = exceptionVarName;
-    exceptionValue = engine->exception;
+    this->exceptionValue = exceptionValue;
     strictMode = p->strictMode;
     activation = 0;
     withObject = 0;
index 42aeba1..934015c 100644 (file)
@@ -103,7 +103,7 @@ struct ExecutionContext
 
     void init(ExecutionEngine *e);
     void init(ExecutionContext *p, Object *with);
-    void initForCatch(ExecutionContext *p, String *exceptionVarName);
+    void initForCatch(ExecutionContext *p, String *exceptionVarName, const QQmlJS::VM::Value &exceptionValue);
     void destroy();
 
     bool hasBinding(String *name) const;
@@ -113,7 +113,7 @@ struct ExecutionContext
     bool deleteBinding(ExecutionContext *ctx, String *name);
 
     ExecutionContext *createWithScope(Object *with);
-    ExecutionContext *createCatchScope(String* exceptionVarName);
+    ExecutionContext *createCatchScope(String* exceptionVarName, const QQmlJS::VM::Value &exceptionValue);
     ExecutionContext *popScope();
 
     void initCallContext(ExecutionContext *parent);
index 447600f..f04ed19 100644 (file)
@@ -112,9 +112,10 @@ QString numberToString(double num, int radix = 10)
     return str;
 }
 
-Exception::Exception(ExecutionContext *throwingContext)
+Exception::Exception(ExecutionContext *throwingContext, const Value &exceptionValue)
 {
     this->throwingContext = throwingContext;
+    this->exception = exceptionValue;
     accepted = false;
 }
 
@@ -1009,19 +1010,7 @@ void __qmljs_throw(ExecutionContext *context, const Value &value)
     if (context->engine->debugger)
         context->engine->debugger->aboutToThrow(value);
 
-    context->engine->exception = value;
-
-    throw Exception(context);
-}
-
-Q_V4_EXPORT void __qmljs_create_exception_handler(ExecutionContext *context)
-{
-    context->engine->exception = Value::undefinedValue();
-}
-
-void __qmljs_get_exception(ExecutionContext *context, Value *result)
-{
-    *result = context->engine->exception;
+    throw Exception(context, value);
 }
 
 void __qmljs_builtin_typeof(ExecutionContext *ctx, Value *result, const Value &value)
@@ -1253,9 +1242,9 @@ ExecutionContext *__qmljs_builtin_push_with_scope(const Value &o, ExecutionConte
     return ctx->createWithScope(obj);
 }
 
-ExecutionContext *__qmljs_builtin_push_catch_scope(String *exceptionVarName, ExecutionContext *ctx)
+ExecutionContext *__qmljs_builtin_push_catch_scope(String *exceptionVarName, const Value &exceptionValue, ExecutionContext *ctx)
 {
-    return ctx->createCatchScope(exceptionVarName);
+    return ctx->createCatchScope(exceptionVarName, exceptionValue);
 }
 
 ExecutionContext *__qmljs_builtin_pop_scope(ExecutionContext *ctx)
index 3cd1972..5795eff 100644 (file)
@@ -90,15 +90,19 @@ struct ErrorObject;
 struct ExecutionEngine;
 
 struct Q_V4_EXPORT Exception {
-    explicit Exception(ExecutionContext *throwingContext);
+    explicit Exception(ExecutionContext *throwingContext, const Value &exceptionValue);
     ~Exception();
 
     void accept(ExecutionContext *catchingContext);
 
     void partiallyUnwindContext(ExecutionContext *catchingContext);
+
+    Value value() const { return exception; }
+
 private:
     ExecutionContext *throwingContext;
     bool accepted;
+    Value exception;
 };
 
 extern "C" {
@@ -132,7 +136,7 @@ void __qmljs_builtin_post_decrement_element(ExecutionContext *context, Value *re
 void Q_NORETURN __qmljs_builtin_throw(ExecutionContext *context, const Value &val);
 void Q_NORETURN __qmljs_builtin_rethrow(ExecutionContext *context);
 ExecutionContext *__qmljs_builtin_push_with_scope(const Value &o, ExecutionContext *ctx);
-ExecutionContext *__qmljs_builtin_push_catch_scope(String *exceptionVarName, ExecutionContext *ctx);
+ExecutionContext *__qmljs_builtin_push_catch_scope(String *exceptionVarName, const QQmlJS::VM::Value &exceptionValue, ExecutionContext *ctx);
 ExecutionContext *__qmljs_builtin_pop_scope(ExecutionContext *ctx);
 void __qmljs_builtin_declare_var(ExecutionContext *ctx, bool deletable, String *name);
 void __qmljs_builtin_define_property(ExecutionContext *ctx, const Value &object, String *name, Value *val);
@@ -204,9 +208,6 @@ void __qmljs_delete_member(ExecutionContext *ctx, Value *result, const Value &ba
 void __qmljs_delete_name(ExecutionContext *ctx, Value *result, String *name);
 
 void Q_NORETURN __qmljs_throw(ExecutionContext*, const Value &value);
-// actually returns a jmp_buf *
-Q_V4_EXPORT void __qmljs_create_exception_handler(ExecutionContext *context);
-void __qmljs_get_exception(ExecutionContext *context, Value *result);
 
 // binary operators
 typedef void (*BinOp)(ExecutionContext *ctx, Value *result, const Value &left, const Value &right);
index aa58086..b92b26f 100644 (file)
@@ -680,18 +680,19 @@ typedef void *(*MiddleOfFunctionEntryPoint(ExecutionContext *, void *localsPtr))
 static void *tryWrapper(ExecutionContext *context, void *localsPtr, MiddleOfFunctionEntryPoint tryBody, MiddleOfFunctionEntryPoint catchBody,
                         VM::String *exceptionVarName, Value *exceptionVar)
 {
+    *exceptionVar = Value::undefinedValue();
     void *addressToContinueAt = 0;
     try {
         addressToContinueAt = tryBody(context, localsPtr);
     } catch (Exception& ex) {
         ex.accept(context);
-        __qmljs_get_exception(context, exceptionVar);
+        *exceptionVar = ex.value();
         try {
-            ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(exceptionVarName, context);
+            ExecutionContext *catchContext = __qmljs_builtin_push_catch_scope(exceptionVarName, ex.value(), context);
             addressToContinueAt = catchBody(catchContext, localsPtr);
             context = __qmljs_builtin_pop_scope(catchContext);
         } catch (Exception& ex) {
-            __qmljs_get_exception(context, exceptionVar);
+            *exceptionVar = ex.value();
             ex.accept(context);
             addressToContinueAt = catchBody(context, localsPtr);
         }
@@ -701,8 +702,6 @@ static void *tryWrapper(ExecutionContext *context, void *localsPtr, MiddleOfFunc
 
 void InstructionSelection::visitTry(IR::Try *t)
 {
-    generateFunctionCall(Assembler::Void, __qmljs_create_exception_handler, Assembler::ContextRegister);
-
     // Call tryWrapper, which is going to re-enter the same function at the address of the try block. At then end
     // of the try function the JIT code will return with the address of the sub-sequent instruction, which tryWrapper
     // returns and to which we jump to.
index 03ba828..7238355 100644 (file)
@@ -116,11 +116,11 @@ DEFINE_MANAGED_VTABLE(GC);
 
 } // builtins
 
-static void showException(QQmlJS::VM::ExecutionContext *ctx)
+static void showException(QQmlJS::VM::ExecutionContext *ctx, const QQmlJS::VM::Value &exception)
 {
-    QQmlJS::VM::ErrorObject *e = ctx->engine->exception.asErrorObject();
+    QQmlJS::VM::ErrorObject *e = exception.asErrorObject();
     if (!e) {
-        std::cerr << "Uncaught exception: " << qPrintable(ctx->engine->exception.toString(ctx)->toQString()) << std::endl;
+        std::cerr << "Uncaught exception: " << qPrintable(exception.toString(ctx)->toQString()) << std::endl;
         return;
     }
 
@@ -369,7 +369,6 @@ int main(int argc, char *argv[])
                 const QString code = QString::fromUtf8(file.readAll());
                 file.close();
 
-                __qmljs_create_exception_handler(ctx);
                 try {
                     QQmlJS::VM::Function *f = QQmlJS::VM::EvalFunction::parseSource(ctx, fn, code, QQmlJS::Codegen::GlobalCode,
                                                                                     /*strictMode =*/ false, /*inheritContext =*/ false);
@@ -382,7 +381,7 @@ int main(int argc, char *argv[])
                     }
                 } catch (QQmlJS::VM::Exception& ex) {
                     ex.accept(ctx);
-                    showException(ctx);
+                    showException(ctx, ex.value());
                     return EXIT_FAILURE;
                 }