Warning, /graphics/krita/3rdparty/ext_qt/0134-V4-Generate-function-tables-on-64bit-windows.patch is written in an unsupported language. File is not indexed.
0001 From 67bb77d22b7a5a3452b2c36da8ec2154d24489e6 Mon Sep 17 00:00:00 2001 0002 From: Ulf Hermann <ulf.hermann@qt.io> 0003 Date: Thu, 8 Nov 2018 18:09:21 +0100 0004 Subject: [PATCH 134/139] V4: Generate function tables on 64bit windows 0005 0006 In order for global exception handlers to be called reliably, the runtime 0007 needs to unwind through JIT-generated code. This can be facilitated by 0008 installing a "function table" for each JITed function that specifies "use 0009 the frame pointer". 0010 0011 Also make sure to generate a function table for JIT'ed regular 0012 expressions. Those were forgotten also in the linux case. 0013 0014 Fixes: QTBUG-50061 0015 Change-Id: Ib0b8ae9356ed80afe1cab017e36efa4ccbe73f90 0016 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io> 0017 (cherry picked from commit 74d23ca548b47c85c4b8cdde5fd5a9026e4eb08c) 0018 Signed-off-by: L. E. Segovia <amy@amyspark.me> 0019 --- 0020 .../QtQml/private/qv4functiontable_p.h | 1 + 0021 include/QtQml/headers.pri | 2 +- 0022 src/3rdparty/masm/assembler/LinkBuffer.h | 13 ++ 0023 src/3rdparty/masm/stubs/ExecutableAllocator.h | 1 + 0024 src/3rdparty/masm/yarr/YarrJIT.cpp | 40 ++++- 0025 src/3rdparty/masm/yarr/YarrJIT.h | 25 ++- 0026 src/qml/jit/qv4assemblercommon.cpp | 44 +---- 0027 src/qml/jsruntime/jsruntime.pri | 18 +++ 0028 src/qml/jsruntime/qv4executableallocator.cpp | 10 +- 0029 src/qml/jsruntime/qv4executableallocator_p.h | 1 + 0030 src/qml/jsruntime/qv4function.cpp | 17 +- 0031 src/qml/jsruntime/qv4function_p.h | 5 +- 0032 src/qml/jsruntime/qv4functiontable_noop.cpp | 65 ++++++++ 0033 src/qml/jsruntime/qv4functiontable_p.h | 75 +++++++++ 0034 src/qml/jsruntime/qv4functiontable_unix.cpp | 99 ++++++++++++ 0035 src/qml/jsruntime/qv4functiontable_win64.cpp | 153 ++++++++++++++++++ 0036 tests/auto/qml/qv4assembler/data/crash.qml | 53 ++++++ 0037 tests/auto/qml/qv4assembler/qv4assembler.pro | 5 + 0038 .../qml/qv4assembler/tst_qv4assembler.cpp | 55 ++++++- 0039 19 files changed, 623 insertions(+), 59 deletions(-) 0040 create mode 100644 include/QtQml/5.12.12/QtQml/private/qv4functiontable_p.h 0041 create mode 100644 src/qml/jsruntime/qv4functiontable_noop.cpp 0042 create mode 100644 src/qml/jsruntime/qv4functiontable_p.h 0043 create mode 100644 src/qml/jsruntime/qv4functiontable_unix.cpp 0044 create mode 100644 src/qml/jsruntime/qv4functiontable_win64.cpp 0045 create mode 100644 tests/auto/qml/qv4assembler/data/crash.qml 0046 0047 diff --git a/include/QtQml/5.12.12/QtQml/private/qv4functiontable_p.h b/include/QtQml/5.12.12/QtQml/private/qv4functiontable_p.h 0048 new file mode 100644 0049 index 00000000..55a639eb 0050 --- /dev/null 0051 +++ b/include/QtQml/5.12.12/QtQml/private/qv4functiontable_p.h 0052 @@ -0,0 +1 @@ 0053 +#include "../../../../../src/qml/jsruntime/qv4functiontable_p.h" 0054 diff --git a/include/QtQml/headers.pri b/include/QtQml/headers.pri 0055 index 08811981..634a8a24 100644 0056 --- a/include/QtQml/headers.pri 0057 +++ b/include/QtQml/headers.pri 0058 @@ -1,6 +1,6 @@ 0059 SYNCQT.HEADER_FILES = qtqmlglobal.h debugger/qqmldebug.h jsapi/qjsengine.h jsapi/qjsvalue.h jsapi/qjsvalueiterator.h qml/qqml.h qml/qqmlabstracturlinterceptor.h qml/qqmlapplicationengine.h qml/qqmlcomponent.h qml/qqmlcontext.h qml/qqmlengine.h qml/qqmlerror.h qml/qqmlexpression.h qml/qqmlextensioninterface.h qml/qqmlextensionplugin.h qml/qqmlfile.h qml/qqmlfileselector.h qml/qqmlincubator.h qml/qqmlinfo.h qml/qqmllist.h qml/qqmlnetworkaccessmanagerfactory.h qml/qqmlparserstatus.h qml/qqmlprivate.h qml/qqmlproperty.h qml/qqmlpropertyvaluesource.h qml/qqmlscriptstring.h util/qqmlpropertymap.h 0060 SYNCQT.GENERATED_HEADER_FILES = QQmlDebuggingEnabler QJSEngine QJSValueList QJSValue QJSValueIterator QQmlAbstractUrlInterceptor QQmlApplicationEngine QQmlComponent QQmlContext QQmlImageProviderBase QQmlEngine QQmlError QQmlExpression QQmlTypesExtensionInterface QQmlExtensionInterface QQmlExtensionPlugin QQmlFile QQmlFileSelector QQmlIncubator QQmlIncubationController QQmlInfo QQmlListProperty QQmlListReference QQmlNetworkAccessManagerFactory QQmlParserStatus QQmlAttachedPropertiesFunc QQmlTypeInfo QQmlProperty QQmlProperties QQmlPropertyValueSource QQmlScriptString QQmlPropertyMap qtqmlversion.h QtQmlVersion QtQml 0061 -SYNCQT.PRIVATE_HEADER_FILES = qtqmlglobal_p.h animations/qabstractanimationjob_p.h animations/qanimationgroupjob_p.h animations/qanimationjobutil_p.h animations/qcontinuinganimationgroupjob_p.h animations/qparallelanimationgroupjob_p.h animations/qpauseanimationjob_p.h animations/qsequentialanimationgroupjob_p.h compiler/qqmlirbuilder_p.h compiler/qqmlpropertycachecreator_p.h compiler/qqmlpropertyvalidator_p.h compiler/qqmltypecompiler_p.h compiler/qv4bytecodegenerator_p.h compiler/qv4bytecodehandler_p.h compiler/qv4codegen_p.h compiler/qv4compilationunitmapper_p.h compiler/qv4compileddata_p.h compiler/qv4compiler_p.h compiler/qv4compilercontext_p.h compiler/qv4compilercontrolflow_p.h compiler/qv4compilerscanfunctions_p.h compiler/qv4instr_moth_p.h debugger/qqmlabstractprofileradapter_p.h debugger/qqmlconfigurabledebugservice_p.h debugger/qqmldebugconnector_p.h debugger/qqmldebugpluginmanager_p.h debugger/qqmldebugserver_p.h debugger/qqmldebugserverconnection_p.h debugger/qqmldebugservice_p.h debugger/qqmldebugservicefactory_p.h debugger/qqmldebugserviceinterfaces_p.h debugger/qqmldebugstatesdelegate_p.h debugger/qqmlmemoryprofiler_p.h debugger/qqmlprofiler_p.h debugger/qqmlprofilerdefinitions_p.h jit/qv4assemblercommon_p.h jit/qv4baselineassembler_p.h jit/qv4baselinejit_p.h jit/qv4jithelpers_p.h jsapi/qjsengine_p.h jsapi/qjsvalue_p.h jsapi/qjsvalueiterator_p.h jsruntime/qv4alloca_p.h jsruntime/qv4argumentsobject_p.h jsruntime/qv4arraybuffer_p.h jsruntime/qv4arraydata_p.h jsruntime/qv4arrayiterator_p.h jsruntime/qv4arrayobject_p.h jsruntime/qv4atomics_p.h jsruntime/qv4booleanobject_p.h jsruntime/qv4context_p.h jsruntime/qv4dataview_p.h jsruntime/qv4dateobject_p.h jsruntime/qv4debugging_p.h jsruntime/qv4engine_p.h jsruntime/qv4enginebase_p.h jsruntime/qv4errorobject_p.h jsruntime/qv4estable_p.h jsruntime/qv4executableallocator_p.h jsruntime/qv4function_p.h jsruntime/qv4functionobject_p.h jsruntime/qv4generatorobject_p.h jsruntime/qv4global_p.h jsruntime/qv4globalobject_p.h jsruntime/qv4identifier_p.h jsruntime/qv4identifiertable_p.h jsruntime/qv4include_p.h jsruntime/qv4internalclass_p.h jsruntime/qv4iterator_p.h jsruntime/qv4jscall_p.h jsruntime/qv4jsonobject_p.h jsruntime/qv4lookup_p.h jsruntime/qv4managed_p.h jsruntime/qv4mapiterator_p.h jsruntime/qv4mapobject_p.h jsruntime/qv4math_p.h jsruntime/qv4mathobject_p.h jsruntime/qv4memberdata_p.h jsruntime/qv4module_p.h jsruntime/qv4numberobject_p.h jsruntime/qv4object_p.h jsruntime/qv4objectiterator_p.h jsruntime/qv4objectproto_p.h jsruntime/qv4persistent_p.h jsruntime/qv4profiling_p.h jsruntime/qv4promiseobject_p.h jsruntime/qv4property_p.h jsruntime/qv4propertykey_p.h jsruntime/qv4proxy_p.h jsruntime/qv4qmlcontext_p.h jsruntime/qv4qobjectwrapper_p.h jsruntime/qv4reflect_p.h jsruntime/qv4regexp_p.h jsruntime/qv4regexpobject_p.h jsruntime/qv4runtime_p.h jsruntime/qv4runtimeapi_p.h jsruntime/qv4runtimecodegen_p.h jsruntime/qv4scopedvalue_p.h jsruntime/qv4script_p.h jsruntime/qv4sequenceobject_p.h jsruntime/qv4serialize_p.h jsruntime/qv4setiterator_p.h jsruntime/qv4setobject_p.h jsruntime/qv4sparsearray_p.h jsruntime/qv4stackframe_p.h jsruntime/qv4string_p.h jsruntime/qv4stringiterator_p.h jsruntime/qv4stringobject_p.h jsruntime/qv4symbol_p.h jsruntime/qv4typedarray_p.h jsruntime/qv4util_p.h jsruntime/qv4value_p.h jsruntime/qv4variantobject_p.h jsruntime/qv4vme_moth_p.h jsruntime/qv4vtable_p.h memory/qv4heap_p.h memory/qv4mm_p.h memory/qv4mmdefs_p.h memory/qv4writebarrier_p.h parser/qqmljsast_p.h parser/qqmljsastfwd_p.h parser/qqmljsastvisitor_p.h parser/qqmljsengine_p.h parser/qqmljsglobal_p.h parser/qqmljskeywords_p.h parser/qqmljslexer_p.h parser/qqmljsmemorypool_p.h qml/qqmlabstractbinding_p.h qml/qqmlapplicationengine_p.h qml/qqmlbinding_p.h qml/qqmlboundsignal_p.h qml/qqmlboundsignalexpressionpointer_p.h qml/qqmlcleanup_p.h qml/qqmlcomponent_p.h qml/qqmlcomponentattached_p.h qml/qqmlcontext_p.h qml/qqmlcustomparser_p.h qml/qqmldata_p.h qml/qqmldelayedcallqueue_p.h qml/qqmldirparser_p.h qml/qqmlengine_p.h qml/qqmlexpression_p.h qml/qqmlextensionplugin_p.h qml/qqmlfileselector_p.h qml/qqmlglobal_p.h qml/qqmlguard_p.h qml/qqmlimport_p.h qml/qqmlincubator_p.h qml/qqmljavascriptexpression_p.h qml/qqmllist_p.h qml/qqmllistwrapper_p.h qml/qqmllocale_p.h qml/qqmlloggingcategory_p.h qml/qqmlmetatype_p.h qml/qqmlnotifier_p.h qml/qqmlobjectcreator_p.h qml/qqmlopenmetaobject_p.h qml/qqmlplatform_p.h qml/qqmlproperty_p.h qml/qqmlpropertycache_p.h qml/qqmlpropertyindex_p.h qml/qqmlpropertyvalueinterceptor_p.h qml/qqmlproxymetaobject_p.h qml/qqmlscriptstring_p.h qml/qqmlstringconverters_p.h qml/qqmltypeloader_p.h qml/qqmltypenamecache_p.h qml/qqmltypenotavailable_p.h qml/qqmltypewrapper_p.h qml/qqmlvaluetype_p.h qml/qqmlvaluetypeproxybinding_p.h qml/qqmlvaluetypewrapper_p.h qml/qqmlvme_p.h qml/qqmlvmemetaobject_p.h qml/qqmlxmlhttprequest_p.h types/qqmlbind_p.h types/qqmlconnections_p.h types/qqmldelegatecomponent_p.h types/qqmldelegatemodel_p.h types/qqmldelegatemodel_p_p.h types/qqmlinstantiator_p.h types/qqmlinstantiator_p_p.h types/qqmllistmodel_p.h types/qqmllistmodel_p_p.h types/qqmllistmodelworkeragent_p.h types/qqmlmodelindexvaluetype_p.h types/qqmlmodelsmodule_p.h types/qqmlobjectmodel_p.h types/qqmltableinstancemodel_p.h types/qqmltimer_p.h types/qquickpackage_p.h types/qquickworkerscript_p.h util/qqmladaptormodel_p.h util/qqmlchangeset_p.h util/qqmllistaccessor_p.h util/qqmllistcompositor_p.h qml/ftw/qbitfield_p.h qml/ftw/qfieldlist_p.h qml/ftw/qfinitestack_p.h qml/ftw/qflagpointer_p.h qml/ftw/qhashedstring_p.h qml/ftw/qintrusivelist_p.h qml/ftw/qlazilyallocated_p.h qml/ftw/qpodvector_p.h qml/ftw/qqmlnullablevalue_p.h qml/ftw/qqmlrefcount_p.h qml/ftw/qqmlthread_p.h qml/ftw/qrecursionwatcher_p.h qml/ftw/qrecyclepool_p.h qml/v8/qqmlbuiltinfunctions_p.h qml/v8/qv4domerrors_p.h qml/v8/qv4sqlerrors_p.h qml/v8/qv8engine_p.h 0062 +SYNCQT.PRIVATE_HEADER_FILES = qtqmlglobal_p.h animations/qabstractanimationjob_p.h animations/qanimationgroupjob_p.h animations/qanimationjobutil_p.h animations/qcontinuinganimationgroupjob_p.h animations/qparallelanimationgroupjob_p.h animations/qpauseanimationjob_p.h animations/qsequentialanimationgroupjob_p.h compiler/qqmlirbuilder_p.h compiler/qqmlpropertycachecreator_p.h compiler/qqmlpropertyvalidator_p.h compiler/qqmltypecompiler_p.h compiler/qv4bytecodegenerator_p.h compiler/qv4bytecodehandler_p.h compiler/qv4codegen_p.h compiler/qv4compilationunitmapper_p.h compiler/qv4compileddata_p.h compiler/qv4compiler_p.h compiler/qv4compilercontext_p.h compiler/qv4compilercontrolflow_p.h compiler/qv4compilerscanfunctions_p.h compiler/qv4instr_moth_p.h debugger/qqmlabstractprofileradapter_p.h debugger/qqmlconfigurabledebugservice_p.h debugger/qqmldebugconnector_p.h debugger/qqmldebugpluginmanager_p.h debugger/qqmldebugserver_p.h debugger/qqmldebugserverconnection_p.h debugger/qqmldebugservice_p.h debugger/qqmldebugservicefactory_p.h debugger/qqmldebugserviceinterfaces_p.h debugger/qqmldebugstatesdelegate_p.h debugger/qqmlmemoryprofiler_p.h debugger/qqmlprofiler_p.h debugger/qqmlprofilerdefinitions_p.h jit/qv4assemblercommon_p.h jit/qv4baselineassembler_p.h jit/qv4baselinejit_p.h jit/qv4jithelpers_p.h jsapi/qjsengine_p.h jsapi/qjsvalue_p.h jsapi/qjsvalueiterator_p.h jsruntime/qv4alloca_p.h jsruntime/qv4argumentsobject_p.h jsruntime/qv4arraybuffer_p.h jsruntime/qv4arraydata_p.h jsruntime/qv4arrayiterator_p.h jsruntime/qv4arrayobject_p.h jsruntime/qv4atomics_p.h jsruntime/qv4booleanobject_p.h jsruntime/qv4context_p.h jsruntime/qv4dataview_p.h jsruntime/qv4dateobject_p.h jsruntime/qv4debugging_p.h jsruntime/qv4engine_p.h jsruntime/qv4enginebase_p.h jsruntime/qv4errorobject_p.h jsruntime/qv4estable_p.h jsruntime/qv4executableallocator_p.h jsruntime/qv4function_p.h jsruntime/qv4functionobject_p.h jsruntime/qv4functiontable_p.h jsruntime/qv4generatorobject_p.h jsruntime/qv4global_p.h jsruntime/qv4globalobject_p.h jsruntime/qv4identifier_p.h jsruntime/qv4identifiertable_p.h jsruntime/qv4include_p.h jsruntime/qv4internalclass_p.h jsruntime/qv4iterator_p.h jsruntime/qv4jscall_p.h jsruntime/qv4jsonobject_p.h jsruntime/qv4lookup_p.h jsruntime/qv4managed_p.h jsruntime/qv4mapiterator_p.h jsruntime/qv4mapobject_p.h jsruntime/qv4math_p.h jsruntime/qv4mathobject_p.h jsruntime/qv4memberdata_p.h jsruntime/qv4module_p.h jsruntime/qv4numberobject_p.h jsruntime/qv4object_p.h jsruntime/qv4objectiterator_p.h jsruntime/qv4objectproto_p.h jsruntime/qv4persistent_p.h jsruntime/qv4profiling_p.h jsruntime/qv4promiseobject_p.h jsruntime/qv4property_p.h jsruntime/qv4propertykey_p.h jsruntime/qv4proxy_p.h jsruntime/qv4qmlcontext_p.h jsruntime/qv4qobjectwrapper_p.h jsruntime/qv4reflect_p.h jsruntime/qv4regexp_p.h jsruntime/qv4regexpobject_p.h jsruntime/qv4runtime_p.h jsruntime/qv4runtimeapi_p.h jsruntime/qv4runtimecodegen_p.h jsruntime/qv4scopedvalue_p.h jsruntime/qv4script_p.h jsruntime/qv4sequenceobject_p.h jsruntime/qv4serialize_p.h jsruntime/qv4setiterator_p.h jsruntime/qv4setobject_p.h jsruntime/qv4sparsearray_p.h jsruntime/qv4stackframe_p.h jsruntime/qv4string_p.h jsruntime/qv4stringiterator_p.h jsruntime/qv4stringobject_p.h jsruntime/qv4symbol_p.h jsruntime/qv4typedarray_p.h jsruntime/qv4util_p.h jsruntime/qv4value_p.h jsruntime/qv4variantobject_p.h jsruntime/qv4vme_moth_p.h jsruntime/qv4vtable_p.h memory/qv4heap_p.h memory/qv4mm_p.h memory/qv4mmdefs_p.h memory/qv4writebarrier_p.h parser/qqmljsast_p.h parser/qqmljsastfwd_p.h parser/qqmljsastvisitor_p.h parser/qqmljsengine_p.h parser/qqmljsglobal_p.h parser/qqmljskeywords_p.h parser/qqmljslexer_p.h parser/qqmljsmemorypool_p.h qml/qqmlabstractbinding_p.h qml/qqmlapplicationengine_p.h qml/qqmlbinding_p.h qml/qqmlboundsignal_p.h qml/qqmlboundsignalexpressionpointer_p.h qml/qqmlcleanup_p.h qml/qqmlcomponent_p.h qml/qqmlcomponentattached_p.h qml/qqmlcontext_p.h qml/qqmlcustomparser_p.h qml/qqmldata_p.h qml/qqmldelayedcallqueue_p.h qml/qqmldirparser_p.h qml/qqmlengine_p.h qml/qqmlexpression_p.h qml/qqmlextensionplugin_p.h qml/qqmlfileselector_p.h qml/qqmlglobal_p.h qml/qqmlguard_p.h qml/qqmlimport_p.h qml/qqmlincubator_p.h qml/qqmljavascriptexpression_p.h qml/qqmllist_p.h qml/qqmllistwrapper_p.h qml/qqmllocale_p.h qml/qqmlloggingcategory_p.h qml/qqmlmetatype_p.h qml/qqmlnotifier_p.h qml/qqmlobjectcreator_p.h qml/qqmlopenmetaobject_p.h qml/qqmlplatform_p.h qml/qqmlproperty_p.h qml/qqmlpropertycache_p.h qml/qqmlpropertyindex_p.h qml/qqmlpropertyvalueinterceptor_p.h qml/qqmlproxymetaobject_p.h qml/qqmlscriptstring_p.h qml/qqmlstringconverters_p.h qml/qqmltypeloader_p.h qml/qqmltypenamecache_p.h qml/qqmltypenotavailable_p.h qml/qqmltypewrapper_p.h qml/qqmlvaluetype_p.h qml/qqmlvaluetypeproxybinding_p.h qml/qqmlvaluetypewrapper_p.h qml/qqmlvme_p.h qml/qqmlvmemetaobject_p.h qml/qqmlxmlhttprequest_p.h types/qqmlbind_p.h types/qqmlconnections_p.h types/qqmldelegatecomponent_p.h types/qqmldelegatemodel_p.h types/qqmldelegatemodel_p_p.h types/qqmlinstantiator_p.h types/qqmlinstantiator_p_p.h types/qqmllistmodel_p.h types/qqmllistmodel_p_p.h types/qqmllistmodelworkeragent_p.h types/qqmlmodelindexvaluetype_p.h types/qqmlmodelsmodule_p.h types/qqmlobjectmodel_p.h types/qqmltableinstancemodel_p.h types/qqmltimer_p.h types/qquickpackage_p.h types/qquickworkerscript_p.h util/qqmladaptormodel_p.h util/qqmlchangeset_p.h util/qqmllistaccessor_p.h util/qqmllistcompositor_p.h qml/ftw/qbitfield_p.h qml/ftw/qfieldlist_p.h qml/ftw/qfinitestack_p.h qml/ftw/qflagpointer_p.h qml/ftw/qhashedstring_p.h qml/ftw/qintrusivelist_p.h qml/ftw/qlazilyallocated_p.h qml/ftw/qpodvector_p.h qml/ftw/qqmlnullablevalue_p.h qml/ftw/qqmlrefcount_p.h qml/ftw/qqmlthread_p.h qml/ftw/qrecursionwatcher_p.h qml/ftw/qrecyclepool_p.h qml/v8/qqmlbuiltinfunctions_p.h qml/v8/qv4domerrors_p.h qml/v8/qv4sqlerrors_p.h qml/v8/qv8engine_p.h 0063 SYNCQT.QPA_HEADER_FILES = 0064 SYNCQT.CLEAN_HEADER_FILES = qtqmlglobal.h debugger/qqmldebug.h jsapi/qjsengine.h jsapi/qjsvalue.h jsapi/qjsvalueiterator.h qml/qqml.h qml/qqmlabstracturlinterceptor.h qml/qqmlapplicationengine.h qml/qqmlcomponent.h qml/qqmlcontext.h qml/qqmlengine.h qml/qqmlerror.h qml/qqmlexpression.h qml/qqmlextensioninterface.h qml/qqmlextensionplugin.h qml/qqmlfile.h qml/qqmlfileselector.h qml/qqmlincubator.h qml/qqmlinfo.h qml/qqmllist.h qml/qqmlnetworkaccessmanagerfactory.h qml/qqmlparserstatus.h qml/qqmlprivate.h qml/qqmlproperty.h qml/qqmlpropertyvaluesource.h qml/qqmlscriptstring.h util/qqmlpropertymap.h 0065 SYNCQT.INJECTIONS = src/qml/qqmljsgrammar_p.h:^5.12.12/QtQml/private/qqmljsgrammar_p.h src/qml/qqmljsparser_p.h:^5.12.12/QtQml/private/qqmljsparser_p.h 0066 diff --git a/src/3rdparty/masm/assembler/LinkBuffer.h b/src/3rdparty/masm/assembler/LinkBuffer.h 0067 index 7f997930..a1bb046d 100644 0068 --- a/src/3rdparty/masm/assembler/LinkBuffer.h 0069 +++ b/src/3rdparty/masm/assembler/LinkBuffer.h 0070 @@ -228,6 +228,8 @@ public: 0071 return m_size; 0072 } 0073 0074 + inline void makeExecutable(); 0075 + 0076 private: 0077 template <typename T> T applyOffset(T src) 0078 { 0079 @@ -353,6 +355,11 @@ void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::performFinaliza 0080 0081 ASSERT(m_size <= INT_MAX); 0082 MacroAssembler::cacheFlush(code(), m_size); 0083 +} 0084 + 0085 +template <typename MacroAssembler, template <typename T> class ExecutableOffsetCalculator> 0086 +inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::makeExecutable() 0087 +{ 0088 ExecutableAllocator::makeExecutable(code(), static_cast<int>(m_size)); 0089 } 0090 0091 @@ -389,6 +396,7 @@ public: 0092 } 0093 0094 virtual void performFinalization() override final; 0095 + inline void makeExecutable(); 0096 0097 inline void linkCode(void* ownerUID, JITCompilationEffort); 0098 0099 @@ -421,6 +429,11 @@ void BranchCompactingLinkBuffer<MacroAssembler>::performFinalization() 0100 #endif 0101 0102 MacroAssembler::cacheFlush(code(), m_size); 0103 +} 0104 + 0105 +template <typename MacroAssembler> 0106 +inline void BranchCompactingLinkBuffer<MacroAssembler>::makeExecutable() 0107 +{ 0108 ExecutableAllocator::makeExecutable(code(), m_initialSize); 0109 } 0110 0111 diff --git a/src/3rdparty/masm/stubs/ExecutableAllocator.h b/src/3rdparty/masm/stubs/ExecutableAllocator.h 0112 index 156b24b4..a439c538 100644 0113 --- a/src/3rdparty/masm/stubs/ExecutableAllocator.h 0114 +++ b/src/3rdparty/masm/stubs/ExecutableAllocator.h 0115 @@ -82,6 +82,7 @@ struct ExecutableMemoryHandle : public RefCounted<ExecutableMemoryHandle> { 0116 0117 inline bool isManaged() const { return true; } 0118 0119 + void *exceptionHandler() { return m_allocation->exceptionHandler(); } 0120 void *start() { return m_allocation->start(); } 0121 size_t sizeInBytes() { return m_size; } 0122 0123 diff --git a/src/3rdparty/masm/yarr/YarrJIT.cpp b/src/3rdparty/masm/yarr/YarrJIT.cpp 0124 index dee2ade4..98e4ade5 100644 0125 --- a/src/3rdparty/masm/yarr/YarrJIT.cpp 0126 +++ b/src/3rdparty/masm/yarr/YarrJIT.cpp 0127 @@ -33,6 +33,8 @@ 0128 #include "Yarr.h" 0129 #include "YarrCanonicalize.h" 0130 0131 +#include <private/qv4functiontable_p.h> 0132 + 0133 #if ENABLE(YARR_JIT) 0134 0135 using namespace WTF; 0136 @@ -3529,17 +3531,30 @@ public: 0137 0138 m_backtrackingState.linkDataLabels(linkBuffer); 0139 0140 + CodeRef codeRef; 0141 if (compileMode == MatchOnly) { 0142 - if (m_charSize == Char8) 0143 - codeBlock.set8BitCodeMatchOnly(FINALIZE_CODE(linkBuffer, "YarrJIT", "Match-only 8-bit regular expression")); 0144 - else 0145 - codeBlock.set16BitCodeMatchOnly(FINALIZE_CODE(linkBuffer, "YarrJIT", "Match-only 16-bit regular expression")); 0146 + if (m_charSize == Char8) { 0147 + codeRef = FINALIZE_CODE(linkBuffer, "YarJIT", 0148 + "Match-only 8-bit regular expression"); 0149 + codeBlock.set8BitCodeMatchOnly(codeRef); 0150 + } else { 0151 + codeRef = FINALIZE_CODE(linkBuffer, "YarJIT", 0152 + "Match-only 16-bit regular expression"); 0153 + codeBlock.set16BitCodeMatchOnly(codeRef); 0154 + } 0155 } else { 0156 - if (m_charSize == Char8) 0157 - codeBlock.set8BitCode(FINALIZE_CODE(linkBuffer, "YarrJIT", "8-bit regular expression")); 0158 - else 0159 - codeBlock.set16BitCode(FINALIZE_CODE(linkBuffer, "YarrJIT", "16-bit regular expression")); 0160 + if (m_charSize == Char8) { 0161 + codeRef = FINALIZE_CODE(linkBuffer, "YarJIT", "8-bit regular expression"); 0162 + codeBlock.set8BitCode(codeRef); 0163 + } else { 0164 + codeRef = FINALIZE_CODE(linkBuffer, "YarJIT", "16-bit regular expression"); 0165 + codeBlock.set16BitCode(codeRef); 0166 + } 0167 } 0168 + QV4::generateFunctionTable(nullptr, &codeRef); 0169 + 0170 + linkBuffer.makeExecutable(); 0171 + 0172 if (m_failureReason) 0173 codeBlock.setFallBackWithFailureReason(*m_failureReason); 0174 } 0175 @@ -3587,6 +3602,15 @@ private: 0176 BacktrackingState m_backtrackingState; 0177 }; 0178 0179 +void YarrCodeBlock::replaceCodeRef(MacroAssemblerCodeRef &target, 0180 + const MacroAssemblerCodeRef &source) 0181 +{ 0182 + if (!!target && target.code().executableAddress() != source.code().executableAddress()) 0183 + QV4::destroyFunctionTable(nullptr, &target); 0184 + 0185 + target = source; 0186 +} 0187 + 0188 static void dumpCompileFailure(JITFailureReason failure) 0189 { 0190 switch (failure) { 0191 diff --git a/src/3rdparty/masm/yarr/YarrJIT.h b/src/3rdparty/masm/yarr/YarrJIT.h 0192 index 8b6b3a75..35a0690f 100644 0193 --- a/src/3rdparty/masm/yarr/YarrJIT.h 0194 +++ b/src/3rdparty/masm/yarr/YarrJIT.h 0195 @@ -82,19 +82,28 @@ class YarrCodeBlock { 0196 0197 public: 0198 YarrCodeBlock() = default; 0199 + ~YarrCodeBlock() { clear(); } 0200 + 0201 + static void replaceCodeRef(MacroAssemblerCodeRef &target, const MacroAssemblerCodeRef &source); 0202 0203 void setFallBackWithFailureReason(JITFailureReason failureReason) { m_failureReason = failureReason; } 0204 std::optional<JITFailureReason> failureReason() { return m_failureReason; } 0205 0206 bool has8BitCode() { return m_ref8.size(); } 0207 bool has16BitCode() { return m_ref16.size(); } 0208 - void set8BitCode(MacroAssemblerCodeRef ref) { m_ref8 = ref; } 0209 - void set16BitCode(MacroAssemblerCodeRef ref) { m_ref16 = ref; } 0210 + void set8BitCode(MacroAssemblerCodeRef ref) { replaceCodeRef(m_ref8, ref); } 0211 + void set16BitCode(MacroAssemblerCodeRef ref) { replaceCodeRef(m_ref16, ref); } 0212 0213 bool has8BitCodeMatchOnly() { return m_matchOnly8.size(); } 0214 bool has16BitCodeMatchOnly() { return m_matchOnly16.size(); } 0215 - void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly8 = matchOnly; } 0216 - void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly16 = matchOnly; } 0217 + void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) 0218 + { 0219 + replaceCodeRef(m_matchOnly8, matchOnly); 0220 + } 0221 + void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) 0222 + { 0223 + replaceCodeRef(m_matchOnly16, matchOnly); 0224 + } 0225 0226 #if ENABLE(YARR_JIT_ALL_PARENS_EXPRESSIONS) 0227 bool usesPatternContextBuffer() { return m_usesPatternContextBuffer; } 0228 @@ -190,10 +199,10 @@ public: 0229 0230 void clear() 0231 { 0232 - m_ref8 = MacroAssemblerCodeRef(); 0233 - m_ref16 = MacroAssemblerCodeRef(); 0234 - m_matchOnly8 = MacroAssemblerCodeRef(); 0235 - m_matchOnly16 = MacroAssemblerCodeRef(); 0236 + replaceCodeRef(m_ref8, MacroAssemblerCodeRef()); 0237 + replaceCodeRef(m_ref16, MacroAssemblerCodeRef()); 0238 + replaceCodeRef(m_matchOnly8, MacroAssemblerCodeRef()); 0239 + replaceCodeRef(m_matchOnly16, MacroAssemblerCodeRef()); 0240 m_failureReason = std::nullopt; 0241 } 0242 0243 diff --git a/src/qml/jit/qv4assemblercommon.cpp b/src/qml/jit/qv4assemblercommon.cpp 0244 index 831496a6..6dc40ad8 100644 0245 --- a/src/qml/jit/qv4assemblercommon.cpp 0246 +++ b/src/qml/jit/qv4assemblercommon.cpp 0247 @@ -43,6 +43,7 @@ 0248 #include "qv4engine_p.h" 0249 #include "qv4assemblercommon_p.h" 0250 #include <private/qv4function_p.h> 0251 +#include <private/qv4functiontable_p.h> 0252 #include <private/qv4runtime_p.h> 0253 0254 #include <assembler/MacroAssemblerCodeRef.h> 0255 @@ -112,17 +113,6 @@ static void printDisassembledOutputWithCalls(QByteArray processedOutput, 0256 qDebug("%s", processedOutput.constData()); 0257 } 0258 0259 -static QByteArray functionName(Function *function) 0260 -{ 0261 - QByteArray name = function->name()->toQString().toUtf8(); 0262 - if (name.isEmpty()) { 0263 - name = QByteArray::number(reinterpret_cast<quintptr>(function), 16); 0264 - name.prepend("QV4::Function(0x"); 0265 - name.append(')'); 0266 - } 0267 - return name; 0268 -} 0269 - 0270 JIT::PlatformAssemblerCommon::~PlatformAssemblerCommon() 0271 {} 0272 0273 @@ -147,7 +137,9 @@ void PlatformAssemblerCommon::link(Function *function, const char *jitKind) 0274 buf.open(QIODevice::WriteOnly); 0275 WTF::setDataFile(new QIODevicePrintStream(&buf)); 0276 0277 - QByteArray name = functionName(function); 0278 + // We use debugAddress here because it's actually for debugging and hidden behind an 0279 + // environment variable. 0280 + const QByteArray name = Function::prettyName(function, linkBuffer.debugAddress()).toUtf8(); 0281 codeRef = linkBuffer.finalizeCodeWithDisassembly(jitKind, "function %s", name.constData()); 0282 0283 WTF::setDataFile(stderr); 0284 @@ -159,31 +151,9 @@ void PlatformAssemblerCommon::link(Function *function, const char *jitKind) 0285 function->codeRef = new JSC::MacroAssemblerCodeRef(codeRef); 0286 function->jittedCode = reinterpret_cast<Function::JittedCode>(function->codeRef->code().executableAddress()); 0287 0288 - // This implements writing of JIT'd addresses so that perf can find the 0289 - // symbol names. 0290 - // 0291 - // Perf expects the mapping to be in a certain place and have certain 0292 - // content, for more information, see: 0293 - // https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt 0294 - static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP"); 0295 - if (Q_UNLIKELY(doProfile)) { 0296 - static QFile perfMapFile(QString::fromLatin1("/tmp/perf-%1.map") 0297 - .arg(QCoreApplication::applicationPid())); 0298 - static const bool isOpen = perfMapFile.open(QIODevice::WriteOnly); 0299 - if (!isOpen) { 0300 - qWarning("QV4::JIT::Assembler: Cannot write perf map file."); 0301 - doProfile = false; 0302 - } else { 0303 - perfMapFile.write(QByteArray::number(reinterpret_cast<quintptr>( 0304 - codeRef.code().executableAddress()), 16)); 0305 - perfMapFile.putChar(' '); 0306 - perfMapFile.write(QByteArray::number(static_cast<qsizetype>(codeRef.size()), 16)); 0307 - perfMapFile.putChar(' '); 0308 - perfMapFile.write(functionName(function)); 0309 - perfMapFile.putChar('\n'); 0310 - perfMapFile.flush(); 0311 - } 0312 - } 0313 + generateFunctionTable(function, &codeRef); 0314 + 0315 + linkBuffer.makeExecutable(); 0316 } 0317 0318 void PlatformAssemblerCommon::prepareCallWithArgCount(int argc) 0319 diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri 0320 index 5ec55b96..b0562ef8 100644 0321 --- a/src/qml/jsruntime/jsruntime.pri 0322 +++ b/src/qml/jsruntime/jsruntime.pri 0323 @@ -142,6 +142,7 @@ qtConfig(qml-sequence-object) { 0324 0325 0326 HEADERS += \ 0327 + $$PWD/qv4functiontable_p.h \ 0328 $$PWD/qv4runtime_p.h \ 0329 $$PWD/qv4runtimeapi_p.h \ 0330 $$PWD/qv4value_p.h \ 0331 @@ -156,6 +157,23 @@ SOURCES += \ 0332 $$PWD/qv4value.cpp \ 0333 $$PWD/qv4executableallocator.cpp 0334 0335 +qmldevtools_build { 0336 + SOURCES += \ 0337 + $$PWD/qv4functiontable_noop.cpp 0338 +} else:win32 { 0339 + equals(QT_ARCH, x86_64){ 0340 + SOURCES += \ 0341 + $$PWD/qv4functiontable_win64.cpp 0342 + } else { 0343 + SOURCES += \ 0344 + $$PWD/qv4functiontable_noop.cpp 0345 + } 0346 +} else { 0347 + SOURCES += \ 0348 + $$PWD/qv4functiontable_unix.cpp 0349 +} 0350 + 0351 + 0352 valgrind { 0353 DEFINES += V4_USE_VALGRIND 0354 } 0355 diff --git a/src/qml/jsruntime/qv4executableallocator.cpp b/src/qml/jsruntime/qv4executableallocator.cpp 0356 index 6f04a712..c836d121 100644 0357 --- a/src/qml/jsruntime/qv4executableallocator.cpp 0358 +++ b/src/qml/jsruntime/qv4executableallocator.cpp 0359 @@ -38,17 +38,23 @@ 0360 ****************************************************************************/ 0361 0362 #include "qv4executableallocator_p.h" 0363 +#include "qv4functiontable_p.h" 0364 0365 #include <wtf/StdLibExtras.h> 0366 #include <wtf/PageAllocation.h> 0367 0368 using namespace QV4; 0369 0370 -void *ExecutableAllocator::Allocation::start() const 0371 +void *ExecutableAllocator::Allocation::exceptionHandler() const 0372 { 0373 return reinterpret_cast<void*>(addr); 0374 } 0375 0376 +void *ExecutableAllocator::Allocation::start() const 0377 +{ 0378 + return reinterpret_cast<void*>(addr + exceptionHandlerSize()); 0379 +} 0380 + 0381 void ExecutableAllocator::Allocation::deallocate(ExecutableAllocator *allocator) 0382 { 0383 if (isValid()) 0384 @@ -162,7 +168,7 @@ ExecutableAllocator::Allocation *ExecutableAllocator::allocate(size_t size) 0385 Allocation *allocation = nullptr; 0386 0387 // Code is best aligned to 16-byte boundaries. 0388 - size = WTF::roundUpToMultipleOf(16, size); 0389 + size = WTF::roundUpToMultipleOf(16, size + exceptionHandlerSize()); 0390 0391 QMultiMap<size_t, Allocation*>::Iterator it = freeAllocations.lowerBound(size); 0392 if (it != freeAllocations.end()) { 0393 diff --git a/src/qml/jsruntime/qv4executableallocator_p.h b/src/qml/jsruntime/qv4executableallocator_p.h 0394 index 375c9a36..013c6d71 100644 0395 --- a/src/qml/jsruntime/qv4executableallocator_p.h 0396 +++ b/src/qml/jsruntime/qv4executableallocator_p.h 0397 @@ -86,6 +86,7 @@ public: 0398 , free(true) 0399 {} 0400 0401 + void *exceptionHandler() const; 0402 void *start() const; 0403 void invalidate() { addr = 0; } 0404 bool isValid() const { return addr != 0; } 0405 diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp 0406 index 51a9b929..55fca618 100644 0407 --- a/src/qml/jsruntime/qv4function.cpp 0408 +++ b/src/qml/jsruntime/qv4function.cpp 0409 @@ -46,6 +46,7 @@ 0410 #include "qv4lookup_p.h" 0411 #include <private/qv4mm_p.h> 0412 #include <private/qv4identifiertable_p.h> 0413 +#include "qv4functiontable_p.h" 0414 #include <assembler/MacroAssemblerCodeRef.h> 0415 #include <private/qv4vme_moth_p.h> 0416 #include <private/qqmlglobal_p.h> 0417 @@ -97,7 +98,10 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, 0418 0419 Function::~Function() 0420 { 0421 - delete codeRef; 0422 + if (codeRef) { 0423 + destroyFunctionTable(this, codeRef); 0424 + delete codeRef; 0425 + } 0426 } 0427 0428 void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> ¶meters) 0429 @@ -144,6 +148,17 @@ void Function::updateInternalClass(ExecutionEngine *engine, const QList<QByteArr 0430 nFormals = parameters.size(); 0431 } 0432 0433 +QString Function::prettyName(const Function *function, const void *code) 0434 +{ 0435 + QString prettyName = function ? function->name()->toQString() : QString(); 0436 + if (prettyName.isEmpty()) { 0437 + prettyName = QString::number(reinterpret_cast<quintptr>(code), 16); 0438 + prettyName.prepend(QLatin1String("QV4::Function(0x")); 0439 + prettyName.append(QLatin1Char(')')); 0440 + } 0441 + return prettyName; 0442 +} 0443 + 0444 QQmlSourceLocation Function::sourceLocation() const 0445 { 0446 return QQmlSourceLocation(sourceFile(), compiledFunction->location.line, compiledFunction->location.column); 0447 diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h 0448 index 62c5d24f..859b6a87 100644 0449 --- a/src/qml/jsruntime/qv4function_p.h 0450 +++ b/src/qml/jsruntime/qv4function_p.h 0451 @@ -88,9 +88,12 @@ struct Q_QML_EXPORT Function { 0452 // used when dynamically assigning signal handlers (QQmlConnection) 0453 void updateInternalClass(ExecutionEngine *engine, const QList<QByteArray> ¶meters); 0454 0455 - inline Heap::String *name() { 0456 + inline Heap::String *name() const { 0457 return compilationUnit->runtimeStrings[compiledFunction->nameIndex]; 0458 } 0459 + 0460 + static QString prettyName(const Function *function, const void *address); 0461 + 0462 inline QString sourceFile() const { return compilationUnit->fileName(); } 0463 inline QUrl finalUrl() const { return compilationUnit->finalUrl(); } 0464 0465 diff --git a/src/qml/jsruntime/qv4functiontable_noop.cpp b/src/qml/jsruntime/qv4functiontable_noop.cpp 0466 new file mode 100644 0467 index 00000000..31c198eb 0468 --- /dev/null 0469 +++ b/src/qml/jsruntime/qv4functiontable_noop.cpp 0470 @@ -0,0 +1,65 @@ 0471 +/**************************************************************************** 0472 +** 0473 +** Copyright (C) 2017 The Qt Company Ltd. 0474 +** Contact: https://www.qt.io/licensing/ 0475 +** 0476 +** This file is part of the QtQml module of the Qt Toolkit. 0477 +** 0478 +** $QT_BEGIN_LICENSE:LGPL$ 0479 +** Commercial License Usage 0480 +** Licensees holding valid commercial Qt licenses may use this file in 0481 +** accordance with the commercial license agreement provided with the 0482 +** Software or, alternatively, in accordance with the terms contained in 0483 +** a written agreement between you and The Qt Company. For licensing terms 0484 +** and conditions see https://www.qt.io/terms-conditions. For further 0485 +** information use the contact form at https://www.qt.io/contact-us. 0486 +** 0487 +** GNU Lesser General Public License Usage 0488 +** Alternatively, this file may be used under the terms of the GNU Lesser 0489 +** General Public License version 3 as published by the Free Software 0490 +** Foundation and appearing in the file LICENSE.LGPL3 included in the 0491 +** packaging of this file. Please review the following information to 0492 +** ensure the GNU Lesser General Public License version 3 requirements 0493 +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 0494 +** 0495 +** GNU General Public License Usage 0496 +** Alternatively, this file may be used under the terms of the GNU 0497 +** General Public License version 2.0 or (at your option) the GNU General 0498 +** Public license version 3 or any later version approved by the KDE Free 0499 +** Qt Foundation. The licenses are as published by the Free Software 0500 +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 0501 +** included in the packaging of this file. Please review the following 0502 +** information to ensure the GNU General Public License requirements will 0503 +** be met: https://www.gnu.org/licenses/gpl-2.0.html and 0504 +** https://www.gnu.org/licenses/gpl-3.0.html. 0505 +** 0506 +** $QT_END_LICENSE$ 0507 +** 0508 +****************************************************************************/ 0509 + 0510 +#include "qv4functiontable_p.h" 0511 + 0512 +QT_BEGIN_NAMESPACE 0513 + 0514 +namespace QV4 { 0515 + 0516 +void generateFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef) 0517 +{ 0518 + Q_UNUSED(function); 0519 + Q_UNUSED(codeRef); 0520 +} 0521 + 0522 +void destroyFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef) 0523 +{ 0524 + Q_UNUSED(function); 0525 + Q_UNUSED(codeRef); 0526 +} 0527 + 0528 +size_t exceptionHandlerSize() 0529 +{ 0530 + return 0; 0531 +} 0532 + 0533 +} // QV4 0534 + 0535 +QT_END_NAMESPACE 0536 diff --git a/src/qml/jsruntime/qv4functiontable_p.h b/src/qml/jsruntime/qv4functiontable_p.h 0537 new file mode 100644 0538 index 00000000..69e3d2bd 0539 --- /dev/null 0540 +++ b/src/qml/jsruntime/qv4functiontable_p.h 0541 @@ -0,0 +1,75 @@ 0542 +/**************************************************************************** 0543 +** 0544 +** Copyright (C) 2018 The Qt Company Ltd. 0545 +** Contact: https://www.qt.io/licensing/ 0546 +** 0547 +** This file is part of the QtQml module of the Qt Toolkit. 0548 +** 0549 +** $QT_BEGIN_LICENSE:LGPL$ 0550 +** Commercial License Usage 0551 +** Licensees holding valid commercial Qt licenses may use this file in 0552 +** accordance with the commercial license agreement provided with the 0553 +** Software or, alternatively, in accordance with the terms contained in 0554 +** a written agreement between you and The Qt Company. For licensing terms 0555 +** and conditions see https://www.qt.io/terms-conditions. For further 0556 +** information use the contact form at https://www.qt.io/contact-us. 0557 +** 0558 +** GNU Lesser General Public License Usage 0559 +** Alternatively, this file may be used under the terms of the GNU Lesser 0560 +** General Public License version 3 as published by the Free Software 0561 +** Foundation and appearing in the file LICENSE.LGPL3 included in the 0562 +** packaging of this file. Please review the following information to 0563 +** ensure the GNU Lesser General Public License version 3 requirements 0564 +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 0565 +** 0566 +** GNU General Public License Usage 0567 +** Alternatively, this file may be used under the terms of the GNU 0568 +** General Public License version 2.0 or (at your option) the GNU General 0569 +** Public license version 3 or any later version approved by the KDE Free 0570 +** Qt Foundation. The licenses are as published by the Free Software 0571 +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 0572 +** included in the packaging of this file. Please review the following 0573 +** information to ensure the GNU General Public License requirements will 0574 +** be met: https://www.gnu.org/licenses/gpl-2.0.html and 0575 +** https://www.gnu.org/licenses/gpl-3.0.html. 0576 +** 0577 +** $QT_END_LICENSE$ 0578 +** 0579 +****************************************************************************/ 0580 + 0581 +#ifndef QV4FUNCTIONTABLE_P_H 0582 +#define QV4FUNCTIONTABLE_P_H 0583 + 0584 +// 0585 +// W A R N I N G 0586 +// ------------- 0587 +// 0588 +// This file is not part of the Qt API. It exists purely as an 0589 +// implementation detail. This header file may change from version to 0590 +// version without notice, or even be removed. 0591 +// 0592 +// We mean it. 0593 +// 0594 + 0595 +#include "qv4global_p.h" 0596 + 0597 +namespace JSC { 0598 +class MacroAssemblerCodeRef; 0599 +} 0600 + 0601 +QT_BEGIN_NAMESPACE 0602 + 0603 +namespace QV4 { 0604 + 0605 +struct Function; 0606 + 0607 +void generateFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef); 0608 +void destroyFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef); 0609 + 0610 +size_t exceptionHandlerSize(); 0611 + 0612 +} 0613 + 0614 +QT_END_NAMESPACE 0615 + 0616 +#endif // QV4FUNCTIONTABLE_P_H 0617 diff --git a/src/qml/jsruntime/qv4functiontable_unix.cpp b/src/qml/jsruntime/qv4functiontable_unix.cpp 0618 new file mode 100644 0619 index 00000000..25b5c271 0620 --- /dev/null 0621 +++ b/src/qml/jsruntime/qv4functiontable_unix.cpp 0622 @@ -0,0 +1,99 @@ 0623 +/**************************************************************************** 0624 +** 0625 +** Copyright (C) 2017 The Qt Company Ltd. 0626 +** Contact: https://www.qt.io/licensing/ 0627 +** 0628 +** This file is part of the QtQml module of the Qt Toolkit. 0629 +** 0630 +** $QT_BEGIN_LICENSE:LGPL$ 0631 +** Commercial License Usage 0632 +** Licensees holding valid commercial Qt licenses may use this file in 0633 +** accordance with the commercial license agreement provided with the 0634 +** Software or, alternatively, in accordance with the terms contained in 0635 +** a written agreement between you and The Qt Company. For licensing terms 0636 +** and conditions see https://www.qt.io/terms-conditions. For further 0637 +** information use the contact form at https://www.qt.io/contact-us. 0638 +** 0639 +** GNU Lesser General Public License Usage 0640 +** Alternatively, this file may be used under the terms of the GNU Lesser 0641 +** General Public License version 3 as published by the Free Software 0642 +** Foundation and appearing in the file LICENSE.LGPL3 included in the 0643 +** packaging of this file. Please review the following information to 0644 +** ensure the GNU Lesser General Public License version 3 requirements 0645 +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 0646 +** 0647 +** GNU General Public License Usage 0648 +** Alternatively, this file may be used under the terms of the GNU 0649 +** General Public License version 2.0 or (at your option) the GNU General 0650 +** Public license version 3 or any later version approved by the KDE Free 0651 +** Qt Foundation. The licenses are as published by the Free Software 0652 +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 0653 +** included in the packaging of this file. Please review the following 0654 +** information to ensure the GNU General Public License requirements will 0655 +** be met: https://www.gnu.org/licenses/gpl-2.0.html and 0656 +** https://www.gnu.org/licenses/gpl-3.0.html. 0657 +** 0658 +** $QT_END_LICENSE$ 0659 +** 0660 +****************************************************************************/ 0661 + 0662 +#include "qv4functiontable_p.h" 0663 +#include "qv4function_p.h" 0664 + 0665 +#include <assembler/MacroAssemblerCodeRef.h> 0666 + 0667 +#include <QtCore/qfile.h> 0668 +#include <QtCore/qcoreapplication.h> 0669 + 0670 +QT_BEGIN_NAMESPACE 0671 + 0672 +namespace QV4 { 0673 + 0674 +void generateFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef) 0675 +{ 0676 + // This implements writing of JIT'd addresses so that perf can find the 0677 + // symbol names. 0678 + // 0679 + // Perf expects the mapping to be in a certain place and have certain 0680 + // content, for more information, see: 0681 + // https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt 0682 + static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP"); 0683 + if (Q_UNLIKELY(doProfile)) { 0684 + static QFile perfMapFile(QString::fromLatin1("/tmp/perf-%1.map") 0685 + .arg(QCoreApplication::applicationPid())); 0686 + static const bool isOpen = perfMapFile.open(QIODevice::WriteOnly); 0687 + if (!isOpen) { 0688 + qWarning("QV4::JIT::Assembler: Cannot write perf map file."); 0689 + doProfile = false; 0690 + } else { 0691 + const void *address = codeRef->code().executableAddress(); 0692 + perfMapFile.write(QByteArray::number(reinterpret_cast<quintptr>(address), 16)); 0693 + perfMapFile.putChar(' '); 0694 + perfMapFile.write(QByteArray::number(static_cast<qsizetype>(codeRef->size()), 16)); 0695 + perfMapFile.putChar(' '); 0696 + perfMapFile.write(Function::prettyName(function, address).toUtf8()); 0697 + perfMapFile.putChar('\n'); 0698 + perfMapFile.flush(); 0699 + } 0700 + } 0701 +} 0702 + 0703 +void destroyFunctionTable(Function *function, JSC::MacroAssemblerCodeRef *codeRef) 0704 +{ 0705 + Q_UNUSED(function); 0706 + Q_UNUSED(codeRef); 0707 + 0708 + // It's not advisable to remove things from the perf map file, as it's primarily used to analyze 0709 + // a trace after the application has terminated. We want to know about all functions that were 0710 + // ever jitted then. If the memory ranges overlap, we will have a problem when analyzing the 0711 + // trace. The JIT should try to avoid this. 0712 +} 0713 + 0714 +size_t exceptionHandlerSize() 0715 +{ 0716 + return 0; 0717 +} 0718 + 0719 +} // QV4 0720 + 0721 +QT_END_NAMESPACE 0722 diff --git a/src/qml/jsruntime/qv4functiontable_win64.cpp b/src/qml/jsruntime/qv4functiontable_win64.cpp 0723 new file mode 100644 0724 index 00000000..bc5b24f6 0725 --- /dev/null 0726 +++ b/src/qml/jsruntime/qv4functiontable_win64.cpp 0727 @@ -0,0 +1,153 @@ 0728 +/**************************************************************************** 0729 +** 0730 +** Copyright (C) 2018 The Qt Company Ltd. 0731 +** Contact: https://www.qt.io/licensing/ 0732 +** 0733 +** This file is part of the QtQml module of the Qt Toolkit. 0734 +** 0735 +** $QT_BEGIN_LICENSE:LGPL$ 0736 +** Commercial License Usage 0737 +** Licensees holding valid commercial Qt licenses may use this file in 0738 +** accordance with the commercial license agreement provided with the 0739 +** Software or, alternatively, in accordance with the terms contained in 0740 +** a written agreement between you and The Qt Company. For licensing terms 0741 +** and conditions see https://www.qt.io/terms-conditions. For further 0742 +** information use the contact form at https://www.qt.io/contact-us. 0743 +** 0744 +** GNU Lesser General Public License Usage 0745 +** Alternatively, this file may be used under the terms of the GNU Lesser 0746 +** General Public License version 3 as published by the Free Software 0747 +** Foundation and appearing in the file LICENSE.LGPL3 included in the 0748 +** packaging of this file. Please review the following information to 0749 +** ensure the GNU Lesser General Public License version 3 requirements 0750 +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 0751 +** 0752 +** GNU General Public License Usage 0753 +** Alternatively, this file may be used under the terms of the GNU 0754 +** General Public License version 2.0 or (at your option) the GNU General 0755 +** Public license version 3 or any later version approved by the KDE Free 0756 +** Qt Foundation. The licenses are as published by the Free Software 0757 +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 0758 +** included in the packaging of this file. Please review the following 0759 +** information to ensure the GNU General Public License requirements will 0760 +** be met: https://www.gnu.org/licenses/gpl-2.0.html and 0761 +** https://www.gnu.org/licenses/gpl-3.0.html. 0762 +** 0763 +** $QT_END_LICENSE$ 0764 +** 0765 +****************************************************************************/ 0766 + 0767 +#include "qv4functiontable_p.h" 0768 + 0769 +#include <assembler/MacroAssemblerCodeRef.h> 0770 + 0771 +#include <QtCore/qdebug.h> 0772 + 0773 +#include <Windows.h> 0774 + 0775 +QT_BEGIN_NAMESPACE 0776 + 0777 +namespace QV4 { 0778 + 0779 +enum UnwindOpcode: UINT8 0780 +{ 0781 + UWOP_PUSH_NONVOL = 0, /* info == register number */ 0782 + UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */ 0783 + UWOP_ALLOC_SMALL, /* info == size of allocation / 8 - 1 */ 0784 + UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */ 0785 + UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */ 0786 + UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */ 0787 + UWOP_SAVE_XMM128 = 8, /* info == XMM reg number, offset in next slot */ 0788 + UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */ 0789 + UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */ 0790 +}; 0791 + 0792 +enum Register : UINT8 0793 +{ 0794 + RAX = 0, 0795 + RCX, 0796 + RDX, 0797 + RBX, 0798 + RSP, 0799 + RBP, 0800 + RSI, 0801 + RDI, 0802 + NONE = 15 0803 +}; 0804 + 0805 +struct UnwindCode 0806 +{ 0807 + UnwindCode(UINT8 offset, UnwindOpcode operation, Register info) 0808 + : offset(offset), operation(operation), info(info) 0809 + {} 0810 + 0811 + UINT8 offset; 0812 + UINT8 operation: 4; 0813 + UINT8 info: 4; 0814 +}; 0815 + 0816 +struct UnwindInfo 0817 +{ 0818 + UINT8 Version : 3; 0819 + UINT8 Flags : 5; 0820 + UINT8 SizeOfProlog; 0821 + UINT8 CountOfUnwindCodes; 0822 + UINT8 FrameRegister : 4; 0823 + UINT8 FrameRegisterOffset : 4; 0824 + UnwindCode UnwindCodes[2]; 0825 +}; 0826 + 0827 +struct ExceptionHandlerRecord 0828 +{ 0829 + RUNTIME_FUNCTION handler; 0830 + UnwindInfo info; 0831 +}; 0832 + 0833 +void generateFunctionTable(Function *, JSC::MacroAssemblerCodeRef *codeRef) 0834 +{ 0835 + ExceptionHandlerRecord *record = reinterpret_cast<ExceptionHandlerRecord *>( 0836 + codeRef->executableMemory()->exceptionHandler()); 0837 + 0838 + record->info.Version = 1; 0839 + record->info.Flags = 0; 0840 + record->info.SizeOfProlog = 4; 0841 + record->info.CountOfUnwindCodes = 2; 0842 + record->info.FrameRegister = RBP; 0843 + record->info.FrameRegisterOffset = 0; 0844 + 0845 + // Push frame pointer 0846 + record->info.UnwindCodes[1] = UnwindCode(1, UWOP_PUSH_NONVOL, RBP); 0847 + // Set frame pointer from stack pointer 0848 + record->info.UnwindCodes[0] = UnwindCode(4, UWOP_SET_FPREG, NONE); 0849 + 0850 + const quintptr codeStart = quintptr(codeRef->code().executableAddress()); 0851 + const quintptr codeSize = codeRef->size(); 0852 + 0853 + record->handler.BeginAddress = DWORD(codeStart - quintptr(record)); 0854 + record->handler.EndAddress = DWORD(codeStart + codeSize - quintptr(record)); 0855 + record->handler.UnwindData = offsetof(ExceptionHandlerRecord, info); 0856 + 0857 + if (!RtlAddFunctionTable(&record->handler, 1, DWORD64(record))) { 0858 + const unsigned int errorCode = GetLastError(); 0859 + qWarning() << "Failed to install win64 unwind hook. Error code:" << errorCode; 0860 + } 0861 +} 0862 + 0863 +void destroyFunctionTable(Function *, JSC::MacroAssemblerCodeRef *codeRef) 0864 +{ 0865 + ExceptionHandlerRecord *record = reinterpret_cast<ExceptionHandlerRecord *>( 0866 + codeRef->executableMemory()->exceptionHandler()); 0867 + if (!RtlDeleteFunctionTable(&record->handler)) { 0868 + const unsigned int errorCode = GetLastError(); 0869 + qWarning() << "Failed to remove win64 unwind hook. Error code:" << errorCode; 0870 + } 0871 +} 0872 + 0873 +size_t exceptionHandlerSize() 0874 +{ 0875 + return sizeof(ExceptionHandlerRecord); 0876 +} 0877 + 0878 +} // QV4 0879 + 0880 +QT_END_NAMESPACE 0881 diff --git a/tests/auto/qml/qv4assembler/data/crash.qml b/tests/auto/qml/qv4assembler/data/crash.qml 0882 new file mode 100644 0883 index 00000000..dfdb9ceb 0884 --- /dev/null 0885 +++ b/tests/auto/qml/qv4assembler/data/crash.qml 0886 @@ -0,0 +1,53 @@ 0887 +/**************************************************************************** 0888 +** 0889 +** Copyright (C) 2018 The Qt Company Ltd. 0890 +** Contact: https://www.qt.io/licensing/ 0891 +** 0892 +** This file is part of the test suite of the Qt Toolkit. 0893 +** 0894 +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ 0895 +** Commercial License Usage 0896 +** Licensees holding valid commercial Qt licenses may use this file in 0897 +** accordance with the commercial license agreement provided with the 0898 +** Software or, alternatively, in accordance with the terms contained in 0899 +** a written agreement between you and The Qt Company. For licensing terms 0900 +** and conditions see https://www.qt.io/terms-conditions. For further 0901 +** information use the contact form at https://www.qt.io/contact-us. 0902 +** 0903 +** GNU General Public License Usage 0904 +** Alternatively, this file may be used under the terms of the GNU 0905 +** General Public License version 3 as published by the Free Software 0906 +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT 0907 +** included in the packaging of this file. Please review the following 0908 +** information to ensure the GNU General Public License requirements will 0909 +** be met: https://www.gnu.org/licenses/gpl-3.0.html. 0910 +** 0911 +** $QT_END_LICENSE$ 0912 +** 0913 +****************************************************************************/ 0914 + 0915 +import QtQml 2.2 0916 +import Crash 1.0 0917 + 0918 +QtObject { 0919 + property Crash crash: Crash { 0920 + id: crash 0921 + } 0922 + 0923 + // Recursion makes the crash more reliable 0924 + // With a single frame the unwinder might guess 0925 + // the next frame by chance. 0926 + function recurse(x) { 0927 + if (x > 32) 0928 + crash.crash(); 0929 + else 0930 + recurse(x + 1); 0931 + } 0932 + 0933 + property Timer timer: Timer { 0934 + interval: 10 0935 + running: true 0936 + onTriggered: recurse(0) 0937 + } 0938 +} 0939 + 0940 diff --git a/tests/auto/qml/qv4assembler/qv4assembler.pro b/tests/auto/qml/qv4assembler/qv4assembler.pro 0941 index afd7586a..895e241c 100644 0942 --- a/tests/auto/qml/qv4assembler/qv4assembler.pro 0943 +++ b/tests/auto/qml/qv4assembler/qv4assembler.pro 0944 @@ -1,7 +1,12 @@ 0945 CONFIG += testcase 0946 TARGET = tst_qv4assembler 0947 + 0948 +include (../../shared/util.pri) 0949 + 0950 macos:CONFIG -= app_bundle 0951 0952 +TESTDATA = data/* 0953 + 0954 SOURCES += tst_qv4assembler.cpp 0955 0956 QT += qml-private testlib 0957 diff --git a/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp b/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp 0958 index afc00ec7..61a3e778 100644 0959 --- a/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp 0960 +++ b/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp 0961 @@ -26,20 +26,37 @@ 0962 ** 0963 ****************************************************************************/ 0964 0965 +#include <util.h> 0966 + 0967 #include <QtTest/QtTest> 0968 #include <QtCore/qprocess.h> 0969 #include <QtCore/qtemporaryfile.h> 0970 +#include <QtQml/qqml.h> 0971 +#include <QtQml/qqmlapplicationengine.h> 0972 + 0973 #include <private/qv4global_p.h> 0974 0975 -class tst_QV4Assembler : public QObject 0976 +#ifdef Q_OS_WIN 0977 +#include <Windows.h> 0978 +#endif 0979 + 0980 +class tst_QV4Assembler : public QQmlDataTest 0981 { 0982 Q_OBJECT 0983 0984 private slots: 0985 + void initTestCase() override; 0986 void perfMapFile(); 0987 + void functionTable(); 0988 void jitEnabled(); 0989 }; 0990 0991 +void tst_QV4Assembler::initTestCase() 0992 +{ 0993 + qputenv("QV4_JIT_CALL_THRESHOLD", "0"); 0994 + QQmlDataTest::initTestCase(); 0995 +} 0996 + 0997 void tst_QV4Assembler::perfMapFile() 0998 { 0999 #if !defined(Q_OS_LINUX) 1000 @@ -87,6 +104,42 @@ void tst_QV4Assembler::perfMapFile() 1001 #endif 1002 } 1003 1004 +#ifdef Q_OS_WIN 1005 +class Crash : public QObject 1006 +{ 1007 + Q_OBJECT 1008 +public: 1009 + explicit Crash(QObject *parent = nullptr) : QObject(parent) { } 1010 + Q_INVOKABLE static void crash(); 1011 +}; 1012 + 1013 +static bool crashHandlerHit = false; 1014 + 1015 +static LONG WINAPI crashHandler(EXCEPTION_POINTERS*) 1016 +{ 1017 + crashHandlerHit = true; 1018 + return EXCEPTION_CONTINUE_EXECUTION; 1019 +} 1020 + 1021 +void Crash::crash() 1022 +{ 1023 + SetUnhandledExceptionFilter(crashHandler); 1024 + RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, nullptr); 1025 +} 1026 +#endif 1027 + 1028 +void tst_QV4Assembler::functionTable() 1029 +{ 1030 +#ifndef Q_OS_WIN 1031 + QSKIP("Function tables only exist on windows."); 1032 +#else 1033 + QQmlApplicationEngine engine; 1034 + qmlRegisterType<Crash>("Crash", 1, 0, "Crash"); 1035 + engine.load(testFileUrl("crash.qml")); 1036 + QTRY_VERIFY(crashHandlerHit); 1037 +#endif 1038 +} 1039 + 1040 #ifdef V4_ENABLE_JIT 1041 #define JIT_ENABLED 1 1042 #else 1043 -- 1044 2.37.3 1045