Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (117728 => 117729)
--- trunk/Source/_javascript_Core/ChangeLog 2012-05-21 05:42:25 UTC (rev 117728)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-05-21 05:42:56 UTC (rev 117729)
@@ -1,3 +1,47 @@
+2012-05-20 Michael Saboff <[email protected]>
+
+ JSGlobalData ScratchBuffers Are Not Visited During Garbage Collection
+ https://bugs.webkit.org/show_bug.cgi?id=86553
+
+ Reviewed by Gavin Barraclough.
+
+ Scratch buffers can contain the only reference to live objects.
+ Therefore visit scratch buffer contents as conservative roots.
+ Changed the scratch buffers to be a struct with an "active"
+ length and the actual buffer. The users of the scratch
+ buffer emit code where needed to set and clear the active
+ length as appropriate. During marking, the active count is
+ used for conservative marking.
+
+ * dfg/DFGAssemblyHelpers.h:
+ (JSC::DFG::AssemblyHelpers::debugCall):
+ * dfg/DFGOSRExitCompiler32_64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGOSRExitCompiler64.cpp:
+ (JSC::DFG::OSRExitCompiler::compileExit):
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGThunks.cpp:
+ (JSC::DFG::osrExitGenerationThunkGenerator):
+ * heap/Heap.cpp:
+ (JSC::Heap::markRoots):
+ * runtime/JSGlobalData.cpp:
+ (JSC::JSGlobalData::gatherConservativeRoots):
+ * runtime/JSGlobalData.h:
+ (JSC::ScratchBuffer::ScratchBuffer):
+ (ScratchBuffer):
+ (JSC::ScratchBuffer::allocationSize):
+ (JSC::ScratchBuffer::setActiveLength):
+ (JSC::ScratchBuffer::activeLength):
+ (JSC::ScratchBuffer::activeLengthPtr):
+ (JSC::ScratchBuffer::dataBuffer):
+ (JSGlobalData):
+ (JSC::JSGlobalData::scratchBufferForSize):
+
2012-05-20 Filip Pizlo <[email protected]>
Predicted types should know about arguments
Modified: trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.h (117728 => 117729)
--- trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.h 2012-05-21 05:42:25 UTC (rev 117728)
+++ trunk/Source/_javascript_Core/dfg/DFGAssemblyHelpers.h 2012-05-21 05:42:56 UTC (rev 117729)
@@ -170,14 +170,21 @@
// Add a debug call. This call has no effect on JIT code execution state.
void debugCall(V_DFGDebugOperation_EP function, void* argument)
{
- EncodedJSValue* buffer = static_cast<EncodedJSValue*>(m_globalData->scratchBufferForSize(sizeof(EncodedJSValue) * (GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters)));
-
+ size_t scratchSize = sizeof(EncodedJSValue) * (GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters);
+ ScratchBuffer* scratchBuffer = m_globalData->scratchBufferForSize(scratchSize);
+ EncodedJSValue* buffer = static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer());
+
for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i)
storePtr(GPRInfo::toRegister(i), buffer + i);
for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
storeDouble(FPRInfo::toRegister(i), GPRInfo::regT0);
}
+
+ // Tell GC mark phase how much of the scratch buffer is active during call.
+ move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), GPRInfo::regT0);
+ storePtr(TrustedImmPtr(scratchSize), GPRInfo::regT0);
+
#if CPU(X86_64) || CPU(ARM_THUMB2)
move(TrustedImmPtr(argument), GPRInfo::argumentGPR1);
move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
@@ -191,6 +198,10 @@
#endif
move(TrustedImmPtr(reinterpret_cast<void*>(function)), scratch);
call(scratch);
+
+ move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), GPRInfo::regT0);
+ storePtr(TrustedImmPtr(0), 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/dfg/DFGOSRExitCompiler32_64.cpp (117728 => 117729)
--- trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler32_64.cpp 2012-05-21 05:42:25 UTC (rev 117728)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler32_64.cpp 2012-05-21 05:42:56 UTC (rev 117729)
@@ -90,13 +90,14 @@
GPRReg scratch = GPRInfo::regT0;
if (scratch == exit.m_jsValueSource.base())
scratch = GPRInfo::regT1;
- EncodedJSValue* scratchBuffer = static_cast<EncodedJSValue*>(m_jit.globalData()->scratchBufferForSize(sizeof(uint32_t)));
- m_jit.store32(scratch, scratchBuffer);
+ ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(sizeof(uint32_t));
+ EncodedJSValue* scratchDataBuffer = static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer());
+ m_jit.store32(scratch, scratchDataBuffer);
m_jit.load32(exit.m_jsValueSource.asAddress(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), scratch);
m_jit.store32(scratch, &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.tag);
m_jit.load32(exit.m_jsValueSource.asAddress(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), scratch);
m_jit.store32(scratch, &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.payload);
- m_jit.load32(scratchBuffer, scratch);
+ m_jit.load32(scratchDataBuffer, scratch);
} else if (exit.m_jsValueSource.hasKnownTag()) {
m_jit.store32(AssemblyHelpers::TrustedImm32(exit.m_jsValueSource.tag()), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.tag);
m_jit.store32(exit.m_jsValueSource.payloadGPR(), &bitwise_cast<EncodedValueDescriptor*>(bucket)->asBits.payload);
@@ -199,7 +200,8 @@
}
unsigned scratchBufferLengthBeforeUInt32s = numberOfPoisonedVirtualRegisters + ((numberOfDisplacedVirtualRegisters * 2) <= GPRInfo::numberOfRegisters ? 0 : numberOfDisplacedVirtualRegisters);
- EncodedJSValue* scratchBuffer = static_cast<EncodedJSValue*>(m_jit.globalData()->scratchBufferForSize(sizeof(EncodedJSValue) * (scratchBufferLengthBeforeUInt32s + (haveUInt32s ? 2 : 0))));
+ ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(sizeof(EncodedJSValue) * (scratchBufferLengthBeforeUInt32s + (haveUInt32s ? 2 : 0)));
+ EncodedJSValue* scratchDataBuffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
// From here on, the code assumes that it is profitable to maximize the distance
// between when something is computed and when it is stored.
@@ -243,7 +245,7 @@
case UnboxedInt32InGPR:
case UnboxedBooleanInGPR:
if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
- m_jit.store32(recovery.gpr(), reinterpret_cast<char*>(scratchBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+ m_jit.store32(recovery.gpr(), reinterpret_cast<char*>(scratchDataBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
m_poisonScratchIndices[exit.variableForIndex(index)] = currentPoisonIndex;
currentPoisonIndex++;
} else {
@@ -260,8 +262,8 @@
break;
case InPair:
if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
- m_jit.store32(recovery.tagGPR(), reinterpret_cast<char*>(scratchBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
- m_jit.store32(recovery.payloadGPR(), reinterpret_cast<char*>(scratchBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+ m_jit.store32(recovery.tagGPR(), reinterpret_cast<char*>(scratchDataBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+ m_jit.store32(recovery.payloadGPR(), reinterpret_cast<char*>(scratchDataBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
m_poisonScratchIndices[exit.variableForIndex(index)] = currentPoisonIndex;
currentPoisonIndex++;
} else {
@@ -270,7 +272,7 @@
}
break;
case UInt32InGPR: {
- EncodedJSValue* myScratch = scratchBuffer + scratchBufferLengthBeforeUInt32s;
+ EncodedJSValue* myScratch = scratchDataBuffer + scratchBufferLengthBeforeUInt32s;
GPRReg addressGPR = GPRInfo::regT0;
if (addressGPR == recovery.gpr())
@@ -285,7 +287,7 @@
m_jit.convertInt32ToDouble(recovery.gpr(), FPRInfo::fpRegT0);
m_jit.addDouble(AssemblyHelpers::AbsoluteAddress(&AssemblyHelpers::twoToThe32), FPRInfo::fpRegT0);
if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
- m_jit.move(AssemblyHelpers::TrustedImmPtr(scratchBuffer + currentPoisonIndex), addressGPR);
+ m_jit.move(AssemblyHelpers::TrustedImmPtr(scratchDataBuffer + currentPoisonIndex), addressGPR);
m_jit.storeDouble(FPRInfo::fpRegT0, addressGPR);
} else
m_jit.storeDouble(FPRInfo::fpRegT0, AssemblyHelpers::addressFor((VirtualRegister)operand));
@@ -295,8 +297,8 @@
positive.link(&m_jit);
if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
- m_jit.store32(recovery.gpr(), reinterpret_cast<char*>(scratchBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
- m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), reinterpret_cast<char*>(scratchBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+ m_jit.store32(recovery.gpr(), reinterpret_cast<char*>(scratchDataBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+ m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), reinterpret_cast<char*>(scratchDataBuffer + currentPoisonIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
} else {
m_jit.store32(recovery.gpr(), AssemblyHelpers::payloadFor((VirtualRegister)operand));
m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), AssemblyHelpers::tagFor((VirtualRegister)operand));
@@ -327,7 +329,7 @@
if (recovery.technique() != InFPR)
continue;
if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
- m_jit.storeDouble(recovery.fpr(), scratchBuffer + currentPoisonIndex);
+ m_jit.storeDouble(recovery.fpr(), scratchDataBuffer + currentPoisonIndex);
m_poisonScratchIndices[exit.variableForIndex(index)] = currentPoisonIndex;
currentPoisonIndex++;
} else
@@ -413,15 +415,15 @@
case DisplacedInRegisterFile:
m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::regT0);
m_jit.load32(AssemblyHelpers::tagFor(recovery.virtualRegister()), GPRInfo::regT1);
- m_jit.store32(GPRInfo::regT0, reinterpret_cast<char*>(scratchBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
- m_jit.store32(GPRInfo::regT1, reinterpret_cast<char*>(scratchBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
+ m_jit.store32(GPRInfo::regT0, reinterpret_cast<char*>(scratchDataBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+ m_jit.store32(GPRInfo::regT1, reinterpret_cast<char*>(scratchDataBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
scratchIndex++;
break;
case Int32DisplacedInRegisterFile:
case CellDisplacedInRegisterFile:
case BooleanDisplacedInRegisterFile:
m_jit.load32(AssemblyHelpers::payloadFor(recovery.virtualRegister()), GPRInfo::regT0);
- m_jit.store32(GPRInfo::regT0, reinterpret_cast<char*>(scratchBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
+ m_jit.store32(GPRInfo::regT0, reinterpret_cast<char*>(scratchDataBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
break;
default:
break;
@@ -433,24 +435,24 @@
const ValueRecovery& recovery = exit.valueRecovery(index);
switch (recovery.technique()) {
case DisplacedInRegisterFile:
- m_jit.load32(reinterpret_cast<char*>(scratchBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
- m_jit.load32(reinterpret_cast<char*>(scratchBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag), GPRInfo::regT1);
+ m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+ m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag), GPRInfo::regT1);
m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
m_jit.store32(GPRInfo::regT1, AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
scratchIndex++;
break;
case Int32DisplacedInRegisterFile:
- m_jit.load32(reinterpret_cast<char*>(scratchBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+ m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::Int32Tag), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
break;
case CellDisplacedInRegisterFile:
- m_jit.load32(reinterpret_cast<char*>(scratchBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+ m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
break;
case BooleanDisplacedInRegisterFile:
- m_jit.load32(reinterpret_cast<char*>(scratchBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+ m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + scratchIndex++) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
m_jit.store32(AssemblyHelpers::TrustedImm32(JSValue::BooleanTag), AssemblyHelpers::tagFor((VirtualRegister)exit.operandForIndex(index)));
m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)exit.operandForIndex(index)));
break;
@@ -475,7 +477,7 @@
case InGPR:
case UnboxedInt32InGPR:
case UnboxedBooleanInGPR: {
- m_jit.load32(reinterpret_cast<char*>(scratchBuffer + poisonIndex(virtualRegister)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+ m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + poisonIndex(virtualRegister)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)virtualRegister));
uint32_t tag = JSValue::EmptyValueTag;
if (recovery.technique() == InGPR)
@@ -491,8 +493,8 @@
case InFPR:
case InPair:
case UInt32InGPR:
- m_jit.load32(reinterpret_cast<char*>(scratchBuffer + poisonIndex(virtualRegister)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
- m_jit.load32(reinterpret_cast<char*>(scratchBuffer + poisonIndex(virtualRegister)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag), GPRInfo::regT1);
+ m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + poisonIndex(virtualRegister)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload), GPRInfo::regT0);
+ m_jit.load32(reinterpret_cast<char*>(scratchDataBuffer + poisonIndex(virtualRegister)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag), GPRInfo::regT1);
m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor((VirtualRegister)virtualRegister));
m_jit.store32(GPRInfo::regT1, AssemblyHelpers::tagFor((VirtualRegister)virtualRegister));
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler64.cpp (117728 => 117729)
--- trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler64.cpp 2012-05-21 05:42:25 UTC (rev 117728)
+++ trunk/Source/_javascript_Core/dfg/DFGOSRExitCompiler64.cpp 2012-05-21 05:42:56 UTC (rev 117729)
@@ -210,7 +210,8 @@
dataLog(" ");
#endif
- EncodedJSValue* scratchBuffer = static_cast<EncodedJSValue*>(m_jit.globalData()->scratchBufferForSize(sizeof(EncodedJSValue) * std::max(haveUInt32s ? 2u : 0u, numberOfPoisonedVirtualRegisters + (numberOfDisplacedVirtualRegisters <= GPRInfo::numberOfRegisters ? 0 : numberOfDisplacedVirtualRegisters))));
+ ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(sizeof(EncodedJSValue) * std::max(haveUInt32s ? 2u : 0u, numberOfPoisonedVirtualRegisters + (numberOfDisplacedVirtualRegisters <= GPRInfo::numberOfRegisters ? 0 : numberOfDisplacedVirtualRegisters)));
+ EncodedJSValue* scratchDataBuffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
// From here on, the code assumes that it is profitable to maximize the distance
// between when something is computed and when it is stored.
@@ -245,8 +246,8 @@
if (addressGPR == recovery.gpr())
addressGPR = GPRInfo::regT1;
- m_jit.storePtr(addressGPR, scratchBuffer);
- m_jit.move(AssemblyHelpers::TrustedImmPtr(scratchBuffer + 1), addressGPR);
+ m_jit.storePtr(addressGPR, scratchDataBuffer);
+ m_jit.move(AssemblyHelpers::TrustedImmPtr(scratchDataBuffer + 1), addressGPR);
m_jit.storeDouble(FPRInfo::fpRegT0, addressGPR);
AssemblyHelpers::Jump positive = m_jit.branch32(AssemblyHelpers::GreaterThanOrEqual, recovery.gpr(), AssemblyHelpers::TrustedImm32(0));
@@ -264,7 +265,7 @@
done.link(&m_jit);
m_jit.loadDouble(addressGPR, FPRInfo::fpRegT0);
- m_jit.loadPtr(scratchBuffer, addressGPR);
+ m_jit.loadPtr(scratchDataBuffer, addressGPR);
break;
}
@@ -289,7 +290,7 @@
case UnboxedInt32InGPR:
case UInt32InGPR:
if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
- m_jit.storePtr(recovery.gpr(), scratchBuffer + currentPoisonIndex);
+ m_jit.storePtr(recovery.gpr(), scratchDataBuffer + currentPoisonIndex);
m_poisonScratchIndices[exit.variableForIndex(index)] = currentPoisonIndex;
currentPoisonIndex++;
} else
@@ -323,7 +324,7 @@
continue;
GPRReg gpr = GPRInfo::toRegister(FPRInfo::toIndex(recovery.fpr()));
if (exit.isVariable(index) && poisonedVirtualRegisters[exit.variableForIndex(index)]) {
- m_jit.storePtr(gpr, scratchBuffer + currentPoisonIndex);
+ m_jit.storePtr(gpr, scratchDataBuffer + currentPoisonIndex);
m_poisonScratchIndices[exit.variableForIndex(index)] = currentPoisonIndex;
currentPoisonIndex++;
} else
@@ -422,20 +423,20 @@
switch (recovery.technique()) {
case DisplacedInRegisterFile:
m_jit.loadPtr(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::regT0);
- m_jit.storePtr(GPRInfo::regT0, scratchBuffer + scratchIndex++);
+ m_jit.storePtr(GPRInfo::regT0, scratchDataBuffer + scratchIndex++);
break;
case Int32DisplacedInRegisterFile: {
m_jit.load32(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::regT0);
m_jit.orPtr(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
- m_jit.storePtr(GPRInfo::regT0, scratchBuffer + scratchIndex++);
+ m_jit.storePtr(GPRInfo::regT0, scratchDataBuffer + scratchIndex++);
break;
}
case DoubleDisplacedInRegisterFile: {
m_jit.loadPtr(AssemblyHelpers::addressFor(recovery.virtualRegister()), GPRInfo::regT0);
m_jit.subPtr(GPRInfo::tagTypeNumberRegister, GPRInfo::regT0);
- m_jit.storePtr(GPRInfo::regT0, scratchBuffer + scratchIndex++);
+ m_jit.storePtr(GPRInfo::regT0, scratchDataBuffer + scratchIndex++);
break;
}
@@ -451,7 +452,7 @@
case DisplacedInRegisterFile:
case Int32DisplacedInRegisterFile:
case DoubleDisplacedInRegisterFile:
- m_jit.loadPtr(scratchBuffer + scratchIndex++, GPRInfo::regT0);
+ m_jit.loadPtr(scratchDataBuffer + scratchIndex++, GPRInfo::regT0);
m_jit.storePtr(GPRInfo::regT0, AssemblyHelpers::addressFor((VirtualRegister)exit.operandForIndex(index)));
break;
@@ -477,7 +478,7 @@
case UnboxedInt32InGPR:
case UInt32InGPR:
case InFPR:
- m_jit.loadPtr(scratchBuffer + poisonIndex(virtualRegister), GPRInfo::regT0);
+ m_jit.loadPtr(scratchDataBuffer + poisonIndex(virtualRegister), GPRInfo::regT0);
m_jit.storePtr(GPRInfo::regT0, AssemblyHelpers::addressFor((VirtualRegister)virtualRegister));
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (117728 => 117729)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2012-05-21 05:42:25 UTC (rev 117728)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2012-05-21 05:42:56 UTC (rev 117729)
@@ -979,20 +979,20 @@
return JSValue::encode(JSValue::decode(value).toPrimitive(exec));
}
-EncodedJSValue DFG_OPERATION operationStrCat(ExecState* exec, void* start, size_t size)
+EncodedJSValue DFG_OPERATION operationStrCat(ExecState* exec, void* scratch, size_t size)
{
JSGlobalData* globalData = &exec->globalData();
NativeCallFrameTracer tracer(globalData, exec);
-
- return JSValue::encode(jsString(exec, static_cast<Register*>(start), size));
+
+ return JSValue::encode(jsString(exec, static_cast<Register*>(static_cast<ScratchBuffer*>(scratch)->dataBuffer()), size));
}
-EncodedJSValue DFG_OPERATION operationNewArray(ExecState* exec, void* start, size_t size)
+EncodedJSValue DFG_OPERATION operationNewArray(ExecState* exec, void* scratch, size_t size)
{
JSGlobalData* globalData = &exec->globalData();
NativeCallFrameTracer tracer(globalData, exec);
-
- return JSValue::encode(constructArray(exec, static_cast<JSValue*>(start), size));
+
+ return JSValue::encode(constructArray(exec, static_cast<JSValue*>(static_cast<ScratchBuffer*>(scratch)->dataBuffer()), size));
}
EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState* exec, size_t start, size_t size)
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (117728 => 117729)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2012-05-21 05:42:25 UTC (rev 117728)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2012-05-21 05:42:56 UTC (rev 117729)
@@ -114,8 +114,8 @@
EncodedJSValue DFG_OPERATION operationResolveBaseStrictPut(ExecState*, Identifier*);
EncodedJSValue DFG_OPERATION operationResolveGlobal(ExecState*, GlobalResolveInfo*, Identifier*);
EncodedJSValue DFG_OPERATION operationToPrimitive(ExecState*, EncodedJSValue);
-EncodedJSValue DFG_OPERATION operationStrCat(ExecState*, void* start, size_t);
-EncodedJSValue DFG_OPERATION operationNewArray(ExecState*, void* start, size_t);
+EncodedJSValue DFG_OPERATION operationStrCat(ExecState*, void*, size_t);
+EncodedJSValue DFG_OPERATION operationNewArray(ExecState*, void*, size_t);
EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState*, size_t, size_t);
EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState*, void*);
void DFG_OPERATION operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (117728 => 117729)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2012-05-21 05:42:25 UTC (rev 117728)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2012-05-21 05:42:56 UTC (rev 117729)
@@ -2954,9 +2954,11 @@
// probably has the best balance of performance and sensibility in the sense
// that it does not increase the complexity of the DFG JIT just to make StrCat
// fast and pretty.
+
+ size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
+ ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
+ EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
- EncodedJSValue* buffer = static_cast<EncodedJSValue*>(m_jit.globalData()->scratchBufferForSize(sizeof(EncodedJSValue) * node.numChildren()));
-
for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
GPRReg opTagGPR = operand.tagGPR();
@@ -2968,12 +2970,27 @@
}
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->activeLengthPtr()), scratch.gpr());
+ m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
+ }
+
GPRResult resultPayload(this);
GPRResult2 resultTag(this);
- callOperation(op == StrCat ? operationStrCat : operationNewArray, resultTag.gpr(), resultPayload.gpr(), buffer, node.numChildren());
+ callOperation(op == StrCat ? operationStrCat : operationNewArray, resultTag.gpr(), resultPayload.gpr(), static_cast<void *>(scratchBuffer), node.numChildren());
+ if (scratchSize) {
+ GPRTemporary scratch(this);
+
+ m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
+ m_jit.storePtr(TrustedImmPtr(0), scratch.gpr());
+ }
+
// FIXME: make the callOperation above explicitly return a cell result, or jitAssert the tag is a cell tag.
cellResult(resultPayload.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (117728 => 117729)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2012-05-21 05:42:25 UTC (rev 117728)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2012-05-21 05:42:56 UTC (rev 117729)
@@ -2954,9 +2954,11 @@
// probably has the best balance of performance and sensibility in the sense
// that it does not increase the complexity of the DFG JIT just to make StrCat
// fast and pretty.
+
+ size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
+ ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
+ EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
- EncodedJSValue* buffer = static_cast<EncodedJSValue*>(m_jit.globalData()->scratchBufferForSize(sizeof(EncodedJSValue) * node.numChildren()));
-
for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
GPRReg opGPR = operand.gpr();
@@ -2966,11 +2968,26 @@
}
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->activeLengthPtr()), scratch.gpr());
+ m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
+ }
+
GPRResult result(this);
- callOperation(op == StrCat ? operationStrCat : operationNewArray, result.gpr(), buffer, node.numChildren());
-
+ callOperation(op == StrCat ? operationStrCat : operationNewArray, result.gpr(), static_cast<void *>(scratchBuffer), node.numChildren());
+
+ if (scratchSize) {
+ GPRTemporary scratch(this);
+
+ m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
+ m_jit.storePtr(TrustedImmPtr(0), scratch.gpr());
+ }
+
cellResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGThunks.cpp (117728 => 117729)
--- trunk/Source/_javascript_Core/dfg/DFGThunks.cpp 2012-05-21 05:42:25 UTC (rev 117728)
+++ trunk/Source/_javascript_Core/dfg/DFGThunks.cpp 2012-05-21 05:42:56 UTC (rev 117729)
@@ -39,7 +39,9 @@
{
MacroAssembler jit;
- EncodedJSValue* buffer = static_cast<EncodedJSValue*>(globalData->scratchBufferForSize(sizeof(EncodedJSValue) * (GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters)));
+ size_t scratchSize = sizeof(EncodedJSValue) * (GPRInfo::numberOfRegisters + FPRInfo::numberOfRegisters);
+ ScratchBuffer* scratchBuffer = globalData->scratchBufferForSize(scratchSize);
+ EncodedJSValue* buffer = static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer());
for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i)
jit.storePtr(GPRInfo::toRegister(i), buffer + i);
@@ -54,9 +56,16 @@
#else
jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
#endif
-
+
+ // Tell GC mark phase how much of the scratch buffer is active during call.
+ jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->activeLengthPtr()), GPRInfo::regT0);
+ jit.storePtr(MacroAssembler::TrustedImmPtr(scratchSize), GPRInfo::regT0);
+
MacroAssembler::Call functionCall = jit.call();
-
+
+ jit.move(MacroAssembler::TrustedImmPtr(scratchBuffer->activeLengthPtr()), GPRInfo::regT0);
+ jit.storePtr(MacroAssembler::TrustedImmPtr(0), GPRInfo::regT0);
+
for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
jit.move(MacroAssembler::TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
jit.loadDouble(GPRInfo::regT0, FPRInfo::toRegister(i));
Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (117728 => 117729)
--- trunk/Source/_javascript_Core/heap/Heap.cpp 2012-05-21 05:42:25 UTC (rev 117728)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp 2012-05-21 05:42:56 UTC (rev 117729)
@@ -451,6 +451,15 @@
GCPHASE(GatherRegisterFileRoots);
registerFile().gatherConservativeRoots(registerFileRoots, m_dfgCodeBlocks);
}
+
+#if ENABLE(DFG_JIT)
+ ConservativeRoots scratchBufferRoots(&m_objectSpace.blocks(), &m_storageSpace);
+ {
+ GCPHASE(GatherScratchBufferRoots);
+ m_globalData->gatherConservativeRoots(scratchBufferRoots);
+ }
+#endif
+
#if ENABLE(GGC)
MarkedBlock::DirtyCellVector dirtyCells;
if (!fullGC) {
@@ -497,7 +506,14 @@
visitor.append(registerFileRoots);
visitor.donateAndDrain();
}
+#if ENABLE(DFG_JIT)
{
+ GCPHASE(VisitScratchBufferRoots);
+ visitor.append(scratchBufferRoots);
+ visitor.donateAndDrain();
+ }
+#endif
+ {
GCPHASE(VisitProtectedObjects);
markProtectedObjects(heapRootVisitor);
visitor.donateAndDrain();
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp (117728 => 117729)
--- trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp 2012-05-21 05:42:25 UTC (rev 117728)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp 2012-05-21 05:42:56 UTC (rev 117729)
@@ -57,6 +57,10 @@
#include <wtf/Threading.h>
#include <wtf/WTFThreadData.h>
+#if ENABLE(DFG_JIT)
+#include "ConservativeRoots.h"
+#endif
+
#if ENABLE(REGEXP_TRACING)
#include "RegExp.h"
#endif
@@ -450,6 +454,19 @@
globalData.releaseExecutableMemory();
}
+#if ENABLE(DFG_JIT)
+void JSGlobalData::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
+{
+ for (size_t i = 0; i < scratchBuffers.size(); i++) {
+ ScratchBuffer* scratchBuffer = scratchBuffers[i];
+ if (scratchBuffer->activeLength()) {
+ void* bufferStart = scratchBuffer->dataBuffer();
+ conservativeRoots.add(bufferStart, static_cast<void*>(static_cast<char*>(bufferStart) + scratchBuffer->activeLength()));
+ }
+ }
+}
+#endif
+
#if ENABLE(REGEXP_TRACING)
void JSGlobalData::addRegExpToTrace(RegExp* regExp)
{
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalData.h (117728 => 117729)
--- trunk/Source/_javascript_Core/runtime/JSGlobalData.h 2012-05-21 05:42:25 UTC (rev 117728)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalData.h 2012-05-21 05:42:56 UTC (rev 117729)
@@ -123,7 +123,28 @@
size_t m_storageOffset;
size_t m_lengthOffset;
};
-
+
+#if ENABLE(DFG_JIT)
+ class ConservativeRoots;
+
+ struct ScratchBuffer {
+ ScratchBuffer()
+ : m_activeLength(0)
+ {
+ }
+
+ static size_t allocationSize(size_t bufferSize) { return sizeof(size_t) + bufferSize; }
+ void setActiveLength(size_t activeLength) { m_activeLength = activeLength; }
+ size_t activeLength() const { return m_activeLength; };
+ size_t* activeLengthPtr() { return &m_activeLength; };
+ void* dataBuffer() { return m_buffer; }
+ void visitEncodedJSValues(SlotVisitor&);
+
+ size_t m_activeLength;
+ void* m_buffer[0];
+ };
+#endif
+
class JSGlobalData : public RefCounted<JSGlobalData> {
public:
// WebCore has a one-to-one mapping of threads to JSGlobalDatas;
@@ -278,10 +299,10 @@
#if ENABLE(DFG_JIT)
uint32_t osrExitIndex;
void* osrExitJumpDestination;
- Vector<void*> scratchBuffers;
+ Vector<ScratchBuffer*> scratchBuffers;
size_t sizeOfLastScratchBuffer;
- void* scratchBufferForSize(size_t size)
+ ScratchBuffer* scratchBufferForSize(size_t size)
{
if (!size)
return 0;
@@ -292,12 +313,16 @@
// total memory usage is somewhere around
// max(scratch buffer size) * 4.
sizeOfLastScratchBuffer = size * 2;
-
- scratchBuffers.append(fastMalloc(sizeOfLastScratchBuffer));
+
+ scratchBuffers.append(static_cast<ScratchBuffer*>(fastMalloc(ScratchBuffer::allocationSize(sizeOfLastScratchBuffer))));
}
-
- return scratchBuffers.last();
+
+ ScratchBuffer* result = scratchBuffers.last();
+ result->setActiveLength(0);
+ return result;
}
+
+ void gatherConservativeRoots(ConservativeRoots&);
#endif
HashMap<OpaqueJSClass*, OwnPtr<OpaqueJSClassContextData> > opaqueJSClassData;