From 7d9780b6308e15dcd4adcb65d7b516666c285f54 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 1 Oct 2013 16:19:28 +0200 Subject: [PATCH] Cleanup exception handling The code in the Exception class operates entirely on the engine's data, so move it into ExecutionEngine instead. This eliminates the need for a QV4::Exception class and catches and old code that tries to still do catch (Exception &) instead of catch (...) Change-Id: Ie608bec6af652038aca6c9423c225a4d7eb13b39 Reviewed-by: Lars Knoll --- src/imports/localstorage/plugin.cpp | 1 - src/qml/compiler/qv4isel_masm.cpp | 1 - src/qml/jsapi/qjsengine.cpp | 1 - src/qml/jsapi/qjsvalue.cpp | 1 - src/qml/jsapi/qjsvalueiterator.cpp | 1 - src/qml/jsruntime/jsruntime.pri | 4 +- src/qml/jsruntime/qv4context.cpp | 21 +--- src/qml/jsruntime/qv4engine.cpp | 59 ++++++++++- .../{qv4exception_gcc.cpp => qv4engine_cxxabi.cpp} | 37 ++++--- src/qml/jsruntime/qv4engine_p.h | 18 +++- src/qml/jsruntime/qv4exception.cpp | 115 --------------------- src/qml/jsruntime/qv4exception_p.h | 64 ------------ src/qml/jsruntime/qv4functionobject.cpp | 2 +- src/qml/jsruntime/qv4globalobject.cpp | 1 - src/qml/jsruntime/qv4include.cpp | 1 - src/qml/jsruntime/qv4script.cpp | 1 - src/qml/jsruntime/qv4value.cpp | 1 - src/qml/jsruntime/qv4vme_moth.cpp | 1 - src/qml/qml/qqmljavascriptexpression_p.h | 1 - .../auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp | 1 - tools/v4/main.cpp | 1 - 21 files changed, 97 insertions(+), 236 deletions(-) rename src/qml/jsruntime/{qv4exception_gcc.cpp => qv4engine_cxxabi.cpp} (96%) delete mode 100644 src/qml/jsruntime/qv4exception.cpp delete mode 100644 src/qml/jsruntime/qv4exception_p.h diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index 4cfc6a0..84bcb75 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -59,7 +59,6 @@ #include #include #include -#include #include using namespace QV4; diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp index 020bdb3..fed1ca8 100644 --- a/src/qml/compiler/qv4isel_masm.cpp +++ b/src/qml/compiler/qv4isel_masm.cpp @@ -48,7 +48,6 @@ #include "qv4lookup_p.h" #include "qv4function_p.h" #include "qv4ssa_p.h" -#include "qv4exception_p.h" #include "qv4regalloc_p.h" #include diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp index d42cabd..107ac98 100644 --- a/src/qml/jsapi/qjsengine.cpp +++ b/src/qml/jsapi/qjsengine.cpp @@ -49,7 +49,6 @@ #include "private/qv4mm_p.h" #include "private/qv4globalobject_p.h" #include "private/qv4script_p.h" -#include "private/qv4exception_p.h" #include #include diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index ba94afa..29734fd 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -54,7 +54,6 @@ #include "qv4regexpobject_p.h" #include "private/qv8engine_p.h" #include -#include #include QV4::ReturnedValue QJSValuePrivate::getValue(QV4::ExecutionEngine *e) diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp index fd5f709..dcf7c47 100644 --- a/src/qml/jsapi/qjsvalueiterator.cpp +++ b/src/qml/jsapi/qjsvalueiterator.cpp @@ -44,7 +44,6 @@ #include "qjsvalue_p.h" #include "private/qv4string_p.h" #include "private/qv4object_p.h" -#include "private/qv4exception_p.h" QT_BEGIN_NAMESPACE diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri index 88cd3a9..d5c29e8 100644 --- a/src/qml/jsruntime/jsruntime.pri +++ b/src/qml/jsruntime/jsruntime.pri @@ -46,7 +46,6 @@ SOURCES += \ $$PWD/qv4qobjectwrapper.cpp \ $$PWD/qv4qmlextensions.cpp \ $$PWD/qv4stacktrace.cpp \ - $$PWD/qv4exception.cpp \ $$PWD/qv4vme_moth.cpp HEADERS += \ @@ -98,7 +97,6 @@ HEADERS += \ $$PWD/qv4qobjectwrapper_p.h \ $$PWD/qv4qmlextensions_p.h \ $$PWD/qv4stacktrace_p.h \ - $$PWD/qv4exception_p.h \ $$PWD/qv4vme_moth_p.h # Use SSE2 floating point math on 32 bit instead of the default @@ -117,7 +115,7 @@ linux*|mac { static_libgcc = $$system($$QMAKE_CXX -print-file-name=libgcc.a) LIBS += $$static_libgcc } - SOURCES += $$PWD/qv4exception_gcc.cpp + SOURCES += $$PWD/qv4engine_cxxabi.cpp DEFINES += V4_CXX_ABI_EXCEPTION } diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 4bba0bf..be6e164 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -48,7 +48,6 @@ #include #include "qv4function_p.h" #include "qv4errorobject_p.h" -#include "qv4exception_p.h" using namespace QV4; @@ -598,7 +597,7 @@ ReturnedValue ExecutionContext::getPropertyAndBase(const StringRef name, ObjectR void ExecutionContext::throwError(const ValueRef value) { - Exception::throwException(this, value); + engine->throwException(value); } void ExecutionContext::throwError(const QString &message) @@ -647,26 +646,12 @@ void ExecutionContext::throwUnimplemented(const QString &message) ReturnedValue ExecutionContext::catchException(StackTrace *trace) { - if (!engine->hasException) - Exception::rethrow(); - while (engine->current != this) - engine->popContext(); - if (trace) - *trace = engine->exceptionStackTrace; - engine->exceptionStackTrace.clear(); - engine->hasException = false; - ReturnedValue res = engine->exceptionValue.asReturnedValue(); - engine->exceptionValue = Encode::undefined(); - return res; + return engine->catchException(this, trace); } void ExecutionContext::rethrowException() { - if (engine->hasException) { - while (engine->current != this) - engine->popContext(); - } - Exception::rethrow(); + engine->rethrowException(this); } void ExecutionContext::throwReferenceError(const ValueRef value) diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index ba7241b..41eb6fe 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -67,7 +67,6 @@ #include "qv4qobjectwrapper_p.h" #include "qv4qmlextensions_p.h" #include "qv4stacktrace_p.h" -#include "qv4exception_p.h" #ifdef V4_ENABLE_JIT #include "qv4isel_masm_p.h" @@ -809,4 +808,62 @@ QmlExtensions *ExecutionEngine::qmlExtensions() return m_qmlExtensions; } +void ExecutionEngine::throwException(const ValueRef value) +{ + Q_ASSERT(!hasException); + hasException = true; + exceptionValue = value; + QV4::Scope scope(this); + QV4::Scoped error(scope, value); + if (!!error) + exceptionStackTrace = error->stackTrace; + else + exceptionStackTrace = stackTrace(); + + if (debugger) + debugger->aboutToThrow(value); + + UnwindHelper::prepareForUnwind(current); + throwInternal(); +} + +void ExecutionEngine::rethrowException(ExecutionContext *intermediateCatchingContext) +{ + if (hasException) { + while (current != intermediateCatchingContext) + popContext(); + } + rethrowInternal(); +} + +ReturnedValue ExecutionEngine::catchException(ExecutionContext *catchingContext, StackTrace *trace) +{ + if (!hasException) + rethrowInternal(); + while (current != catchingContext) + popContext(); + if (trace) + *trace = exceptionStackTrace; + exceptionStackTrace.clear(); + hasException = false; + ReturnedValue res = exceptionValue.asReturnedValue(); + exceptionValue = Encode::undefined(); + return res; +} + +#if !defined(V4_CXX_ABI_EXCEPTION) +struct DummyException +{}; + +void ExecutionEngine::throwInternal() +{ + throw DummyException(); +} + +void ExecutionEngine::rethrowInternal() +{ + throw; +} +#endif + QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4exception_gcc.cpp b/src/qml/jsruntime/qv4engine_cxxabi.cpp similarity index 96% rename from src/qml/jsruntime/qv4exception_gcc.cpp rename to src/qml/jsruntime/qv4engine_cxxabi.cpp index d3c406f..6141753 100644 --- a/src/qml/jsruntime/qv4exception_gcc.cpp +++ b/src/qml/jsruntime/qv4engine_cxxabi.cpp @@ -38,8 +38,9 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "qv4engine_p.h" -#include "qv4exception_p.h" +#if defined(V4_CXX_ABI_EXCEPTION) // On arm we link libgcc statically and want to avoid exporting the _Unwind* symbols #if defined(Q_PROCESSOR_ARM) @@ -94,22 +95,7 @@ QT_BEGIN_NAMESPACE using namespace QV4; -void Exception::rethrow() -{ - cxa_eh_globals *globals = __cxa_get_globals(); - cxa_exception *exception = globals->caughtExceptions; - - // Make sure we only re-throw our foreign exceptions. For general re-throw - // we'd need different code. -#ifndef __ARM_EABI_UNWINDER__ - Q_ASSERT(exception->unwindHeader.exception_class == 0x514d4c4a53563400); // QMLJSV40 -#endif - - globals->caughtExceptions = 0; - _Unwind_RaiseException(&exception->unwindHeader); -} - -void Exception::throwInternal() +void ExecutionEngine::throwInternal() { _Unwind_Exception *exception = (_Unwind_Exception*)malloc(sizeof(_Unwind_Exception)); memset(exception, 0, sizeof(*exception)); @@ -132,4 +118,21 @@ void Exception::throwInternal() std::terminate(); } +void ExecutionEngine::rethrowInternal() +{ + cxa_eh_globals *globals = __cxa_get_globals(); + cxa_exception *exception = globals->caughtExceptions; + + // Make sure we only re-throw our foreign exceptions. For general re-throw + // we'd need different code. +#ifndef __ARM_EABI_UNWINDER__ + Q_ASSERT(exception->unwindHeader.exception_class == 0x514d4c4a53563400); // QMLJSV40 +#endif + + globals->caughtExceptions = 0; + _Unwind_RaiseException(&exception->unwindHeader); +} + QT_END_NAMESPACE + +#endif diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 9a83ddc..e70ac7b 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -237,10 +237,6 @@ struct Q_QML_EXPORT ExecutionEngine RegExpCache *regExpCache; - SafeValue exceptionValue; - bool hasException; - StackTrace exceptionStackTrace; - // Scarce resources are "exceptionally high cost" QVariant types where allowing the // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other // out-of-resource situations. When such a resource is passed into JavaScript we @@ -324,6 +320,20 @@ struct Q_QML_EXPORT ExecutionEngine QmlExtensions *qmlExtensions(); + // Exception handling + SafeValue exceptionValue; + bool hasException; + StackTrace exceptionStackTrace; + + void Q_NORETURN throwException(const ValueRef value); + void Q_NORETURN rethrowException(ExecutionContext *intermediateCatchingContext); + ReturnedValue catchException(ExecutionContext *catchingContext, StackTrace *trace); + + void Q_NORETURN throwInternal(); + void Q_NORETURN rethrowInternal(); + // ---- + + private: QmlExtensions *m_qmlExtensions; }; diff --git a/src/qml/jsruntime/qv4exception.cpp b/src/qml/jsruntime/qv4exception.cpp deleted file mode 100644 index 8cee153..0000000 --- a/src/qml/jsruntime/qv4exception.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv4exception_p.h" -#include "qv4errorobject_p.h" -#include "qv4debugging_p.h" -#include "qv4unwindhelper_p.h" - -#include - -#if USE(LIBUNWIND_DEBUG) -#include -#include -#endif - -QT_BEGIN_NAMESPACE - -using namespace QV4; - - -void Exception::throwException(ExecutionContext *context, const ValueRef value) -{ - ExecutionEngine *engine = context->engine; - Q_ASSERT(!engine->hasException); - engine->hasException = true; - engine->exceptionValue = value; - QV4::Scope scope(engine); - QV4::Scoped error(scope, value); - if (!!error) - engine->exceptionStackTrace = error->stackTrace; - else - engine->exceptionStackTrace = engine->stackTrace(); - - if (context->engine->debugger) - context->engine->debugger->aboutToThrow(value); - - UnwindHelper::prepareForUnwind(context); - -#if USE(LIBUNWIND_DEBUG) - printf("about to throw exception. walking stack first with libunwind:\n"); - unw_cursor_t cursor; unw_context_t uc; - unw_word_t ip, sp; - - unw_getcontext(&uc); - unw_init_local(&cursor, &uc); - while (unw_step(&cursor) > 0) { - unw_get_reg(&cursor, UNW_REG_IP, &ip); - unw_get_reg(&cursor, UNW_REG_SP, &sp); - printf("ip = %lx, sp = %lx ", (long) ip, (long) sp); - void * const addr = (void*)ip; - char **symbol = backtrace_symbols(&addr, 1); - printf("%s", symbol[0]); - free(symbol); - printf("\n"); - } - printf("stack walked. throwing exception now...\n"); -#endif - - throwInternal(); -} - -#if !defined(V4_CXX_ABI_EXCEPTION) -void Exception::rethrow() -{ - throw; -} - -struct DummyException -{}; - -void Exception::throwInternal() -{ - throw DummyException(); -} -#endif - -QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4exception_p.h b/src/qml/jsruntime/qv4exception_p.h deleted file mode 100644 index 8889630..0000000 --- a/src/qml/jsruntime/qv4exception_p.h +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef QV4EXCEPTION_P -#define QV4EXCEPTION_P - -#include -#include "qv4value_p.h" -#include "qv4engine_p.h" - -QT_BEGIN_NAMESPACE - -namespace QV4 { - -struct Q_QML_EXPORT Exception { - static void Q_NORETURN throwException(ExecutionContext *throwingContext, const ValueRef exceptionValue); - static void Q_NORETURN rethrow(); - -private: - static void Q_NORETURN throwInternal(); -}; - -} // namespace QV4 - -QT_END_NAMESPACE - -#endif // QV4EXCEPTION_P diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 305efba..058c71f 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -46,7 +46,7 @@ #include "qv4stringobject_p.h" #include "qv4function_p.h" #include "qv4mm_p.h" -#include "qv4exception_p.h" + #include "qv4arrayobject_p.h" #include "qv4scopedvalue_p.h" diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp index a465fdc..e1e986e 100644 --- a/src/qml/jsruntime/qv4globalobject.cpp +++ b/src/qml/jsruntime/qv4globalobject.cpp @@ -46,7 +46,6 @@ #include "qv4function_p.h" #include "qv4debugging_p.h" #include "qv4script_p.h" -#include "qv4exception_p.h" #include "qv4scopedvalue_p.h" #include diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index 44ba059..47d2832 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -53,7 +53,6 @@ #include #include #include -#include #include QT_BEGIN_NAMESPACE diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index e320656..4081be5 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -45,7 +45,6 @@ #include "qv4function_p.h" #include "qv4context_p.h" #include "qv4debugging_p.h" -#include "qv4exception_p.h" #include "qv4scopedvalue_p.h" #include diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp index 3c9db5e..318fb48 100644 --- a/src/qml/jsruntime/qv4value.cpp +++ b/src/qml/jsruntime/qv4value.cpp @@ -42,7 +42,6 @@ #include #include #include "qv4mm_p.h" -#include "qv4exception_p.h" #include diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 0807e6b..64b49f9 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -43,7 +43,6 @@ #include "qv4instr_moth_p.h" #include #include -#include #include #include #include diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h index efea961..4435704 100644 --- a/src/qml/qml/qqmljavascriptexpression_p.h +++ b/src/qml/qml/qqmljavascriptexpression_p.h @@ -57,7 +57,6 @@ #include #include #include -#include QT_BEGIN_NAMESPACE diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index ea8a1fe..b89d3da 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -54,7 +54,6 @@ #include "testhttpserver.h" #include "../../shared/util.h" #include -#include #include #ifdef Q_CC_MSVC diff --git a/tools/v4/main.cpp b/tools/v4/main.cpp index 3d79e89..e6ab56b 100644 --- a/tools/v4/main.cpp +++ b/tools/v4/main.cpp @@ -52,7 +52,6 @@ #include "private/qv4mm_p.h" #include "private/qv4context_p.h" #include "private/qv4script_p.h" -#include "private/qv4exception_p.h" #ifdef V4_ENABLE_JIT # include "private/qv4isel_masm_p.h" -- 2.7.4