From 0dd884aca1fffcd94fbe55006c94363415aa0965 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 14 Mar 2019 10:42:19 +0100 Subject: Baseline JIT: Save accumulator in toInt32LhsAcc() toInt32LhsAcc convertes both the lhs and the accumulator to int32. If the accumulator is not saved, a GC run during the conversion of the lhs might trash its value. Fixes: QTBUG-74058 Change-Id: Ic42693061c7d483bb430d77bcc095de6ff9a6843 Reviewed-by: Simon Hausmann --- src/qml/jit/qv4baselineassembler.cpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'src/qml/jit') diff --git a/src/qml/jit/qv4baselineassembler.cpp b/src/qml/jit/qv4baselineassembler.cpp index 5c08c42977..b13f646360 100644 --- a/src/qml/jit/qv4baselineassembler.cpp +++ b/src/qml/jit/qv4baselineassembler.cpp @@ -208,17 +208,20 @@ public: isNumber.link(this); } + // this converts both the lhs and the accumulator to int32 void toInt32LhsAcc(Address lhs, RegisterID lhsTarget) { load64(lhs, lhsTarget); urshift64(lhsTarget, TrustedImm32(Value::QuickType_Shift), ScratchRegister2); auto lhsIsInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2); - pushAligned(AccumulatorRegister); + const Address accumulatorStackAddress(JSStackFrameRegister, + offsetof(CallData, accumulator)); + storeAccumulator(accumulatorStackAddress); move(lhsTarget, registerForArg(0)); callHelper(toInt32Helper); move(ReturnValueRegister, lhsTarget); - popAligned(AccumulatorRegister); + loadAccumulator(accumulatorStackAddress); lhsIsInt.link(this); urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister2); @@ -498,6 +501,7 @@ public: isNumber.link(this); } + // this converts both the lhs and the accumulator to int32 void toInt32LhsAcc(Address lhs, RegisterID lhsTarget) { bool accumulatorNeedsSaving = AccumulatorRegisterValue == ReturnValueRegisterValue @@ -510,32 +514,28 @@ public: auto lhsIsInt = jump(); lhsIsNotInt.link(this); - if (accumulatorNeedsSaving) { - push(AccumulatorRegisterTag); - push(AccumulatorRegisterValue); - } + + // Save accumulator from being garbage collected, no matter if we will reuse the register. + const Address accumulatorStackAddress(JSStackFrameRegister, + offsetof(CallData, accumulator)); + storeAccumulator(accumulatorStackAddress); if (ArgInRegCount < 2) { - if (!accumulatorNeedsSaving) - subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); + subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); push(lhsTarget); load32(lhs, lhsTarget); push(lhsTarget); } else { - if (accumulatorNeedsSaving) - subPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); move(lhsTarget, registerForArg(1)); load32(lhs, registerForArg(0)); } callHelper(toInt32Helper); move(ReturnValueRegisterValue, lhsTarget); - if (accumulatorNeedsSaving) { - addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); - pop(AccumulatorRegisterValue); - pop(AccumulatorRegisterTag); - } else if (ArgInRegCount < 2) { + if (ArgInRegCount < 2) addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister); - } + + if (accumulatorNeedsSaving) // otherwise it's still the same + loadAccumulator(accumulatorStackAddress); lhsIsInt.link(this); -- cgit v1.2.3 From c9e6251cc8dfcf002f64b07e48dd68b7edd3f630 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 2 Jan 2019 16:09:56 +0100 Subject: Implement dummy QML lookups for "global" variables When resolving names in the context of QML bindings, we now direct runtime access to QQmlContextWrapper::resolveQmlPropertyLookupGetter. At the moment this does basically the same as Runtime::method_loadName, which we called earlier. However this now provides the opportunity to optimize lookups in the QML context in a central place. When performing a call on a scope or context object property, we also did not use a CallName() instruction - which would have gotten the thisObject wrong - but instead we use a dedicated CallScopeObjectProperty and CallContextObjectProperty instruction. These rely on identifying these properties at compile time, which goes away with lookups (and also doesn't work when using ahead-of-time compilation). Therefore the qml context property lookup is using a getPropertyAndBase style signature and Runtime::method_callQmlContextPropertyLookup uses that. For the tests to pass, some error expectations need adjusting. In particular the compile-time detection of write attempts to id objects is now delayed to the run-time. The old code path is still there and will be removed separately in the next commit (as it is massive). Task-number: QTBUG-69898 Change-Id: Iad1ff93d3758c4db984a7c2d003beee21ed2275c Reviewed-by: Ulf Hermann --- src/qml/jit/qv4baselinejit.cpp | 22 ++++++++++++++++++++++ src/qml/jit/qv4baselinejit_p.h | 2 ++ src/qml/jit/qv4jithelpers.cpp | 6 ++++++ src/qml/jit/qv4jithelpers_p.h | 1 + 4 files changed, 31 insertions(+) (limited to 'src/qml/jit') diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp index 098bbfc6c6..47cef3b3bd 100644 --- a/src/qml/jit/qv4baselinejit.cpp +++ b/src/qml/jit/qv4baselinejit.cpp @@ -213,6 +213,16 @@ void BaselineJIT::generate_LoadGlobalLookup(int index) as->checkException(); } +void BaselineJIT::generate_LoadQmlContextPropertyLookup(int index) +{ + as->prepareCallWithArgCount(3); + as->passInt32AsArg(index, 2); + as->passEngineAsArg(1); + as->passFunctionAsArg(0); + BASELINEJIT_GENERATE_RUNTIME_CALL(Helpers::loadQmlContextPropertyLookup, CallResultDestination::InAccumulator); + as->checkException(); +} + void BaselineJIT::generate_StoreNameSloppy(int name) { STORE_IP(); @@ -514,6 +524,18 @@ void BaselineJIT::generate_CallGlobalLookup(int index, int argc, int argv) as->checkException(); } +void BaselineJIT::generate_CallQmlContextPropertyLookup(int index, int argc, int argv) +{ + STORE_IP(); + as->prepareCallWithArgCount(4); + as->passInt32AsArg(argc, 3); + as->passJSSlotAsArg(argv, 2); + as->passInt32AsArg(index, 1); + as->passEngineAsArg(0); + BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlContextPropertyLookup, CallResultDestination::InAccumulator); + as->checkException(); +} + void BaselineJIT::generate_CallScopeObjectProperty(int propIdx, int base, int argc, int argv) { STORE_IP(); diff --git a/src/qml/jit/qv4baselinejit_p.h b/src/qml/jit/qv4baselinejit_p.h index 98d23f4517..4db1eb1806 100644 --- a/src/qml/jit/qv4baselinejit_p.h +++ b/src/qml/jit/qv4baselinejit_p.h @@ -97,6 +97,7 @@ public: void generate_LoadClosure(int value) override; void generate_LoadName(int name) override; void generate_LoadGlobalLookup(int index) override; + void generate_LoadQmlContextPropertyLookup(int index) override; void generate_StoreNameSloppy(int name) override; void generate_StoreNameStrict(int name) override; void generate_LoadElement(int base) override; @@ -128,6 +129,7 @@ public: void generate_CallName(int name, int argc, int argv) override; void generate_CallPossiblyDirectEval(int argc, int argv) override; void generate_CallGlobalLookup(int index, int argc, int argv) override; + void generate_CallQmlContextPropertyLookup(int index, int argc, int argv) override; void generate_CallScopeObjectProperty(int propIdx, int base, int argc, int argv) override; void generate_CallContextObjectProperty(int propIdx, int base, int argc, int argv) override; void generate_CallWithSpread(int func, int thisObject, int argc, int argv) override; diff --git a/src/qml/jit/qv4jithelpers.cpp b/src/qml/jit/qv4jithelpers.cpp index f43f37ad70..674fd8c8c8 100644 --- a/src/qml/jit/qv4jithelpers.cpp +++ b/src/qml/jit/qv4jithelpers.cpp @@ -70,6 +70,12 @@ ReturnedValue loadGlobalLookup(Function *f, ExecutionEngine *engine, int index) return l->globalGetter(l, engine); } +ReturnedValue loadQmlContextPropertyLookup(Function *f, ExecutionEngine *engine, int index) +{ + Lookup *l = f->compilationUnit->runtimeLookups + index; + return l->qmlContextPropertyGetter(l, engine, nullptr); +} + ReturnedValue toObject(ExecutionEngine *engine, const Value &obj) { if (obj.isObject()) diff --git a/src/qml/jit/qv4jithelpers_p.h b/src/qml/jit/qv4jithelpers_p.h index bd5f65034d..d9abfc071e 100644 --- a/src/qml/jit/qv4jithelpers_p.h +++ b/src/qml/jit/qv4jithelpers_p.h @@ -66,6 +66,7 @@ namespace Helpers { void convertThisToObject(ExecutionEngine *engine, Value *t); ReturnedValue loadGlobalLookup(Function *f, ExecutionEngine *engine, int index); +ReturnedValue loadQmlContextPropertyLookup(Function *f, ExecutionEngine *engine, int index); ReturnedValue toObject(ExecutionEngine *engine, const Value &obj); ReturnedValue exp(const Value &base, const Value &exp); ReturnedValue getLookup(Function *f, ExecutionEngine *engine, const Value &base, int index); -- cgit v1.2.3 From 5cfccf30898aed5ca96c0f8779b0f8a1117118b7 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 3 Jan 2019 15:44:34 +0100 Subject: Remove dead compile time QML context/scope property and id object code After enabling lookups in QML files, we can remove all the code that tries to deal with (type) compile time detection of access to id objects and properties of the scope/context object. This also allows removing quite a bit of run-time code paths and even byte code instructions. Task-number: QTBUG-69898 Change-Id: I7b26d7983393594a3ef56466d3e633f1822b76f4 Reviewed-by: Ulf Hermann --- src/qml/jit/qv4baselinejit.cpp | 103 ----------------------------------------- src/qml/jit/qv4baselinejit_p.h | 13 ------ 2 files changed, 116 deletions(-) (limited to 'src/qml/jit') diff --git a/src/qml/jit/qv4baselinejit.cpp b/src/qml/jit/qv4baselinejit.cpp index 47cef3b3bd..1e4288e3c9 100644 --- a/src/qml/jit/qv4baselinejit.cpp +++ b/src/qml/jit/qv4baselinejit.cpp @@ -347,66 +347,6 @@ void BaselineJIT::generate_StoreSuperProperty(int property) as->checkException(); } - -void BaselineJIT::generate_StoreScopeObjectProperty(int base, int propertyIndex) -{ - STORE_ACC(); - as->prepareCallWithArgCount(4); - as->passAccumulatorAsArg(3); - as->passInt32AsArg(propertyIndex, 2); - as->passJSSlotAsArg(base, 1); - as->passEngineAsArg(0); - BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeQmlScopeObjectProperty, CallResultDestination::Ignore); - as->checkException(); -} - -void BaselineJIT::generate_StoreContextObjectProperty(int base, int propertyIndex) -{ - STORE_ACC(); - as->prepareCallWithArgCount(4); - as->passAccumulatorAsArg(3); - as->passInt32AsArg(propertyIndex, 2); - as->passJSSlotAsArg(base, 1); - as->passEngineAsArg(0); - BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_storeQmlContextObjectProperty, CallResultDestination::Ignore); - as->checkException(); -} - -void BaselineJIT::generate_LoadScopeObjectProperty(int propertyIndex, int base, int captureRequired) -{ - STORE_IP(); - as->prepareCallWithArgCount(4); - as->passInt32AsArg(captureRequired, 3); - as->passInt32AsArg(propertyIndex, 2); - as->passJSSlotAsArg(base, 1); - as->passEngineAsArg(0); - BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlScopeObjectProperty, CallResultDestination::InAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_LoadContextObjectProperty(int propertyIndex, int base, int captureRequired) -{ - STORE_IP(); - as->prepareCallWithArgCount(4); - as->passInt32AsArg(captureRequired, 3); - as->passInt32AsArg(propertyIndex, 2); - as->passJSSlotAsArg(base, 1); - as->passEngineAsArg(0); - BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlContextObjectProperty, CallResultDestination::InAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_LoadIdObject(int index, int base) -{ - STORE_IP(); - as->prepareCallWithArgCount(3); - as->passInt32AsArg(index, 2); - as->passJSSlotAsArg(base, 1); - as->passEngineAsArg(0); - BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlIdObject, CallResultDestination::InAccumulator); - as->checkException(); -} - void BaselineJIT::generate_Yield() { // ##### @@ -536,33 +476,6 @@ void BaselineJIT::generate_CallQmlContextPropertyLookup(int index, int argc, int as->checkException(); } -void BaselineJIT::generate_CallScopeObjectProperty(int propIdx, int base, int argc, int argv) -{ - STORE_IP(); - as->prepareCallWithArgCount(5); - as->passInt32AsArg(argc, 4); - as->passJSSlotAsArg(argv, 3); - as->passInt32AsArg(propIdx, 2); - as->passJSSlotAsArg(base, 1); - as->passEngineAsArg(0); - BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlScopeObjectProperty, CallResultDestination::InAccumulator); - as->checkException(); -} - -void BaselineJIT::generate_CallContextObjectProperty(int propIdx, int base, int argc, int argv) -{ - STORE_IP(); - as->prepareCallWithArgCount(5); - as->passInt32AsArg(argc, 4); - as->passJSSlotAsArg(argv, 3); - as->passInt32AsArg(propIdx, 2); - as->passJSSlotAsArg(base, 1); - as->passEngineAsArg(0); - BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_callQmlContextObjectProperty, CallResultDestination::InAccumulator); - as->checkException(); -} - - void BaselineJIT::generate_CallWithSpread(int func, int thisObject, int argc, int argv) { STORE_IP(); @@ -981,22 +894,6 @@ void BaselineJIT::generate_Sub(int lhs) { as->sub(lhs); } // as->checkException(); //} -void BaselineJIT::generate_LoadQmlContext(int result) -{ - as->prepareCallWithArgCount(1); - as->passEngineAsArg(0); - BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlContext, CallResultDestination::InAccumulator); - as->storeReg(result); -} - -void BaselineJIT::generate_LoadQmlImportedScripts(int result) -{ - as->prepareCallWithArgCount(1); - as->passEngineAsArg(0); - BASELINEJIT_GENERATE_RUNTIME_CALL(Runtime::method_loadQmlImportedScripts, CallResultDestination::InAccumulator); - as->storeReg(result); -} - void BaselineJIT::generate_InitializeBlockDeadTemporalZone(int firstReg, int count) { as->loadValue(Value::emptyValue().rawValue()); diff --git a/src/qml/jit/qv4baselinejit_p.h b/src/qml/jit/qv4baselinejit_p.h index 4db1eb1806..6646eb713e 100644 --- a/src/qml/jit/qv4baselinejit_p.h +++ b/src/qml/jit/qv4baselinejit_p.h @@ -108,15 +108,6 @@ public: void generate_SetLookup(int index, int base) override; void generate_LoadSuperProperty(int property) override; void generate_StoreSuperProperty(int property) override; - void generate_StoreScopeObjectProperty(int base, - int propertyIndex) override; - void generate_StoreContextObjectProperty(int base, - int propertyIndex) override; - void generate_LoadScopeObjectProperty(int propertyIndex, int base, - int captureRequired) override; - void generate_LoadContextObjectProperty(int propertyIndex, int base, - int captureRequired) override; - void generate_LoadIdObject(int index, int base) override; void generate_Yield() override; void generate_YieldStar() override; void generate_Resume(int) override; @@ -130,8 +121,6 @@ public: void generate_CallPossiblyDirectEval(int argc, int argv) override; void generate_CallGlobalLookup(int index, int argc, int argv) override; void generate_CallQmlContextPropertyLookup(int index, int argc, int argv) override; - void generate_CallScopeObjectProperty(int propIdx, int base, int argc, int argv) override; - void generate_CallContextObjectProperty(int propIdx, int base, int argc, int argv) override; void generate_CallWithSpread(int func, int thisObject, int argc, int argv) override; void generate_TailCall(int func, int thisObject, int argc, int argv) override; void generate_Construct(int func, int argc, int argv) override; @@ -213,8 +202,6 @@ public: void generate_Div(int lhs) override; void generate_Mod(int lhs) override; void generate_Sub(int lhs) override; - void generate_LoadQmlContext(int result) override; - void generate_LoadQmlImportedScripts(int result) override; void generate_InitializeBlockDeadTemporalZone(int firstReg, int count) override; void generate_ThrowOnNullOrUndefined() override; void generate_GetTemplateObject(int index) override; -- cgit v1.2.3