Title: [117729] trunk/Source/_javascript_Core
Revision
117729
Author
[email protected]
Date
2012-05-20 22:42:56 -0700 (Sun, 20 May 2012)

Log Message

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):

Modified Paths

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;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to