diff options
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 4 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 68 |
2 files changed, 45 insertions, 27 deletions
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index ecc110a16f..b007e65c4b 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -97,7 +97,9 @@ struct Q_QML_EXPORT CppStackFrame { int originalArgumentsCount; int instructionPointer; const char *yield; - const char *exceptionHandler; + const char *unwindHandler; + const char *unwindLabel; + int unwindLevel; QString source() const; QString function() const; diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index e180298789..165902ed36 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -344,7 +344,7 @@ static struct InstrCount { #endif #define CHECK_EXCEPTION \ if (engine->hasException) \ - goto catchException + goto handleUnwind static inline Heap::CallContext *getScope(QV4::Value *stack, int level) { @@ -510,7 +510,10 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const QV4::Value *thisObj frame.originalArguments = argv; frame.originalArgumentsCount = argc; frame.yield = nullptr; - frame.exceptionHandler = nullptr; + frame.unwindHandler = nullptr; + frame.unwindLabel = nullptr; + frame.unwindLevel = 0; + Function *function; { @@ -810,7 +813,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code) if (engine->hasException) { // an empty value indicates that the generator was called with return() if (engine->exceptionValue->asReturnedValue() != Primitive::emptyValue().asReturnedValue()) - goto catchException; + goto handleUnwind; engine->hasException = false; *engine->exceptionValue = Primitive::undefinedValue(); } else { @@ -823,7 +826,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code) Value func = STACK_VALUE(name); if (Q_UNLIKELY(!func.isFunctionObject())) { acc = engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow())); - goto catchException; + goto handleUnwind; } acc = static_cast<const FunctionObject &>(func).call(nullptr, stack + argv, argc); CHECK_EXCEPTION; @@ -843,7 +846,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code) if (Q_UNLIKELY(!f.isFunctionObject())) { acc = engine->throwTypeError(); - goto catchException; + goto handleUnwind; } acc = static_cast<FunctionObject &>(f).call(stack + base, stack + argv, argc); @@ -887,14 +890,30 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code) MOTH_END_INSTR(CallContextObjectProperty) MOTH_BEGIN_INSTR(SetUnwindHandler) - frame.exceptionHandler = offset ? code + offset : nullptr; + frame.unwindHandler = offset ? code + offset : nullptr; MOTH_END_INSTR(SetUnwindHandler) + MOTH_BEGIN_INSTR(UnwindDispatch) + CHECK_EXCEPTION; + if (frame.unwindLevel) { + --frame.unwindLevel; + if (frame.unwindLevel) + goto handleUnwind; + code = frame.unwindLabel; + } + MOTH_END_INSTR(UnwindDispatch) + + MOTH_BEGIN_INSTR(UnwindToLabel) + frame.unwindLevel = level; + frame.unwindLabel = code + offset; + goto handleUnwind; + MOTH_END_INSTR(UnwindToLabel) + MOTH_BEGIN_INSTR(ThrowException) STORE_IP(); STORE_ACC(); Runtime::method_throwException(engine, accumulator); - goto catchException; + goto handleUnwind; MOTH_END_INSTR(ThrowException) MOTH_BEGIN_INSTR(GetException) @@ -904,8 +923,10 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code) MOTH_END_INSTR(HasException) MOTH_BEGIN_INSTR(SetException) - *engine->exceptionValue = acc; - engine->hasException = true; + if (acc != Primitive::emptyValue().asReturnedValue()) { + *engine->exceptionValue = acc; + engine->hasException = true; + } MOTH_END_INSTR(SetException) MOTH_BEGIN_INSTR(PushCatchContext) @@ -979,7 +1000,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code) if (function->isStrict()) { STORE_IP(); engine->throwTypeError(); - goto catchException; + goto handleUnwind; } acc = Encode(false); } else { @@ -992,7 +1013,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code) if (function->isStrict()) { STORE_IP(); engine->throwTypeError(); - goto catchException; + goto handleUnwind; } acc = Encode(false); } else { @@ -1006,7 +1027,7 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code) STORE_IP(); QString n = function->compilationUnit->runtimeStrings[name]->toQString(); engine->throwSyntaxError(QStringLiteral("Can't delete property %1").arg(n)); - goto catchException; + goto handleUnwind; } acc = Encode(false); } else { @@ -1096,6 +1117,11 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code) } MOTH_END_INSTR(JumpFalse) + MOTH_BEGIN_INSTR(JumpNoException) + if (!engine->hasException) + code += offset; + MOTH_END_INSTR(JumpNoException) + MOTH_BEGIN_INSTR(JumpNotUndefined) if (Q_LIKELY(acc != QV4::Encode::undefined())) code += offset; @@ -1242,16 +1268,6 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code) CHECK_EXCEPTION; MOTH_END_INSTR(CmpInstanceOf) - MOTH_BEGIN_INSTR(JumpStrictNotEqualStackSlotInt) - if (STACK_VALUE(lhs).int_32() != rhs || STACK_VALUE(lhs).isUndefined()) - code += offset; - MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt) - - MOTH_BEGIN_INSTR(JumpStrictEqualStackSlotInt) - if (STACK_VALUE(lhs).int_32() == rhs && !STACK_VALUE(lhs).isUndefined()) - code += offset; - MOTH_END_INSTR(JumpStrictNotEqualStackSlotInt) - MOTH_BEGIN_INSTR(UNot) if (ACC.integerCompatible()) { acc = Encode(!static_cast<bool>(ACC.int_32())); @@ -1456,12 +1472,12 @@ QV4::ReturnedValue VME::interpret(CppStackFrame &frame, const char *code) STACK_VALUE(result) = Runtime::method_loadQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine)); MOTH_END_INSTR(LoadQmlImportedScripts) - catchException: - Q_ASSERT(engine->hasException); - if (!frame.exceptionHandler) { + handleUnwind: + Q_ASSERT(engine->hasException || frame.unwindLevel); + if (!frame.unwindHandler) { acc = Encode::undefined(); return acc; } - code = frame.exceptionHandler; + code = frame.unwindHandler; } } |