aboutsummaryrefslogtreecommitdiffstats
path: root/moth
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2012-11-14 10:15:19 +0100
committerErik Verbruggen <erik.verbruggen@digia.com>2012-11-14 11:45:03 +0100
commit8f69d75c785ff86face31db880abdb8414d1cbfe (patch)
tree6bd6fb4b6b445e1deeecda8e8bbed21e8120a503 /moth
parent614b6c0a8d1c7621b423228a4bf4d1761503b148 (diff)
Fix interpreter exception handling.
The stack frame of the interpreting function is restored, but all the datastructures live on the heap. So, save them out on handler creation, and restore them afterwards. Change-Id: I84b84007cc9944b56926bf0387c2798f7841cd2a Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'moth')
-rw-r--r--moth/qv4vme_moth.cpp46
-rw-r--r--moth/qv4vme_moth_p.h4
2 files changed, 46 insertions, 4 deletions
diff --git a/moth/qv4vme_moth.cpp b/moth/qv4vme_moth.cpp
index 66df75f79e..e9c43d4701 100644
--- a/moth/qv4vme_moth.cpp
+++ b/moth/qv4vme_moth.cpp
@@ -197,13 +197,30 @@ void VME::operator()(QQmlJS::VM::Context *context, const uchar *code
TEMP(instr.targetTempIndex) = __qmljs_builtin_typeof(args[0], context);
break;
case Instr::instr_callBuiltin::builtin_throw:
- TEMP(instr.targetTempIndex) = __qmljs_builtin_typeof(args[0], context);
+ TRACE(builtin_throw, "Throwing now...%s", "");
+ __qmljs_builtin_throw(args[0], context);
break;
- case Instr::instr_callBuiltin::builtin_create_exception_handler:
+ case Instr::instr_callBuiltin::builtin_create_exception_handler: {
+ TRACE(builtin_create_exception_handler, "%s", "");
buf = __qmljs_create_exception_handler(context);
- TEMP(instr.targetTempIndex) = VM::Value::fromInt32(setjmp(* static_cast<jmp_buf *>(buf)));
- break;
+ // The targetTempIndex is the only value we need from the instr to
+ // continue execution when an exception is caught.
+ int targetTempIndex = instr.targetTempIndex;
+ int didThrow = setjmp(* static_cast<jmp_buf *>(buf));
+ // Two ways to come here: after a create, or after a throw.
+ if (didThrow)
+ // At this point, the interpreter state can be anything but
+ // valid, so first restore the state. This includes all relevant
+ // locals.
+ restoreState(context, stack, targetTempIndex, code);
+ else
+ // Save the state and any variables we need when catching an
+ // exception, so we can restore the state at that point.
+ saveState(context, stack, targetTempIndex, code);
+ TEMP(targetTempIndex) = VM::Value::fromInt32(didThrow);
+ } break;
case Instr::instr_callBuiltin::builtin_delete_exception_handler:
+ TRACE(builtin_delete_exception_handler, "%s", "");
__qmljs_delete_exception_handler(context);
break;
case Instr::instr_callBuiltin::builtin_get_exception:
@@ -328,3 +345,24 @@ void VME::exec(VM::Context *ctxt, const uchar *code)
vme(ctxt, code);
}
+void VME::restoreState(VM::Context *context, QVector<VM::Value> &stack, int &targetTempIndex, const uchar *&code)
+{
+ typedef VM::ExecutionEngine::ExceptionHandler EH;
+ EH::InterpreterState *state = context->engine->unwindStack.last()->interpreterState;
+ assert(state);
+ stack.resize(state->stack.size());
+ ::memcpy(stack.data(), state->stack.data(), sizeof(VM::Value) * state->stack.size());
+ targetTempIndex = state->targetTempIndex;
+ code = state->code;
+}
+
+void VME::saveState(VM::Context *context, const QVector<VM::Value> &stack, int targetTempIndex, const uchar *code)
+{
+ typedef VM::ExecutionEngine::ExceptionHandler EH;
+ EH::InterpreterState *state = new EH::InterpreterState;
+ context->engine->unwindStack.last()->interpreterState = state;
+ state->stack.resize(stack.size());
+ ::memcpy(state->stack.data(), stack.data(), sizeof(VM::Value) * stack.size());
+ state->targetTempIndex = targetTempIndex;
+ state->code = code;
+}
diff --git a/moth/qv4vme_moth_p.h b/moth/qv4vme_moth_p.h
index db1507d84d..b1bc45bab5 100644
--- a/moth/qv4vme_moth_p.h
+++ b/moth/qv4vme_moth_p.h
@@ -21,6 +21,10 @@ public:
#ifdef MOTH_THREADED_INTERPRETER
static void **instructionJumpTable();
#endif
+
+private:
+ static void restoreState(VM::Context *context, QVector<VM::Value> &stack, int &targetTempIndex, const uchar *&code);
+ static void saveState(VM::Context *context, const QVector<VM::Value> &stack, int targetTempIndex, const uchar *code);
};
} // namespace Moth