Title: [292767] trunk/Source/_javascript_Core
Revision
292767
Author
[email protected]
Date
2022-04-12 00:51:30 -0700 (Tue, 12 Apr 2022)

Log Message

[JSC] Reduce Baseline JIT code size in debug builds
https://bugs.webkit.org/show_bug.cgi?id=238928

Patch by Geza Lore <[email protected]> on 2022-04-12
Reviewed by Saam Barati.

The Baseline JIT used to emit a substantial but identical sequence to
check pinned registers and the SP at the beginning of every bytecode.
This caused large code bloat and made it somewhat difficult to use
debug builds on resource constrained platforms. Trying to alleviate
this by emitting a small dispatcher after the slow path section (but
before the stack overflow check), which then tail-calls a shared
thunk. The opcodes then call this very small dispatcher. The source op
of a faulting bytecode is easily visible in the link register (or on
the stack on x86).

This saves 34% Baseline JIT code size (and 14% overall) on a debug
build with JetStream2. Also fixes all code-size related test failures
on the ARMv7 debug build.

* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::emitConsistencyCheck):
(JSC::JIT::compileAndLinkWithoutFinalizing):
(JSC::JIT::link):
* jit/JIT.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (292766 => 292767)


--- trunk/Source/_javascript_Core/ChangeLog	2022-04-12 06:49:21 UTC (rev 292766)
+++ trunk/Source/_javascript_Core/ChangeLog	2022-04-12 07:51:30 UTC (rev 292767)
@@ -1,3 +1,31 @@
+2022-04-12  Geza Lore  <[email protected]>
+
+        [JSC] Reduce Baseline JIT code size in debug builds
+        https://bugs.webkit.org/show_bug.cgi?id=238928
+
+        Reviewed by Saam Barati.
+
+        The Baseline JIT used to emit a substantial but identical sequence to
+        check pinned registers and the SP at the beginning of every bytecode.
+        This caused large code bloat and made it somewhat difficult to use
+        debug builds on resource constrained platforms. Trying to alleviate
+        this by emitting a small dispatcher after the slow path section (but
+        before the stack overflow check), which then tail-calls a shared
+        thunk. The opcodes then call this very small dispatcher. The source op
+        of a faulting bytecode is easily visible in the link register (or on
+        the stack on x86).
+
+        This saves 34% Baseline JIT code size (and 14% overall) on a debug
+        build with JetStream2. Also fixes all code-size related test failures
+        on the ARMv7 debug build.
+
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::emitConsistencyCheck):
+        (JSC::JIT::compileAndLinkWithoutFinalizing):
+        (JSC::JIT::link):
+        * jit/JIT.h:
+
 2022-04-11  Yusuke Suzuki  <[email protected]>
 
         [JSC] Reduce use of unnecessary cryptographicallyRandom numbers

Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (292766 => 292767)


--- trunk/Source/_javascript_Core/jit/JIT.cpp	2022-04-12 06:49:21 UTC (rev 292766)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp	2022-04-12 07:51:30 UTC (rev 292767)
@@ -143,17 +143,6 @@
     }
 }
 
-void JIT::assertStackPointerOffset()
-{
-    if (!ASSERT_ENABLED)
-        return;
-    
-    addPtr(TrustedImm32(stackPointerOffsetFor(m_unlinkedCodeBlock) * sizeof(Register)), callFrameRegister, regT0);
-    Jump ok = branchPtr(Equal, regT0, stackPointerRegister);
-    breakpoint();
-    ok.link(this);
-}
-
 void JIT::resetSP()
 {
     addPtr(TrustedImm32(stackPointerOffsetFor(m_unlinkedCodeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
@@ -248,19 +237,8 @@
         }
 
 #if ASSERT_ENABLED
-        if (opcodeID != op_catch) {
-            loadPtr(addressFor(CallFrameSlot::codeBlock), regT0);
-            loadPtr(Address(regT0, CodeBlock::offsetOfMetadataTable()), regT1);
-            loadPtr(Address(regT0, CodeBlock::offsetOfBaselineJITData()), regT2);
-
-            auto metadataOK = branchPtr(Equal, regT1, s_metadataGPR);
-            breakpoint();
-            metadataOK.link(this);
-
-            auto constantsOK = branchPtr(Equal, regT2, s_constantsGPR);
-            breakpoint();
-            constantsOK.link(this);
-        }
+        if (opcodeID != op_catch)
+            m_consistencyCheckCalls.append(nearCall());
 #endif
 
         if (UNLIKELY(m_compilation)) {
@@ -281,9 +259,6 @@
             });
         }
 
-        if (opcodeID != op_catch)
-            assertStackPointerOffset();
-
         switch (opcodeID) {
         DEFINE_SLOW_OP(less)
         DEFINE_SLOW_OP(lesseq)
@@ -688,6 +663,57 @@
     Base::emitRestoreCalleeSavesFor(&RegisterAtOffsetList::llintBaselineCalleeSaveRegisters());
 }
 
+#if ASSERT_ENABLED
+MacroAssemblerCodeRef<JITThunkPtrTag> JIT::consistencyCheckGenerator(VM&)
+{
+    CCallHelpers jit;
+
+    constexpr GPRReg stackOffsetGPR = regT0; // Incoming
+    constexpr GPRReg expectedStackPointerGPR = regT1;
+    constexpr GPRReg expectedMetadataGPR = regT2;
+    constexpr GPRReg expectedConstantsGPR = regT3;
+
+    jit.tagReturnAddress();
+
+    jit.mul32(TrustedImm32(sizeof(Register)), stackOffsetGPR, stackOffsetGPR);
+    jit.subPtr(callFrameRegister, stackOffsetGPR, expectedStackPointerGPR);
+    // Fix up in case the call sequence (from the op) changed the stack pointer, e.g.: like on x86
+    if (constexpr size_t delta = sizeof(CallerFrameAndPC) - prologueStackPointerDelta())
+        jit.subPtr(TrustedImm32(delta), expectedStackPointerGPR);
+
+    jit.loadPtr(addressFor(CallFrameSlot::codeBlock), expectedConstantsGPR);
+    jit.loadPtr(Address(expectedConstantsGPR, CodeBlock::offsetOfMetadataTable()), expectedMetadataGPR);
+    jit.loadPtr(Address(expectedConstantsGPR, CodeBlock::offsetOfBaselineJITData()), expectedConstantsGPR);
+
+    auto stackPointerOK = jit.branchPtr(Equal, expectedStackPointerGPR, stackPointerRegister);
+    jit.breakpoint();
+    stackPointerOK.link(&jit);
+
+    auto metadataOK = jit.branchPtr(Equal, expectedMetadataGPR, s_metadataGPR);
+    jit.breakpoint();
+    metadataOK.link(&jit);
+
+    auto constantsOK = jit.branchPtr(Equal, expectedConstantsGPR, s_constantsGPR);
+    jit.breakpoint();
+    constantsOK.link(&jit);
+
+    jit.ret();
+
+    LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID, LinkBuffer::Profile::ExtraCTIThunk);
+    return FINALIZE_CODE(patchBuffer, JITThunkPtrTag, "Baseline: generateConsistencyCheck");
+}
+
+void JIT::emitConsistencyCheck()
+{
+    ASSERT(!m_consistencyCheckLabel.isSet());
+    m_consistencyCheckLabel = label();
+    move(TrustedImm32(-stackPointerOffsetFor(m_unlinkedCodeBlock)), regT0);
+    m_bytecodeIndex = BytecodeIndex(0);
+    emitNakedNearTailCall(vm().getCTIStub(consistencyCheckGenerator).retaggedCode<NoPtrTag>());
+    m_bytecodeIndex = BytecodeIndex(); // Reset this, in order to guard its use with ASSERTs.
+}
+#endif
+
 void JIT::compileAndLinkWithoutFinalizing(JITCompilationEffort effort)
 {
     DFG::CapabilityLevel level = m_profiledCodeBlock->capabilityLevel();
@@ -791,6 +817,10 @@
         m_disassembler->setEndOfSlowPath(label());
     m_pcToCodeOriginMapBuilder.appendItem(label(), PCToCodeOriginMapBuilder::defaultCodeOrigin());
 
+#if ASSERT_ENABLED
+    emitConsistencyCheck();
+#endif
+
     stackOverflow.link(this);
     m_bytecodeIndex = BytecodeIndex(0);
     if (maxFrameExtentForSlowPathCall)
@@ -903,6 +933,12 @@
             patchBuffer.link(record.from, record.callee);
     }
 
+#if ASSERT_ENABLED
+    const auto consistencyCheck = patchBuffer.locationOf<JSInternalPtrTag>(m_consistencyCheckLabel);
+    for (auto& call : m_consistencyCheckCalls)
+        patchBuffer.link<JSInternalPtrTag>(call, consistencyCheck);
+#endif
+
     auto finalizeICs = [&] (auto& generators) {
         for (auto& gen : generators) {
             gen.m_unlinkedStubInfo->start = patchBuffer.locationOf<JITStubRoutinePtrTag>(gen.m_start);

Modified: trunk/Source/_javascript_Core/jit/JIT.h (292766 => 292767)


--- trunk/Source/_javascript_Core/jit/JIT.h	2022-04-12 06:49:21 UTC (rev 292766)
+++ trunk/Source/_javascript_Core/jit/JIT.h	2022-04-12 07:51:30 UTC (rev 292767)
@@ -388,8 +388,6 @@
         template<typename SlowOperation>
         void emit_compareAndJumpSlowImpl(VirtualRegister op1, VirtualRegister op2, unsigned target, size_t instructionSize, DoubleCondition, SlowOperation, bool invert, Vector<SlowCaseEntry>::iterator&);
 
-        void assertStackPointerOffset();
-
         void emit_op_add(const JSInstruction*);
         void emit_op_bitand(const JSInstruction*);
         void emit_op_bitor(const JSInstruction*);
@@ -884,6 +882,11 @@
         void emitSaveCalleeSaves();
         void emitRestoreCalleeSaves();
 
+#if ASSERT_ENABLED
+        static MacroAssemblerCodeRef<JITThunkPtrTag> consistencyCheckGenerator(VM&);
+        void emitConsistencyCheck();
+#endif
+
         static bool reportCompileTimes();
         static bool computeCompileTimes();
 
@@ -921,6 +924,10 @@
 
         JumpList m_exceptionChecks;
         JumpList m_exceptionChecksWithCallFrameRollback;
+#if ASSERT_ENABLED
+        Label m_consistencyCheckLabel;
+        Vector<Call> m_consistencyCheckCalls;
+#endif
 
         unsigned m_getByIdIndex { UINT_MAX };
         unsigned m_getByValIndex { UINT_MAX };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to