Title: [90187] trunk/Source/_javascript_Core
Revision
90187
Author
[email protected]
Date
2011-06-30 17:10:23 -0700 (Thu, 30 Jun 2011)

Log Message

2011-06-30  Geoffrey Garen  <[email protected]>

        Reviewed by Gavin Barraclough.

        Added empty write barrier stubs in all the right places in the DFG JIT
        https://bugs.webkit.org/show_bug.cgi?id=63764
        
        SunSpider thinks this might be a 0.5% speedup. Meh.

        * dfg/DFGJITCodeGenerator.cpp:
        (JSC::DFG::JITCodeGenerator::writeBarrier): Le stub.

        (JSC::DFG::JITCodeGenerator::cachedPutById): Don't do anything special
        for the case where base == scratch, since we now require base and scratch
        to be not equal, for the sake of the write barrier.

        * dfg/DFGJITCodeGenerator.h: Le stub.

        * dfg/DFGNonSpeculativeJIT.cpp:
        (JSC::DFG::NonSpeculativeJIT::compile): Don't reuse the base register
        as the scratch register, since that's incompatible with the write barrier,
        which needs a distinct base and scratch.
        
        Do put the global object into a register before loading its var storage,
        since it needs to be in a register for the write barrier to operate on it.

        * dfg/DFGSpeculativeJIT.cpp:
        (JSC::DFG::SpeculativeJIT::compile):
        * jit/JITPropertyAccess.cpp:
        (JSC::JIT::emitWriteBarrier): Second verse, same as the first.

        * jit/JITPropertyAccess.cpp:
        (JSC::JIT::emit_op_get_scoped_var):
        (JSC::JIT::emit_op_put_scoped_var):
        (JSC::JIT::emit_op_put_global_var): Deployed offsetOfRegisters() to more
        places.

        (JSC::JIT::emitWriteBarrier): Added a teeny tiny ASSERT so this function
        is a little more than meaningless.

        * jit/JITPropertyAccess32_64.cpp:
        (JSC::JIT::emit_op_get_scoped_var):
        (JSC::JIT::emit_op_put_scoped_var):
        (JSC::JIT::emit_op_put_global_var): Deployed offsetOfRegisters() to more
        places.

        (JSC::JIT::emitWriteBarrier): Added a teeny tiny ASSERT so this function
        is a little more than meaningless.

        * runtime/JSVariableObject.h:
        (JSC::JSVariableObject::offsetOfRegisters): Now used by the JIT, since
        we put the global object in a register and only then load its var storage
        by offset.

        (JSC::JIT::emitWriteBarrier):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (90186 => 90187)


--- trunk/Source/_javascript_Core/ChangeLog	2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-07-01 00:10:23 UTC (rev 90187)
@@ -1,3 +1,59 @@
+2011-06-30  Geoffrey Garen  <[email protected]>
+
+        Reviewed by Gavin Barraclough.
+
+        Added empty write barrier stubs in all the right places in the DFG JIT
+        https://bugs.webkit.org/show_bug.cgi?id=63764
+        
+        SunSpider thinks this might be a 0.5% speedup. Meh.
+
+        * dfg/DFGJITCodeGenerator.cpp:
+        (JSC::DFG::JITCodeGenerator::writeBarrier): Le stub.
+
+        (JSC::DFG::JITCodeGenerator::cachedPutById): Don't do anything special
+        for the case where base == scratch, since we now require base and scratch
+        to be not equal, for the sake of the write barrier.
+
+        * dfg/DFGJITCodeGenerator.h: Le stub.
+
+        * dfg/DFGNonSpeculativeJIT.cpp:
+        (JSC::DFG::NonSpeculativeJIT::compile): Don't reuse the base register
+        as the scratch register, since that's incompatible with the write barrier,
+        which needs a distinct base and scratch.
+        
+        Do put the global object into a register before loading its var storage,
+        since it needs to be in a register for the write barrier to operate on it.
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emitWriteBarrier): Second verse, same as the first.
+
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_get_scoped_var):
+        (JSC::JIT::emit_op_put_scoped_var):
+        (JSC::JIT::emit_op_put_global_var): Deployed offsetOfRegisters() to more
+        places.
+
+        (JSC::JIT::emitWriteBarrier): Added a teeny tiny ASSERT so this function
+        is a little more than meaningless.
+
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::emit_op_get_scoped_var):
+        (JSC::JIT::emit_op_put_scoped_var):
+        (JSC::JIT::emit_op_put_global_var): Deployed offsetOfRegisters() to more
+        places.
+
+        (JSC::JIT::emitWriteBarrier): Added a teeny tiny ASSERT so this function
+        is a little more than meaningless.
+
+        * runtime/JSVariableObject.h:
+        (JSC::JSVariableObject::offsetOfRegisters): Now used by the JIT, since
+        we put the global object in a register and only then load its var storage
+        by offset.
+
+        (JSC::JIT::emitWriteBarrier):
+
 2011-06-30  Oliver Hunt  <[email protected]>
 
         Fix ARMv6 build

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp (90186 => 90187)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-07-01 00:10:23 UTC (rev 90187)
@@ -368,16 +368,20 @@
         unlock(scratchGPR);
 }
 
+void JITCodeGenerator::writeBarrier(GPRReg owner, GPRReg scratch)
+{
+    UNUSED_PARAM(owner);
+    UNUSED_PARAM(scratch);
+    ASSERT(owner != scratch);
+}
+
 void JITCodeGenerator::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
 {
-    GPRReg slowPathScratch = scratchGPR;
-    
-    if (scratchGPR == baseGPR)
-        slowPathScratch = tryAllocate();
-    
     JITCompiler::DataLabelPtr structureToCompare;
     JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
     
+    writeBarrier(baseGPR, scratchGPR);
+
     m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
     JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));
 
@@ -418,10 +422,7 @@
     int8_t callToSlowCase = static_cast<int8_t>(m_jit.differenceBetween(functionCall, slowCase));
     int8_t callToDone = static_cast<int8_t>(m_jit.differenceBetween(functionCall, doneLabel));
 
-    m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToStore, callToSlowCase, callToDone, static_cast<int8_t>(baseGPR), static_cast<int8_t>(valueGPR), static_cast<int8_t>(slowPathScratch));
-
-    if (scratchGPR == baseGPR && slowPathScratch != InvalidGPRReg)
-        unlock(slowPathScratch);
+    m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToStore, callToSlowCase, callToDone, static_cast<int8_t>(baseGPR), static_cast<int8_t>(valueGPR), static_cast<int8_t>(scratchGPR));
 }
 
 #ifndef NDEBUG

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h (90186 => 90187)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-07-01 00:10:23 UTC (rev 90187)
@@ -517,6 +517,8 @@
             ASSERT_NOT_REACHED();
         }
     }
+    
+    void writeBarrier(GPRReg ownerGPR, GPRReg scratchGPR);
 
     void cachedGetById(GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
     void cachedPutById(GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());

Modified: trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp (90186 => 90187)


--- trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp	2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp	2011-07-01 00:10:23 UTC (rev 90187)
@@ -770,7 +770,7 @@
     case PutById: {
         JSValueOperand base(this, node.child1);
         JSValueOperand value(this, node.child2);
-        GPRTemporary scratch(this, base);
+        GPRTemporary scratch(this);
         GPRReg valueGPR = value.gpr();
         GPRReg baseGPR = base.gpr();
         
@@ -785,7 +785,7 @@
     case PutByIdDirect: {
         JSValueOperand base(this, node.child1);
         JSValueOperand value(this, node.child2);
-        GPRTemporary scratch(this, base);
+        GPRTemporary scratch(this);
         GPRReg valueGPR = value.gpr();
         GPRReg baseGPR = base.gpr();
         
@@ -810,12 +810,19 @@
 
     case PutGlobalVar: {
         JSValueOperand value(this, node.child1);
-        GPRTemporary temp(this);
+        GPRTemporary globalObject(this);
+        GPRTemporary scratch(this);
+        
+        GPRReg globalObjectReg = globalObject.gpr();
+        GPRReg scratchReg = scratch.gpr();
 
-        JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
-        m_jit.loadPtr(globalObject->addressOfRegisters(), temp.gpr());
-        m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(temp.gpr(), node.varNumber()));
+        m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), globalObjectReg);
 
+        writeBarrier(globalObjectReg, scratchReg);
+
+        m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
+        m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
+
         noResult(m_compileIndex);
         break;
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (90186 => 90187)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-07-01 00:10:23 UTC (rev 90187)
@@ -891,14 +891,16 @@
         SpeculateCellOperand base(this, node.child1);
         SpeculateStrictInt32Operand property(this, node.child2);
         JSValueOperand value(this, node.child3);
-        GPRTemporary storage(this);
+        GPRTemporary scratch(this);
 
-        // Map base, property & value into registers, allocate a register for storage.
+        // Map base, property & value into registers, allocate a scratch register.
         GPRReg baseReg = base.gpr();
         GPRReg propertyReg = property.gpr();
         GPRReg valueReg = value.gpr();
-        GPRReg storageReg = storage.gpr();
+        GPRReg scratchReg = scratch.gpr();
 
+        writeBarrier(baseReg, scratchReg);
+
         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
         // If we have predicted the base to be type array, we can skip the check.
         Node& baseNode = m_jit.graph()[node.child1];
@@ -907,16 +909,17 @@
         MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
 
         // Code to handle put beyond array bounds.
-        silentSpillAllRegisters(storageReg, baseReg, propertyReg, valueReg);
+        silentSpillAllRegisters(scratchReg, baseReg, propertyReg, valueReg);
         setupStubArguments(baseReg, propertyReg, valueReg);
         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
         JITCompiler::Call functionCall = appendCallWithExceptionCheck(operationPutByValBeyondArrayBounds);
-        silentFillAllRegisters(storageReg);
+        silentFillAllRegisters(scratchReg);
         JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump();
 
         withinArrayBounds.link(&m_jit);
 
         // Get the array storage.
+        GPRReg storageReg = scratchReg;
         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
 
         // Check if we're writing to a hole; if so increment m_numValuesInVector.
@@ -945,17 +948,20 @@
         SpeculateCellOperand base(this, node.child1);
         SpeculateStrictInt32Operand property(this, node.child2);
         JSValueOperand value(this, node.child3);
-        GPRTemporary storage(this, base); // storage may overwrite base.
+        GPRTemporary scratch(this);
+        
+        GPRReg baseReg = base.gpr();
+        GPRReg scratchReg = scratch.gpr();
 
+        writeBarrier(baseReg, scratchReg);
+
         // Get the array storage.
-        GPRReg storageReg = storage.gpr();
-        m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSArray::storageOffset()), storageReg);
+        GPRReg storageReg = scratchReg;
+        m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
 
-        // Map property & value into registers.
+        // Store the value to the array.
         GPRReg propertyReg = property.gpr();
         GPRReg valueReg = value.gpr();
-
-        // Store the value to the array.
         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
 
         noResult(m_compileIndex);
@@ -1048,7 +1054,7 @@
     case PutById: {
         SpeculateCellOperand base(this, node.child1);
         JSValueOperand value(this, node.child2);
-        GPRTemporary scratch(this, base);
+        GPRTemporary scratch(this);
 
         cachedPutById(base.gpr(), value.gpr(), scratch.gpr(), node.identifierNumber(), NotDirect);
         
@@ -1059,7 +1065,7 @@
     case PutByIdDirect: {
         SpeculateCellOperand base(this, node.child1);
         JSValueOperand value(this, node.child2);
-        GPRTemporary scratch(this, base);
+        GPRTemporary scratch(this);
 
         cachedPutById(base.gpr(), value.gpr(), scratch.gpr(), node.identifierNumber(), Direct);
 
@@ -1080,12 +1086,19 @@
 
     case PutGlobalVar: {
         JSValueOperand value(this, node.child1);
-        GPRTemporary temp(this);
+        GPRTemporary globalObject(this);
+        GPRTemporary scratch(this);
+        
+        GPRReg globalObjectReg = globalObject.gpr();
+        GPRReg scratchReg = scratch.gpr();
 
-        JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
-        m_jit.loadPtr(globalObject->addressOfRegisters(), temp.gpr());
-        m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(temp.gpr(), node.varNumber()));
+        m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), globalObjectReg);
 
+        writeBarrier(globalObjectReg, scratchReg);
+
+        m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
+        m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
+
         noResult(m_compileIndex);
         break;
     }

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (90186 => 90187)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp	2011-07-01 00:10:23 UTC (rev 90187)
@@ -965,7 +965,7 @@
         loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
 
     loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT0);
-    loadPtr(Address(regT0, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT0);
+    loadPtr(Address(regT0, JSVariableObject::offsetOfRegisters()), regT0);
     loadPtr(Address(regT0, currentInstruction[2].u.operand * sizeof(Register)), regT0);
     emitPutVirtualRegister(currentInstruction[1].u.operand);
 }
@@ -992,7 +992,7 @@
 
     emitWriteBarrier(regT1, regT2);
 
-    loadPtr(Address(regT1, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT1);
+    loadPtr(Address(regT1, JSVariableObject::offsetOfRegisters()), regT1);
     storePtr(regT0, Address(regT1, currentInstruction[1].u.operand * sizeof(Register)));
 }
 
@@ -1013,7 +1013,7 @@
     
     emitWriteBarrier(regT1, regT2);
 
-    loadPtr(Address(regT1, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT1);
+    loadPtr(Address(regT1, JSVariableObject::offsetOfRegisters()), regT1);
     storePtr(regT0, Address(regT1, currentInstruction[1].u.operand * sizeof(Register)));
 }
 
@@ -1021,6 +1021,7 @@
 {
     UNUSED_PARAM(owner);
     UNUSED_PARAM(scratch);
+    ASSERT(owner != scratch);
 }
 
 #endif // USE(JSVALUE64)

Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp (90186 => 90187)


--- trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp	2011-07-01 00:10:23 UTC (rev 90187)
@@ -1004,7 +1004,7 @@
         loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
 
     loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2);
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT2);
+    loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2);
 
     emitLoad(index, regT1, regT0, regT2);
     emitStore(dst, regT1, regT0);
@@ -1035,7 +1035,7 @@
 
     emitWriteBarrier(regT2, regT3);
 
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT2);
+    loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2);
     emitStore(index, regT1, regT0, regT2);
     map(m_bytecodeOffset + OPCODE_LENGTH(op_put_scoped_var), value, regT1, regT0);
 }
@@ -1066,7 +1066,7 @@
 
     emitWriteBarrier(regT2, regT3);
 
-    loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, m_registers)), regT2);
+    loadPtr(Address(regT2, JSVariableObject::offsetOfRegisters()), regT2);
     emitStore(index, regT1, regT0, regT2);
     map(m_bytecodeOffset + OPCODE_LENGTH(op_put_global_var), value, regT1, regT0);
 }
@@ -1075,6 +1075,7 @@
 {
     UNUSED_PARAM(owner);
     UNUSED_PARAM(scratch);
+    ASSERT(owner != scratch);
 }
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/JSVariableObject.h (90186 => 90187)


--- trunk/Source/_javascript_Core/runtime/JSVariableObject.h	2011-06-30 23:48:22 UTC (rev 90186)
+++ trunk/Source/_javascript_Core/runtime/JSVariableObject.h	2011-07-01 00:10:23 UTC (rev 90187)
@@ -57,6 +57,7 @@
         WriteBarrier<Unknown>& registerAt(int index) const { return m_registers[index]; }
 
         WriteBarrier<Unknown>* const * addressOfRegisters() const { return &m_registers; }
+        static size_t offsetOfRegisters() { return OBJECT_OFFSETOF(JSVariableObject, m_registers); }
 
         static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
         {
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to