Title: [284224] trunk/Source/_javascript_Core
Revision
284224
Author
[email protected]
Date
2021-10-14 18:49:44 -0700 (Thu, 14 Oct 2021)

Log Message

Make unlinked Baseline JIT scope operations bias the order of checks to the ResolveType that profiling tells us we are likely to be
https://bugs.webkit.org/show_bug.cgi?id=231715

Reviewed by Yusuke Suzuki.

This is a small throughout win in the code generated by unlinked baseline JIT.

* jit/JIT.h:
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_resolve_scope):
(JSC::JIT::generateOpResolveScopeThunk):
(JSC::JIT::emit_op_get_from_scope):
(JSC::JIT::generateOpGetFromScopeThunk):
(JSC::JIT::emit_op_put_to_scope):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (284223 => 284224)


--- trunk/Source/_javascript_Core/ChangeLog	2021-10-15 01:44:56 UTC (rev 284223)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-10-15 01:49:44 UTC (rev 284224)
@@ -1,3 +1,20 @@
+2021-10-14  Saam Barati  <[email protected]>
+
+        Make unlinked Baseline JIT scope operations bias the order of checks to the ResolveType that profiling tells us we are likely to be
+        https://bugs.webkit.org/show_bug.cgi?id=231715
+
+        Reviewed by Yusuke Suzuki.
+
+        This is a small throughout win in the code generated by unlinked baseline JIT.
+
+        * jit/JIT.h:
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_resolve_scope):
+        (JSC::JIT::generateOpResolveScopeThunk):
+        (JSC::JIT::emit_op_get_from_scope):
+        (JSC::JIT::generateOpGetFromScopeThunk):
+        (JSC::JIT::emit_op_put_to_scope):
+
 2021-10-14  Alex Christensen  <[email protected]>
 
         Remove Variant.h

Modified: trunk/Source/_javascript_Core/jit/JIT.h (284223 => 284224)


--- trunk/Source/_javascript_Core/jit/JIT.h	2021-10-15 01:44:56 UTC (rev 284223)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2021-10-15 01:49:44 UTC (rev 284224)
@@ -751,8 +751,10 @@
 
         static MacroAssemblerCodeRef<JITThunkPtrTag> slow_op_get_from_scopeGenerator(VM&);
         static MacroAssemblerCodeRef<JITThunkPtrTag> slow_op_resolve_scopeGenerator(VM&);
-        static MacroAssemblerCodeRef<JITThunkPtrTag> generateOpGetFromScopeThunk(VM&, std::optional<ResolveType>, const char* thunkName);
-        static MacroAssemblerCodeRef<JITThunkPtrTag> generateOpResolveScopeThunk(VM&, std::optional<ResolveType>, const char* thunkName);
+        template <ResolveType>
+        static MacroAssemblerCodeRef<JITThunkPtrTag> generateOpGetFromScopeThunk(VM&);
+        template <ResolveType>
+        static MacroAssemblerCodeRef<JITThunkPtrTag> generateOpResolveScopeThunk(VM&);
 #endif // ENABLE(EXTRA_CTI_THUNKS)
 
         Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter)

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (284223 => 284224)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2021-10-15 01:44:56 UTC (rev 284223)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2021-10-15 01:49:44 UTC (rev 284224)
@@ -1963,18 +1963,6 @@
     else {
         ptrdiff_t metadataOffset = m_unlinkedCodeBlock->metadata().offsetInMetadataTable(bytecode);
 
-        auto closureVarGenerator = [] (VM& vm) {
-            return JIT::generateOpResolveScopeThunk(vm, ClosureVar, "Baseline: op_resolve_scope ClosureVar");
-        };
-
-        auto closureVarWithVarInjectionChecksGenerator = [] (VM& vm) {
-            return JIT::generateOpResolveScopeThunk(vm, ClosureVarWithVarInjectionChecks, "Baseline: op_resolve_scope ClosureVarWithVarInjectionChecks");
-        };
-
-        auto genericResolveScopeGenerator = [] (VM& vm) {
-            return JIT::generateOpResolveScopeThunk(vm, std::nullopt, "Baseline: op_resolve_scope generic");
-        };
-
         constexpr GPRReg metadataGPR = regT2;
         constexpr GPRReg scopeGPR = regT0;
         constexpr GPRReg bytecodeOffsetGPR = regT5;
@@ -1985,11 +1973,24 @@
 
         MacroAssemblerCodeRef<JITThunkPtrTag> code;
         if (profiledResolveType == ClosureVar)
-            code = vm.getCTIStub(closureVarGenerator);
+            code = vm.getCTIStub(generateOpResolveScopeThunk<ClosureVar>);
         else if (profiledResolveType == ClosureVarWithVarInjectionChecks)
-            code = vm.getCTIStub(closureVarWithVarInjectionChecksGenerator);
+            code = vm.getCTIStub(generateOpResolveScopeThunk<ClosureVarWithVarInjectionChecks>);
+        else if (profiledResolveType == GlobalVar)
+            code = vm.getCTIStub(generateOpResolveScopeThunk<GlobalVar>);
+        else if (profiledResolveType == GlobalProperty)
+            code = vm.getCTIStub(generateOpResolveScopeThunk<GlobalProperty>);
+        else if (profiledResolveType == GlobalLexicalVar)
+            code = vm.getCTIStub(generateOpResolveScopeThunk<GlobalLexicalVar>);
+        else if (profiledResolveType == GlobalVarWithVarInjectionChecks)
+            code = vm.getCTIStub(generateOpResolveScopeThunk<GlobalVarWithVarInjectionChecks>);
+        else if (profiledResolveType == GlobalPropertyWithVarInjectionChecks)
+            code = vm.getCTIStub(generateOpResolveScopeThunk<GlobalPropertyWithVarInjectionChecks>);
+        else if (profiledResolveType == GlobalLexicalVarWithVarInjectionChecks)
+            code = vm.getCTIStub(generateOpResolveScopeThunk<GlobalLexicalVarWithVarInjectionChecks>);
         else
-            code = vm.getCTIStub(genericResolveScopeGenerator);
+            code = vm.getCTIStub(generateOpResolveScopeThunk<GlobalVar>);
+
         emitNakedNearCall(code.retaggedCode<NoPtrTag>());
     }
 
@@ -1996,7 +1997,8 @@
     emitPutVirtualRegister(dst);
 }
 
-MacroAssemblerCodeRef<JITThunkPtrTag> JIT::generateOpResolveScopeThunk(VM& vm, std::optional<ResolveType> resolveType, const char* thunkName)
+template <ResolveType profiledResolveType>
+MacroAssemblerCodeRef<JITThunkPtrTag> JIT::generateOpResolveScopeThunk(VM& vm)
 {
     // The thunk generated by this function can only work with the LLInt / Baseline JIT because
     // it makes assumptions about the right globalObject being available from CallFrame::codeBlock().
@@ -2033,8 +2035,8 @@
 
     auto emitResolveClosure = [&] (bool needsVarInjectionChecks) {
         doVarInjectionCheck(needsVarInjectionChecks);
-        static_assert(scopeGPR == regT0);
         jit.load32(Address(metadataGPR, Metadata::offsetOfLocalScopeDepth()), regT1);
+        RELEASE_ASSERT(scopeGPR == regT0);
 
         Label loop = jit.label();
         Jump done = jit.branchTest32(Zero, regT1);
@@ -2085,14 +2087,15 @@
         }
     };
 
-    if (resolveType) {
-        RELEASE_ASSERT(*resolveType == ClosureVar || *resolveType == ClosureVarWithVarInjectionChecks);
-        emitCode(*resolveType);
-    } else {
+    if (profiledResolveType == ClosureVar)
+        emitCode(ClosureVar);
+    else if (profiledResolveType == ClosureVarWithVarInjectionChecks)
+        emitCode(ClosureVarWithVarInjectionChecks);
+    else {
         JumpList skipToEnd;
         jit.load32(Address(metadataGPR, Metadata::offsetOfResolveType()), regT1);
 
-        auto emitCase = [&] (ResolveType resolveType) {
+        auto emitCaseWithoutCheck = [&] (ResolveType resolveType) {
             Jump notCase = jit.branch32(NotEqual, regT1, TrustedImm32(resolveType));
             emitCode(resolveType);
             skipToEnd.append(jit.jump());
@@ -2099,6 +2102,23 @@
             notCase.link(&jit);
         };
 
+        auto emitCase = [&] (ResolveType resolveType) {
+            if (resolveType != profiledResolveType)
+                emitCaseWithoutCheck(resolveType);
+        };
+
+        // Check that we're the profiled resolve type first.
+        switch (profiledResolveType) {
+        case ResolvedClosureVar:
+        case ModuleVar:
+        case UnresolvedProperty:
+        case UnresolvedPropertyWithVarInjectionChecks:
+            break;
+        default:
+            emitCaseWithoutCheck(profiledResolveType);
+            break;
+        }
+
         emitCase(GlobalVar);
         emitCase(GlobalProperty);
         emitCase(GlobalLexicalVar);
@@ -2114,7 +2134,7 @@
 
     LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID, LinkBuffer::Profile::Thunk);
     patchBuffer.link(slowCase, CodeLocationLabel(vm.getCTIStub(slow_op_resolve_scopeGenerator).retaggedCode<NoPtrTag>()));
-    return FINALIZE_CODE(patchBuffer, JITThunkPtrTag, thunkName);
+    return FINALIZE_CODE(patchBuffer, JITThunkPtrTag, "resolve_scope thunk");
 }
 
 MacroAssemblerCodeRef<JITThunkPtrTag> JIT::slow_op_resolve_scopeGenerator(VM& vm)
@@ -2344,18 +2364,6 @@
     ASSERT(BytecodeIndex(bytecodeOffset) == m_bytecodeIndex);
     ASSERT(m_unlinkedCodeBlock->instructionAt(m_bytecodeIndex) == currentInstruction);
 
-    auto closureVarGenerator = [] (VM& vm) {
-        return JIT::generateOpGetFromScopeThunk(vm, ClosureVar, "Baseline: op_get_from_scope ClosureVar");
-    };
-
-    auto closureVarWithVarInjectionChecksGenerator = [] (VM& vm) {
-        return JIT::generateOpGetFromScopeThunk(vm, ClosureVarWithVarInjectionChecks, "Baseline: op_get_from_scope ClosureVar");
-    };
-
-    auto genericGetFromScopeGenerator = [] (VM& vm) {
-        return JIT::generateOpGetFromScopeThunk(vm, std::nullopt, "Baseline: op_get_from_scope generic");
-    };
-
     constexpr GPRReg metadataGPR = regT4;
     constexpr GPRReg scopeGPR = regT2;
     constexpr GPRReg bytecodeOffsetGPR = regT5;
@@ -2368,17 +2376,28 @@
 
     MacroAssemblerCodeRef<JITThunkPtrTag> code;
     if (profiledResolveType == ClosureVar)
-        code = vm.getCTIStub(closureVarGenerator);
+        code = vm.getCTIStub(generateOpGetFromScopeThunk<ClosureVar>);
     else if (profiledResolveType == ClosureVarWithVarInjectionChecks)
-        code = vm.getCTIStub(closureVarWithVarInjectionChecksGenerator);
+        code = vm.getCTIStub(generateOpGetFromScopeThunk<ClosureVarWithVarInjectionChecks>);
+    else if (profiledResolveType == GlobalVar)
+        code = vm.getCTIStub(generateOpGetFromScopeThunk<GlobalVar>);
+    else if (profiledResolveType == GlobalVarWithVarInjectionChecks)
+        code = vm.getCTIStub(generateOpGetFromScopeThunk<GlobalVarWithVarInjectionChecks>);
+    else if (profiledResolveType == GlobalProperty)
+        code = vm.getCTIStub(generateOpGetFromScopeThunk<GlobalProperty>);
+    else if (profiledResolveType == GlobalLexicalVar)
+        code = vm.getCTIStub(generateOpGetFromScopeThunk<GlobalLexicalVar>);
+    else if (profiledResolveType == GlobalLexicalVarWithVarInjectionChecks)
+        code = vm.getCTIStub(generateOpGetFromScopeThunk<GlobalLexicalVarWithVarInjectionChecks>);
     else
-        code = vm.getCTIStub(genericGetFromScopeGenerator);
+        code = vm.getCTIStub(generateOpGetFromScopeThunk<GlobalVar>);
 
     emitNakedNearCall(code.retaggedCode<NoPtrTag>());
     emitPutVirtualRegister(dst);
 }
 
-MacroAssemblerCodeRef<JITThunkPtrTag> JIT::generateOpGetFromScopeThunk(VM& vm, std::optional<ResolveType> resolveType, const char* thunkName)
+template <ResolveType profiledResolveType>
+MacroAssemblerCodeRef<JITThunkPtrTag> JIT::generateOpGetFromScopeThunk(VM& vm)
 {
     // The thunk generated by this function can only work with the LLInt / Baseline JIT because
     // it makes assumptions about the right globalObject being available from CallFrame::codeBlock().
@@ -2468,43 +2487,44 @@
         }
     };
 
-    if (resolveType) {
-        RELEASE_ASSERT(*resolveType == ClosureVar || *resolveType == ClosureVarWithVarInjectionChecks);
-        emitCode(*resolveType);
-    } else {
+    if (profiledResolveType == ClosureVar || profiledResolveType == ClosureVarWithVarInjectionChecks)
+        emitCode(profiledResolveType);
+    else {
         JumpList skipToEnd;
         jit.load32(Address(metadataGPR, Metadata::offsetOfGetPutInfo()), regT0);
         jit.and32(TrustedImm32(GetPutInfo::typeBits), regT0); // Load ResolveType into T0
 
-        Jump notGlobalVar = jit.branch32(NotEqual, regT0, TrustedImm32(GlobalVar));
-        emitCode(GlobalVar);
-        skipToEnd.append(jit.jump());
-        notGlobalVar.link(&jit);
+        auto emitCaseWithoutCheck = [&] (ResolveType resolveType) {
+            Jump notCase = jit.branch32(NotEqual, regT0, TrustedImm32(resolveType));
+            emitCode(resolveType);
+            skipToEnd.append(jit.jump());
+            notCase.link(&jit);
+        };
 
-        Jump notGlobalVarWithVarInjection = jit.branch32(NotEqual, regT0, TrustedImm32(GlobalVarWithVarInjectionChecks));
-        emitCode(GlobalVarWithVarInjectionChecks);
-        skipToEnd.append(jit.jump());
-        notGlobalVarWithVarInjection.link(&jit);
+        auto emitCase = [&] (ResolveType resolveType) {
+            if (profiledResolveType != resolveType)
+                emitCaseWithoutCheck(resolveType);
+        };
 
-        Jump isGlobalProperty = jit.branch32(Equal, regT0, TrustedImm32(GlobalProperty));
-        Jump notGlobalPropertyWithVarInjections = jit.branch32(NotEqual, regT0, TrustedImm32(GlobalPropertyWithVarInjectionChecks));
-        isGlobalProperty.link(&jit);
-        emitCode(GlobalProperty);
-        skipToEnd.append(jit.jump());
-        notGlobalPropertyWithVarInjections.link(&jit);
+        switch (profiledResolveType) {
+        case ResolvedClosureVar:
+        case ModuleVar:
+        case UnresolvedProperty:
+        case UnresolvedPropertyWithVarInjectionChecks:
+            break;
+        default:
+            emitCaseWithoutCheck(profiledResolveType);
+            break;
+        }
 
-        Jump notGlobalLexicalVar = jit.branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVar));
-        emitCode(GlobalLexicalVar);
-        skipToEnd.append(jit.jump());
-        notGlobalLexicalVar.link(&jit);
+        emitCase(GlobalVar);
+        emitCase(GlobalProperty);
+        emitCase(GlobalLexicalVar);
+        emitCase(GlobalVarWithVarInjectionChecks);
+        emitCase(GlobalPropertyWithVarInjectionChecks);
+        emitCase(GlobalLexicalVarWithVarInjectionChecks);
 
-        Jump notGlobalLexicalVarWithVarInjections = jit.branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVarWithVarInjectionChecks));
-        emitCode(GlobalLexicalVarWithVarInjectionChecks);
-        skipToEnd.append(jit.jump());
-        notGlobalLexicalVarWithVarInjections.link(&jit);
-
         slowCase.append(jit.jump());
-
         skipToEnd.link(&jit);
     }
 
@@ -2515,7 +2535,7 @@
 
     LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID, LinkBuffer::Profile::Thunk);
     patchBuffer.link(slowCase, CodeLocationLabel(vm.getCTIStub(slow_op_get_from_scopeGenerator).retaggedCode<NoPtrTag>()));
-    return FINALIZE_CODE(patchBuffer, JITThunkPtrTag, thunkName);
+    return FINALIZE_CODE(patchBuffer, JITThunkPtrTag, "get_from_scope thunk");
 }
 
 MacroAssemblerCodeRef<JITThunkPtrTag> JIT::slow_op_get_from_scopeGenerator(VM& vm)
@@ -2680,35 +2700,35 @@
         load32FromMetadata(bytecode, OpPutToScope::Metadata::offsetOfGetPutInfo(), regT0);
         and32(TrustedImm32(GetPutInfo::typeBits), regT0); // Load ResolveType into T0
 
-        Jump isGlobalProperty = branch32(Equal, regT0, TrustedImm32(GlobalProperty));
-        Jump notGlobalPropertyWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalPropertyWithVarInjectionChecks));
-        isGlobalProperty.link(this);
-        emitCode(GlobalProperty);
-        skipToEnd.append(jump());
-        notGlobalPropertyWithVarInjections.link(this);
+        auto emitCaseWithoutCheck = [&] (ResolveType resolveType) {
+            Jump notCase = branch32(NotEqual, regT0, TrustedImm32(resolveType));
+            emitCode(resolveType);
+            skipToEnd.append(jump());
+            notCase.link(this);
+        };
 
-        Jump notGlobalVar = branch32(NotEqual, regT0, TrustedImm32(GlobalVar));
-        emitCode(GlobalVar);
-        skipToEnd.append(jump());
-        notGlobalVar.link(this);
+        auto emitCase = [&] (ResolveType resolveType) {
+            if (profiledResolveType != resolveType)
+                emitCaseWithoutCheck(resolveType);
+        };
 
-        Jump notGlobalVarWithVarInjection = branch32(NotEqual, regT0, TrustedImm32(GlobalVarWithVarInjectionChecks));
-        emitCode(GlobalVarWithVarInjectionChecks);
-        skipToEnd.append(jump());
-        notGlobalVarWithVarInjection.link(this);
+        switch (profiledResolveType) {
+        case UnresolvedProperty:
+        case UnresolvedPropertyWithVarInjectionChecks:
+            break;
+        default:
+            emitCaseWithoutCheck(profiledResolveType);
+            break;
+        }
 
-        Jump notGlobalLexicalVar = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVar));
-        emitCode(GlobalLexicalVar);
-        skipToEnd.append(jump());
-        notGlobalLexicalVar.link(this);
+        emitCase(GlobalVar);
+        emitCase(GlobalProperty);
+        emitCase(GlobalLexicalVar);
+        emitCase(GlobalVarWithVarInjectionChecks);
+        emitCase(GlobalPropertyWithVarInjectionChecks);
+        emitCase(GlobalLexicalVarWithVarInjectionChecks);
 
-        Jump notGlobalLexicalVarWithVarInjections = branch32(NotEqual, regT0, TrustedImm32(GlobalLexicalVarWithVarInjectionChecks));
-        emitCode(GlobalLexicalVarWithVarInjectionChecks);
-        skipToEnd.append(jump());
-        notGlobalLexicalVarWithVarInjections.link(this);
-
         addSlowCase(jump());
-
         skipToEnd.link(this);
     }
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to