Title: [278875] trunk/Source/_javascript_Core
Revision
278875
Author
mark....@apple.com
Date
2021-06-15 09:09:27 -0700 (Tue, 15 Jun 2021)

Log Message

Move setting of scratch buffer active lengths to the runtime functions.
https://bugs.webkit.org/show_bug.cgi?id=227013
rdar://79325068

Reviewed by Keith Miller.

We previously emit JIT'ed code to set and unset the ScratchBuffer active length
around calls into C++ runtime functions.  This was needed because the runtime
functions may allow GC to run, and GC needs to be able to scan the values stored
in the ScratchBuffer.

In this patch, we change it so that the runtime functions that need it will
declare an ActiveScratchBufferScope RAII object that will set the ScratchBuffer
active length, and unset it on exit.  This allows us to:

1. Emit less JIT code.  The runtime function can take care of it.
2. Elide setting the ScratchBuffer active length if not needed.  The runtime
   functions know whether they can GC or not.  They only need to set the active
   length if they can GC.

Note that scanning of the active ScratchBuffer is done synchronously on the
mutator thread via Heap::gatherScratchBufferRoots(), which is called as part of
the GC conservative root scan.  This means there is no urgency / sequencing that
requires that the active length be set before calling into the runtime function.
Setting it in the runtime function itself is fine as long as it is done before
the function executes any operations that can GC.

This patch also made the following changes:

1. Introduce ActiveScratchBufferScope RAII object used to set/unset the
   ScratchBuffer length in the runtime functions.  ActiveScratchBufferScope takes
   the active length in units of number of stack slots / Registers / JSValues
   instead of bytes.

2. Deleted ScratchRegisterAllocator::preserveUsedRegistersToScratchBufferForCall()
   and ScratchRegisterAllocator::restoreUsedRegistersFromScratchBufferForCall().
   These functions are unused.

The reasoning behind what values to pass to ActiveScratchBufferScope, is any:

1. AssemblyHelpers::debugCall() in AssemblyHelpers.cpp:
   The ScratchBuffer is only used for operationDebugPrintSpeculationFailure(),
   which now declares an ActiveScratchBufferScope.

   The active length is GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters.
   See scratchSize in AssemblyHelpers::debugCall().

2. genericGenerationThunkGenerator() in FTLThunks.cpp:
   The scratch buffer size for determining the active length is
   requiredScratchMemorySizeInBytes().  

   However, genericGenerationThunkGenerator() generates code to call either
   operationCompileFTLOSRExit() or operationCompileFTLLazySlowPath().  Both of
   these functions will DeferGCForAWhile.  Hence, GC cannot run, and we don't need
   to set the active length here.

3. compileArrayPush() in FTLLowerDFGToB3.cpp:

   Cases Array::Int32, Array::Contiguous, or Array::Double calls
   operationArrayPushMultiple() or operationArrayPushDoubleMultiple().

   For operationArrayPushMultiple(), the active length is elementCount.  See
   computation of scratchSize.

   For operationArrayPushDoubleMultiple(), we don't need to set the active length
   because the ScratchBuffer only contains double values.  The GC does not need
   to scan those.

   Case Array::ArrayStorage calls operationArrayPushMultiple().
   The active length is elementCount.  See computation of scratchSize.

   compileNewArray() in FTLLowerDFGToB3.cpp:

   Calls operationNewArray().  Active length is m_node->numChildren(), which is
   passed to operationNewArray() as the size parameter.  See computation of
   scratchSize.

   compileNewArrayWithSpread() in FTLLowerDFGToB3.cpp:

   Calls operationNewArrayWithSpreadSlow().  Active length is m_node->numChildren(),
   which is passes to operationNewArrayWithSpreadSlow() as the numItems parameter.
   See computation of scratchSize.

4. osrExitGenerationThunkGenerator() in DFGThunks.cpp:

   Calls operationCompileOSRExit().  Active length is GPRInfo::numberOfRegisters +
   FPRInfo::numberOfRegisters.  See computation of scratchSize.

5. compileNewArray() in DFGSpeculativeJIT.cpp:

   Calls operationNewArray().  Active length is node->numChildren(), which is
   passed in as the size parameter.

   compileNewArrayWithSpread() in DFGSpeculativeJIT.cpp:

   Calls operationNewArrayWithSpreadSlow().  Active length is node->numChildren(),
   which is passed in as the numItems parameter.

   compileArrayPush() in DFGSpeculativeJIT.cpp:

   Calls operationArrayPushMultiple().  Active length is elementCount, which is
   passed in as the elementCount parameter.

   Calls operationArrayPushDoubleMultiple().  Active length is elementCount, but
   we don't need to set it because the ScratchBuffer only contains double values.


* dfg/DFGOSRExit.cpp:
(JSC::DFG::JSC_DEFINE_JIT_OPERATION):
* dfg/DFGOperations.cpp:
(JSC::DFG::JSC_DEFINE_JIT_OPERATION):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileNewArray):
(JSC::DFG::SpeculativeJIT::compileNewArrayWithSpread):
(JSC::DFG::SpeculativeJIT::compileArrayPush):
* dfg/DFGThunks.cpp:
(JSC::DFG::osrExitGenerationThunkGenerator):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileArrayPush):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArray):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSpread):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::JSC_DEFINE_JIT_OPERATION):
* ftl/FTLOperations.cpp:
(JSC::FTL::JSC_DEFINE_JIT_OPERATION):
* ftl/FTLThunks.cpp:
(JSC::FTL::genericGenerationThunkGenerator):
* jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::debugCall):
* jit/ScratchRegisterAllocator.cpp:
(JSC::ScratchRegisterAllocator::preserveUsedRegistersToScratchBufferForCall): Deleted.
(JSC::ScratchRegisterAllocator::restoreUsedRegistersFromScratchBufferForCall): Deleted.
* jit/ScratchRegisterAllocator.h:
* runtime/VM.h:
* runtime/VMInlines.h:
(JSC::ActiveScratchBufferScope::ActiveScratchBufferScope):
(JSC::ActiveScratchBufferScope::~ActiveScratchBufferScope):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (278874 => 278875)


--- trunk/Source/_javascript_Core/ChangeLog	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-06-15 16:09:27 UTC (rev 278875)
@@ -1,3 +1,143 @@
+2021-06-15  Mark Lam  <mark....@apple.com>
+
+        Move setting of scratch buffer active lengths to the runtime functions.
+        https://bugs.webkit.org/show_bug.cgi?id=227013
+        rdar://79325068
+
+        Reviewed by Keith Miller.
+
+        We previously emit JIT'ed code to set and unset the ScratchBuffer active length
+        around calls into C++ runtime functions.  This was needed because the runtime
+        functions may allow GC to run, and GC needs to be able to scan the values stored
+        in the ScratchBuffer.
+
+        In this patch, we change it so that the runtime functions that need it will
+        declare an ActiveScratchBufferScope RAII object that will set the ScratchBuffer
+        active length, and unset it on exit.  This allows us to:
+
+        1. Emit less JIT code.  The runtime function can take care of it.
+        2. Elide setting the ScratchBuffer active length if not needed.  The runtime
+           functions know whether they can GC or not.  They only need to set the active
+           length if they can GC.
+
+        Note that scanning of the active ScratchBuffer is done synchronously on the
+        mutator thread via Heap::gatherScratchBufferRoots(), which is called as part of
+        the GC conservative root scan.  This means there is no urgency / sequencing that
+        requires that the active length be set before calling into the runtime function.
+        Setting it in the runtime function itself is fine as long as it is done before
+        the function executes any operations that can GC.
+
+        This patch also made the following changes:
+
+        1. Introduce ActiveScratchBufferScope RAII object used to set/unset the
+           ScratchBuffer length in the runtime functions.  ActiveScratchBufferScope takes
+           the active length in units of number of stack slots / Registers / JSValues
+           instead of bytes.
+
+        2. Deleted ScratchRegisterAllocator::preserveUsedRegistersToScratchBufferForCall()
+           and ScratchRegisterAllocator::restoreUsedRegistersFromScratchBufferForCall().
+           These functions are unused.
+
+        The reasoning behind what values to pass to ActiveScratchBufferScope, is any:
+
+        1. AssemblyHelpers::debugCall() in AssemblyHelpers.cpp:
+           The ScratchBuffer is only used for operationDebugPrintSpeculationFailure(),
+           which now declares an ActiveScratchBufferScope.
+
+           The active length is GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters.
+           See scratchSize in AssemblyHelpers::debugCall().
+
+        2. genericGenerationThunkGenerator() in FTLThunks.cpp:
+           The scratch buffer size for determining the active length is
+           requiredScratchMemorySizeInBytes().  
+
+           However, genericGenerationThunkGenerator() generates code to call either
+           operationCompileFTLOSRExit() or operationCompileFTLLazySlowPath().  Both of
+           these functions will DeferGCForAWhile.  Hence, GC cannot run, and we don't need
+           to set the active length here.
+
+        3. compileArrayPush() in FTLLowerDFGToB3.cpp:
+
+           Cases Array::Int32, Array::Contiguous, or Array::Double calls
+           operationArrayPushMultiple() or operationArrayPushDoubleMultiple().
+
+           For operationArrayPushMultiple(), the active length is elementCount.  See
+           computation of scratchSize.
+
+           For operationArrayPushDoubleMultiple(), we don't need to set the active length
+           because the ScratchBuffer only contains double values.  The GC does not need
+           to scan those.
+
+           Case Array::ArrayStorage calls operationArrayPushMultiple().
+           The active length is elementCount.  See computation of scratchSize.
+
+           compileNewArray() in FTLLowerDFGToB3.cpp:
+
+           Calls operationNewArray().  Active length is m_node->numChildren(), which is
+           passed to operationNewArray() as the size parameter.  See computation of
+           scratchSize.
+
+           compileNewArrayWithSpread() in FTLLowerDFGToB3.cpp:
+
+           Calls operationNewArrayWithSpreadSlow().  Active length is m_node->numChildren(),
+           which is passes to operationNewArrayWithSpreadSlow() as the numItems parameter.
+           See computation of scratchSize.
+
+        4. osrExitGenerationThunkGenerator() in DFGThunks.cpp:
+
+           Calls operationCompileOSRExit().  Active length is GPRInfo::numberOfRegisters +
+           FPRInfo::numberOfRegisters.  See computation of scratchSize.
+
+        5. compileNewArray() in DFGSpeculativeJIT.cpp:
+
+           Calls operationNewArray().  Active length is node->numChildren(), which is
+           passed in as the size parameter.
+
+           compileNewArrayWithSpread() in DFGSpeculativeJIT.cpp:
+
+           Calls operationNewArrayWithSpreadSlow().  Active length is node->numChildren(),
+           which is passed in as the numItems parameter.
+
+           compileArrayPush() in DFGSpeculativeJIT.cpp:
+
+           Calls operationArrayPushMultiple().  Active length is elementCount, which is
+           passed in as the elementCount parameter.
+
+           Calls operationArrayPushDoubleMultiple().  Active length is elementCount, but
+           we don't need to set it because the ScratchBuffer only contains double values.
+
+
+        * dfg/DFGOSRExit.cpp:
+        (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
+        * dfg/DFGOperations.cpp:
+        (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileNewArray):
+        (JSC::DFG::SpeculativeJIT::compileNewArrayWithSpread):
+        (JSC::DFG::SpeculativeJIT::compileArrayPush):
+        * dfg/DFGThunks.cpp:
+        (JSC::DFG::osrExitGenerationThunkGenerator):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileArrayPush):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewArray):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSpread):
+        * ftl/FTLOSRExitCompiler.cpp:
+        (JSC::FTL::JSC_DEFINE_JIT_OPERATION):
+        * ftl/FTLOperations.cpp:
+        (JSC::FTL::JSC_DEFINE_JIT_OPERATION):
+        * ftl/FTLThunks.cpp:
+        (JSC::FTL::genericGenerationThunkGenerator):
+        * jit/AssemblyHelpers.cpp:
+        (JSC::AssemblyHelpers::debugCall):
+        * jit/ScratchRegisterAllocator.cpp:
+        (JSC::ScratchRegisterAllocator::preserveUsedRegistersToScratchBufferForCall): Deleted.
+        (JSC::ScratchRegisterAllocator::restoreUsedRegistersFromScratchBufferForCall): Deleted.
+        * jit/ScratchRegisterAllocator.h:
+        * runtime/VM.h:
+        * runtime/VMInlines.h:
+        (JSC::ActiveScratchBufferScope::ActiveScratchBufferScope):
+        (JSC::ActiveScratchBufferScope::~ActiveScratchBufferScope):
+
 2021-06-14  Yusuke Suzuki  <ysuz...@apple.com>
 
         [JSC] Workaround ICU uloc_addLikelySubtags / uloc_minimizeSubtags bugs

Modified: trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp (278874 => 278875)


--- trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExit.cpp	2021-06-15 16:09:27 UTC (rev 278875)
@@ -41,6 +41,7 @@
 #include "JSCJSValueInlines.h"
 #include "OperandsInlines.h"
 #include "ProbeContext.h"
+#include "VMInlines.h"
 
 #include <wtf/Scope.h>
 
@@ -144,6 +145,7 @@
 {
     VM& vm = callFrame->deprecatedVM();
     auto scope = DECLARE_THROW_SCOPE(vm);
+    ActiveScratchBufferScope activeScratchBufferScope(vm, GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters);
 
     if constexpr (validateDFGDoesGC) {
         // We're about to exit optimized code. So, there's no longer any optimized
@@ -890,6 +892,7 @@
 {
     VM& vm = callFrame->deprecatedVM();
     NativeCallFrameTracer tracer(vm, callFrame);
+    ActiveScratchBufferScope activeScratchBufferScope(vm, GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters);
 
     SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw);
     CodeBlock* codeBlock = debugInfo->codeBlock;

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (278874 => 278875)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2021-06-15 16:09:27 UTC (rev 278875)
@@ -1039,6 +1039,7 @@
     VM& vm = globalObject->vm();
     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+    ActiveScratchBufferScope activeScratchBufferScope(vm, elementCount);
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     // We assume that multiple JSArray::push calls with ArrayWithInt32/ArrayWithContiguous do not cause JS traps.
@@ -1064,6 +1065,7 @@
     VM& vm = globalObject->vm();
     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+    // Don't need a ActiveScratchBufferScope here because the scratch buffer only contains double values for this call.
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     // We assume that multiple JSArray::push calls with ArrayWithDouble do not cause JS traps.
@@ -1732,7 +1734,8 @@
     VM& vm = globalObject->vm();
     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
-    
+    ActiveScratchBufferScope activeScratchBufferScope(vm, size);
+
     return bitwise_cast<char*>(constructArray(globalObject, arrayStructure, static_cast<JSValue*>(buffer), size));
 }
 
@@ -3039,6 +3042,7 @@
     VM& vm = globalObject->vm();
     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
+    ActiveScratchBufferScope activeScratchBufferScope(vm, numItems);
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     EncodedJSValue* values = static_cast<EncodedJSValue*>(buffer);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (278874 => 278875)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2021-06-15 16:09:27 UTC (rev 278875)
@@ -9167,14 +9167,6 @@
 
     flushRegisters();
 
-    if (scratchSize) {
-        GPRTemporary scratch(this);
-
-        // Tell GC mark phase how much of the scratch buffer is active during call.
-        m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), scratch.gpr());
-        m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
-    }
-
     GPRFlushedCallResult result(this);
 
     callOperation(
@@ -9182,13 +9174,6 @@
         static_cast<void*>(buffer), size_t(node->numChildren()));
     m_jit.exceptionCheck();
 
-    if (scratchSize) {
-        GPRTemporary scratch(this);
-
-        m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), scratch.gpr());
-        m_jit.storePtr(TrustedImmPtr(nullptr), scratch.gpr());
-    }
-
     cellResult(result.gpr(), node, UseChildrenCalledExplicitly);
 }
 
@@ -9339,12 +9324,6 @@
         }
     }
 
-    {
-        GPRTemporary scratch(this);
-        m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), scratch.gpr());
-        m_jit.storePtr(TrustedImmPtr(scratchSize), MacroAssembler::Address(scratch.gpr()));
-    }
-
     flushRegisters();
 
     GPRFlushedCallResult result(this);
@@ -9352,11 +9331,6 @@
 
     callOperation(operationNewArrayWithSpreadSlow, resultGPR, TrustedImmPtr::weakPointer(m_graph, globalObject), buffer, node->numChildren());
     m_jit.exceptionCheck();
-    {
-        GPRTemporary scratch(this);
-        m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), scratch.gpr());
-        m_jit.storePtr(TrustedImmPtr(nullptr), MacroAssembler::Address(scratch.gpr()));
-    }
 
     cellResult(resultGPR, node);
 }
@@ -9875,8 +9849,6 @@
         size_t scratchSize = sizeof(EncodedJSValue) * elementCount;
         ScratchBuffer* scratchBuffer = vm().scratchBufferForSize(scratchSize);
         m_jit.move(TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())), bufferGPR);
-        m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), storageLengthGPR);
-        m_jit.storePtr(TrustedImmPtr(scratchSize), MacroAssembler::Address(storageLengthGPR));
 
         storageDone.link(&m_jit);
         for (unsigned elementIndex = 0; elementIndex < elementCount; ++elementIndex) {
@@ -9892,9 +9864,6 @@
 
         addSlowPathGenerator(slowPathCall(m_jit.jump(), this, operationArrayPushMultiple, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, bufferGPR, TrustedImm32(elementCount)));
 
-        m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), bufferGPR);
-        m_jit.storePtr(TrustedImmPtr(nullptr), MacroAssembler::Address(bufferGPR));
-
         base.use();
         storage.use();
 
@@ -9949,8 +9918,6 @@
         size_t scratchSize = sizeof(double) * elementCount;
         ScratchBuffer* scratchBuffer = vm().scratchBufferForSize(scratchSize);
         m_jit.move(TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())), bufferGPR);
-        m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), storageLengthGPR);
-        m_jit.storePtr(TrustedImmPtr(scratchSize), MacroAssembler::Address(storageLengthGPR));
 
         storageDone.link(&m_jit);
         for (unsigned elementIndex = 0; elementIndex < elementCount; ++elementIndex) {
@@ -9966,9 +9933,6 @@
 
         addSlowPathGenerator(slowPathCall(m_jit.jump(), this, operationArrayPushDoubleMultiple, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, bufferGPR, TrustedImm32(elementCount)));
 
-        m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), bufferGPR);
-        m_jit.storePtr(TrustedImmPtr(nullptr), MacroAssembler::Address(bufferGPR));
-
         base.use();
         storage.use();
 
@@ -10030,8 +9994,6 @@
         size_t scratchSize = sizeof(EncodedJSValue) * elementCount;
         ScratchBuffer* scratchBuffer = vm().scratchBufferForSize(scratchSize);
         m_jit.move(TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())), bufferGPR);
-        m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), storageLengthGPR);
-        m_jit.storePtr(TrustedImmPtr(scratchSize), MacroAssembler::Address(storageLengthGPR));
 
         storageDone.link(&m_jit);
         for (unsigned elementIndex = 0; elementIndex < elementCount; ++elementIndex) {
@@ -10048,9 +10010,6 @@
         addSlowPathGenerator(
             slowPathCall(m_jit.jump(), this, operationArrayPushMultiple, resultRegs, TrustedImmPtr::weakPointer(m_graph, m_graph.globalObjectFor(node->origin.semantic)), baseGPR, bufferGPR, TrustedImm32(elementCount)));
 
-        m_jit.move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), bufferGPR);
-        m_jit.storePtr(TrustedImmPtr(nullptr), MacroAssembler::Address(bufferGPR));
-
         base.use();
         storage.use();
 

Modified: trunk/Source/_javascript_Core/dfg/DFGThunks.cpp (278874 => 278875)


--- trunk/Source/_javascript_Core/dfg/DFGThunks.cpp	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/dfg/DFGThunks.cpp	2021-06-15 16:09:27 UTC (rev 278875)
@@ -31,11 +31,11 @@
 #include "CCallHelpers.h"
 #include "DFGJITCode.h"
 #include "DFGOSRExit.h"
+#include "DFGOSRExitCompilerCommon.h"
 #include "FPRInfo.h"
 #include "GPRInfo.h"
 #include "LinkBuffer.h"
 #include "MacroAssembler.h"
-#include "DFGOSRExitCompilerCommon.h"
 
 namespace JSC { namespace DFG {
 
@@ -62,10 +62,6 @@
         jit.storeDouble(FPRInfo::toRegister(i), MacroAssembler::Address(GPRInfo::regT0));
     }
     
-    // Tell GC mark phase how much of the scratch buffer is active during call.
-    jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->addressOfActiveLength()), GPRInfo::regT0);
-    jit.storePtr(MacroAssembler::TrustedImmPtr(scratchSize), MacroAssembler::Address(GPRInfo::regT0));
-
     // Set up one argument.
     jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     jit.prepareCallOperation(vm);
@@ -72,9 +68,6 @@
 
     MacroAssembler::Call functionCall = jit.call(OperationPtrTag);
 
-    jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->addressOfActiveLength()), GPRInfo::regT0);
-    jit.storePtr(MacroAssembler::TrustedImmPtr(nullptr), MacroAssembler::Address(GPRInfo::regT0));
-
     for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
         jit.move(MacroAssembler::TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
         jit.loadDouble(MacroAssembler::Address(GPRInfo::regT0), FPRInfo::toRegister(i));

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (278874 => 278875)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2021-06-15 16:09:27 UTC (rev 278875)
@@ -6162,7 +6162,6 @@
             static_assert(sizeof(EncodedJSValue) == sizeof(double), "");
             ASSERT(scratchSize);
             ScratchBuffer* scratchBuffer = vm().scratchBufferForSize(scratchSize);
-            m_out.storePtr(m_out.constIntPtr(scratchSize), m_out.absolute(scratchBuffer->addressOfActiveLength()));
             ValueFromBlock slowBufferResult = m_out.anchor(m_out.constIntPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())));
             m_out.jump(setup);
 
@@ -6192,7 +6191,6 @@
             if (m_node->arrayMode().type() == Array::Double)
                 operation = &operationArrayPushDoubleMultiple;
             ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, operation, weakPointer(globalObject), base, buffer, m_out.constInt32(elementCount)));
-            m_out.storePtr(m_out.constIntPtr(0), m_out.absolute(scratchBuffer->addressOfActiveLength()));
             m_out.jump(continuation);
 
             m_out.appendTo(continuation, lastNext);
@@ -6268,7 +6266,6 @@
             size_t scratchSize = sizeof(EncodedJSValue) * elementCount;
             ASSERT(scratchSize);
             ScratchBuffer* scratchBuffer = vm().scratchBufferForSize(scratchSize);
-            m_out.storePtr(m_out.constIntPtr(scratchSize), m_out.absolute(scratchBuffer->addressOfActiveLength()));
             ValueFromBlock slowBufferResult = m_out.anchor(m_out.constIntPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())));
             m_out.jump(setup);
 
@@ -6286,7 +6283,6 @@
 
             m_out.appendTo(slowCallPath, continuation);
             ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, operationArrayPushMultiple, weakPointer(globalObject), base, buffer, m_out.constInt32(elementCount)));
-            m_out.storePtr(m_out.constIntPtr(0), m_out.absolute(scratchBuffer->addressOfActiveLength()));
             m_out.jump(continuation);
 
             m_out.appendTo(continuation, lastNext);
@@ -7278,17 +7274,12 @@
             }
             m_out.store64(valueToStore, m_out.absolute(buffer + operandIndex));
         }
-        
-        m_out.storePtr(
-            m_out.constIntPtr(scratchSize), m_out.absolute(scratchBuffer->addressOfActiveLength()));
-        
+
         LValue result = vmCall(
             Int64, operationNewArray, weakPointer(globalObject),
             weakStructure(structure), m_out.constIntPtr(buffer),
             m_out.constIntPtr(m_node->numChildren()));
-        
-        m_out.storePtr(m_out.intPtrZero, m_out.absolute(scratchBuffer->addressOfActiveLength()));
-        
+
         setJSValue(result);
     }
 
@@ -7524,9 +7515,7 @@
             m_out.store64(value, m_out.absolute(&buffer[i]));
         }
 
-        m_out.storePtr(m_out.constIntPtr(scratchSize), m_out.absolute(scratchBuffer->addressOfActiveLength()));
         LValue result = vmCall(Int64, operationNewArrayWithSpreadSlow, weakPointer(globalObject), m_out.constIntPtr(buffer), m_out.constInt32(m_node->numChildren()));
-        m_out.storePtr(m_out.constIntPtr(0), m_out.absolute(scratchBuffer->addressOfActiveLength()));
 
         setJSValue(result);
     }

Modified: trunk/Source/_javascript_Core/ftl/FTLOSRExitCompiler.cpp (278874 => 278875)


--- trunk/Source/_javascript_Core/ftl/FTLOSRExitCompiler.cpp	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/ftl/FTLOSRExitCompiler.cpp	2021-06-15 16:09:27 UTC (rev 278875)
@@ -523,6 +523,7 @@
         dataLog("Compiling OSR exit with exitID = ", exitID, "\n");
 
     VM& vm = callFrame->deprecatedVM();
+    // Don't need an ActiveScratchBufferScope here because we DeferGCForAWhile below.
 
     if constexpr (validateDFGDoesGC) {
         // We're about to exit optimized code. So, there's no longer any optimized

Modified: trunk/Source/_javascript_Core/ftl/FTLOperations.cpp (278874 => 278875)


--- trunk/Source/_javascript_Core/ftl/FTLOperations.cpp	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/ftl/FTLOperations.cpp	2021-06-15 16:09:27 UTC (rev 278875)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014-2020 Apple Inc. All rights reserved.
+ * Copyright (C) 2014-2021 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -730,6 +730,7 @@
 JSC_DEFINE_JIT_OPERATION(operationCompileFTLLazySlowPath, void*, (CallFrame* callFrame, unsigned index))
 {
     VM& vm = callFrame->deprecatedVM();
+    // Don't need an ActiveScratchBufferScope here because we DeferGCForAWhile.
 
     // We cannot GC. We've got pointers in evil places.
     DeferGCForAWhile deferGC(vm.heap);

Modified: trunk/Source/_javascript_Core/ftl/FTLThunks.cpp (278874 => 278875)


--- trunk/Source/_javascript_Core/ftl/FTLThunks.cpp	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/ftl/FTLThunks.cpp	2021-06-15 16:09:27 UTC (rev 278875)
@@ -76,10 +76,6 @@
     char* buffer = static_cast<char*>(scratchBuffer->dataBuffer());
     
     saveAllRegisters(jit, buffer);
-    
-    // Tell GC mark phase how much of the scratch buffer is active during call.
-    jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->addressOfActiveLength()), GPRInfo::nonArgGPR1);
-    jit.storePtr(MacroAssembler::TrustedImmPtr(requiredScratchMemorySizeInBytes()), GPRInfo::nonArgGPR1);
 
     jit.loadPtr(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     jit.peek(
@@ -94,11 +90,7 @@
     // return address "slot" (be it a register or the stack).
     
     jit.move(GPRInfo::returnValueGPR, GPRInfo::regT0);
-    
-    // Make sure we tell the GC that we're not using the scratch buffer anymore.
-    jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->addressOfActiveLength()), GPRInfo::regT1);
-    jit.storePtr(MacroAssembler::TrustedImmPtr(nullptr), GPRInfo::regT1);
-    
+
     // Prepare for tail call.
     while (numberOfRequiredPops--)
         jit.popToRestore(GPRInfo::regT1);

Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp (278874 => 278875)


--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp	2021-06-15 16:09:27 UTC (rev 278875)
@@ -966,10 +966,6 @@
         storeDouble(FPRInfo::toRegister(i), GPRInfo::regT0);
     }
 
-    // Tell GC mark phase how much of the scratch buffer is active during call.
-    move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), GPRInfo::regT0);
-    storePtr(TrustedImmPtr(scratchSize), GPRInfo::regT0);
-
 #if CPU(X86_64) || CPU(ARM_THUMB2) || CPU(ARM64) || CPU(MIPS)
     move(TrustedImmPtr(buffer), GPRInfo::argumentGPR2);
     move(TrustedImmPtr(argument), GPRInfo::argumentGPR1);
@@ -982,9 +978,6 @@
     move(TrustedImmPtr(tagCFunctionPtr<OperationPtrTag>(function)), scratch);
     call(scratch, OperationPtrTag);
 
-    move(TrustedImmPtr(scratchBuffer->addressOfActiveLength()), GPRInfo::regT0);
-    storePtr(TrustedImmPtr(nullptr), GPRInfo::regT0);
-
     for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
         move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
         loadDouble(GPRInfo::regT0, FPRInfo::toRegister(i));

Modified: trunk/Source/_javascript_Core/jit/ScratchRegisterAllocator.cpp (278874 => 278875)


--- trunk/Source/_javascript_Core/jit/ScratchRegisterAllocator.cpp	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/jit/ScratchRegisterAllocator.cpp	2021-06-15 16:09:27 UTC (rev 278875)
@@ -161,73 +161,6 @@
     return usedRegistersForCall().numberOfSetRegisters() * sizeof(JSValue);
 }
 
-void ScratchRegisterAllocator::preserveUsedRegistersToScratchBufferForCall(MacroAssembler& jit, ScratchBuffer* scratchBuffer, GPRReg scratchGPR)
-{
-    RegisterSet usedRegisters = usedRegistersForCall();
-    if (!usedRegisters.numberOfSetRegisters())
-        return;
-    
-    unsigned count = 0;
-    for (GPRReg reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
-        if (usedRegisters.get(reg)) {
-            jit.storePtr(reg, static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + count);
-            count++;
-        }
-        if (GPRInfo::toIndex(reg) != GPRInfo::InvalidIndex
-            && scratchGPR == InvalidGPRReg
-            && !m_lockedRegisters.get(reg) && !m_scratchRegisters.get(reg))
-            scratchGPR = reg;
-    }
-    RELEASE_ASSERT(scratchGPR != InvalidGPRReg);
-    for (FPRReg reg = MacroAssembler::firstFPRegister(); reg <= MacroAssembler::lastFPRegister(); reg = MacroAssembler::nextFPRegister(reg)) {
-        if (usedRegisters.get(reg)) {
-            jit.move(MacroAssembler::TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + count), scratchGPR);
-            count++;
-            jit.storeDouble(reg, scratchGPR);
-        }
-    }
-    RELEASE_ASSERT(count * sizeof(JSValue) == desiredScratchBufferSizeForCall());
-    
-    jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->addressOfActiveLength()), scratchGPR);
-    jit.storePtr(MacroAssembler::TrustedImmPtr(static_cast<size_t>(count * sizeof(JSValue))), scratchGPR);
-}
-
-void ScratchRegisterAllocator::restoreUsedRegistersFromScratchBufferForCall(MacroAssembler& jit, ScratchBuffer* scratchBuffer, GPRReg scratchGPR)
-{
-    RegisterSet usedRegisters = usedRegistersForCall();
-    if (!usedRegisters.numberOfSetRegisters())
-        return;
-    
-    if (scratchGPR == InvalidGPRReg) {
-        // Find a scratch register.
-        for (unsigned i = GPRInfo::numberOfRegisters; i--;) {
-            if (m_lockedRegisters.getGPRByIndex(i) || m_scratchRegisters.getGPRByIndex(i))
-                continue;
-            scratchGPR = GPRInfo::toRegister(i);
-            break;
-        }
-    }
-    RELEASE_ASSERT(scratchGPR != InvalidGPRReg);
-    
-    jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->addressOfActiveLength()), scratchGPR);
-    jit.storePtr(MacroAssembler::TrustedImmPtr(nullptr), scratchGPR);
-
-    // Restore double registers first.
-    unsigned count = usedRegisters.numberOfSetGPRs();
-    for (FPRReg reg = MacroAssembler::firstFPRegister(); reg <= MacroAssembler::lastFPRegister(); reg = MacroAssembler::nextFPRegister(reg)) {
-        if (usedRegisters.get(reg)) {
-            jit.move(MacroAssembler::TrustedImmPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + (count++)), scratchGPR);
-            jit.loadDouble(scratchGPR, reg);
-        }
-    }
-        
-    count = 0;
-    for (GPRReg reg = MacroAssembler::firstRegister(); reg <= MacroAssembler::lastRegister(); reg = MacroAssembler::nextRegister(reg)) {
-        if (usedRegisters.get(reg))
-            jit.loadPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) + (count++), reg);
-    }
-}
-
 unsigned ScratchRegisterAllocator::preserveRegistersToStackForCall(MacroAssembler& jit, const RegisterSet& usedRegisters, unsigned extraBytesAtTopOfStack)
 {
     RELEASE_ASSERT(extraBytesAtTopOfStack % sizeof(void*) == 0);

Modified: trunk/Source/_javascript_Core/jit/ScratchRegisterAllocator.h (278874 => 278875)


--- trunk/Source/_javascript_Core/jit/ScratchRegisterAllocator.h	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/jit/ScratchRegisterAllocator.h	2021-06-15 16:09:27 UTC (rev 278875)
@@ -91,9 +91,6 @@
     
     unsigned desiredScratchBufferSizeForCall() const;
     
-    void preserveUsedRegistersToScratchBufferForCall(MacroAssembler& jit, ScratchBuffer* scratchBuffer, GPRReg scratchGPR = InvalidGPRReg);
-    void restoreUsedRegistersFromScratchBufferForCall(MacroAssembler& jit, ScratchBuffer* scratchBuffer, GPRReg scratchGPR = InvalidGPRReg);
-
     static unsigned preserveRegistersToStackForCall(MacroAssembler& jit, const RegisterSet& usedRegisters, unsigned extraPaddingInBytes);
     static void restoreRegistersFromStackForCall(MacroAssembler& jit, const RegisterSet& usedRegisters, const RegisterSet& ignore, unsigned numberOfStackBytesUsedForRegisterPreservation, unsigned extraPaddingInBytes);
 

Modified: trunk/Source/_javascript_Core/runtime/VM.h (278874 => 278875)


--- trunk/Source/_javascript_Core/runtime/VM.h	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2021-06-15 16:09:27 UTC (rev 278875)
@@ -280,6 +280,15 @@
 #pragma warning(pop)
 #endif
 
+class ActiveScratchBufferScope {
+public:
+    ActiveScratchBufferScope(VM&, size_t activeScratchBufferSizeInJSValues);
+    ~ActiveScratchBufferScope();
+
+private:
+    ScratchBuffer* m_scratchBuffer;
+};
+
 class VM : public ThreadSafeRefCounted<VM>, public DoublyLinkedListNode<VM> {
 public:
     // WebCore has a one-to-one mapping of threads to VMs;

Modified: trunk/Source/_javascript_Core/runtime/VMInlines.h (278874 => 278875)


--- trunk/Source/_javascript_Core/runtime/VMInlines.h	2021-06-15 14:47:54 UTC (rev 278874)
+++ trunk/Source/_javascript_Core/runtime/VMInlines.h	2021-06-15 16:09:27 UTC (rev 278875)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2021 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,7 +31,22 @@
 #include "Watchdog.h"
 
 namespace JSC {
-    
+
+inline ActiveScratchBufferScope::ActiveScratchBufferScope(VM& vm, size_t activeScratchBufferSizeInJSValues)
+    : m_scratchBuffer(vm.scratchBufferForSize(activeScratchBufferSizeInJSValues * sizeof(EncodedJSValue)))
+{
+    // Tell GC mark phase how much of the scratch buffer is active during the call operation this scope is used in.
+    if (m_scratchBuffer)
+        m_scratchBuffer->u.m_activeLength = activeScratchBufferSizeInJSValues * sizeof(EncodedJSValue);
+}
+
+inline ActiveScratchBufferScope::~ActiveScratchBufferScope()
+{
+    // Tell the GC that we're not using the scratch buffer anymore.
+    if (m_scratchBuffer)
+        m_scratchBuffer->u.m_activeLength = 0;
+}
+
 bool VM::ensureStackCapacityFor(Register* newTopOfStack)
 {
 #if !ENABLE(C_LOOP)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to