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)