Title: [90063] trunk/Source/_javascript_Core
Revision
90063
Author
[email protected]
Date
2011-06-29 16:45:28 -0700 (Wed, 29 Jun 2011)

Log Message

2011-06-29  Filip Pizlo  <[email protected]>

        Reviewed by Gavin Barraclough.

        DFG JIT does not do put_by_id transition caching.
        https://bugs.webkit.org/show_bug.cgi?id=63662

        * dfg/DFGJITCodeGenerator.cpp:
        (JSC::DFG::JITCodeGenerator::cachedPutById):
        * dfg/DFGJITCompiler.h:
        (JSC::DFG::JITCompiler::addPropertyAccess):
        * dfg/DFGRepatch.cpp:
        (JSC::DFG::testPrototype):
        (JSC::DFG::tryCachePutByID):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (90062 => 90063)


--- trunk/Source/_javascript_Core/ChangeLog	2011-06-29 23:42:03 UTC (rev 90062)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-06-29 23:45:28 UTC (rev 90063)
@@ -1,3 +1,18 @@
+2011-06-29  Filip Pizlo  <[email protected]>
+
+        Reviewed by Gavin Barraclough.
+
+        DFG JIT does not do put_by_id transition caching.
+        https://bugs.webkit.org/show_bug.cgi?id=63662
+
+        * dfg/DFGJITCodeGenerator.cpp:
+        (JSC::DFG::JITCodeGenerator::cachedPutById):
+        * dfg/DFGJITCompiler.h:
+        (JSC::DFG::JITCompiler::addPropertyAccess):
+        * dfg/DFGRepatch.cpp:
+        (JSC::DFG::testPrototype):
+        (JSC::DFG::tryCachePutByID):
+
 2011-06-29  Geoffrey Garen  <[email protected]>
 
         Reviewed by Oliver Hunt.

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp (90062 => 90063)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-06-29 23:42:03 UTC (rev 90062)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-06-29 23:45:28 UTC (rev 90063)
@@ -370,12 +370,26 @@
 
 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::Equal, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
+    JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
     
+    m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
+    JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));
+
+    JITCompiler::Jump done = m_jit.jump();
+
+    structureCheck.link(&m_jit);
+
     if (slowPathTarget.isSet())
         slowPathTarget.link(&m_jit);
 
+    JITCompiler::Label slowCase = m_jit.label();
+
     silentSpillAllRegisters(InvalidGPRReg, baseGPR, valueGPR);
     setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(valueGPR, baseGPR);
     m_jit.move(JITCompiler::ImmPtr(identifier(identifierNumber)), GPRInfo::argumentGPR3);
@@ -395,19 +409,19 @@
     JITCompiler::Call functionCall = appendCallWithExceptionCheck(optimizedCall);
     silentFillAllRegisters(InvalidGPRReg);
 
-    JITCompiler::Jump handledByC = m_jit.jump();
-    structureCheck.link(&m_jit);
+    done.link(&m_jit);
+    JITCompiler::Label doneLabel = m_jit.label();
 
-    m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
-    JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));
-
     int8_t checkImmToCall = static_cast<int8_t>(m_jit.differenceBetween(structureToCompare, functionCall));
     int8_t callToCheck = static_cast<int8_t>(m_jit.differenceBetween(functionCall, structureCheck));
     int8_t callToStore = static_cast<int8_t>(m_jit.differenceBetween(functionCall, storeWithPatch));
+    int8_t callToSlowCase = static_cast<int8_t>(m_jit.differenceBetween(functionCall, slowCase));
+    int8_t callToDone = static_cast<int8_t>(m_jit.differenceBetween(functionCall, doneLabel));
 
-    handledByC.link(&m_jit);
+    m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToStore, callToSlowCase, callToDone, static_cast<int8_t>(baseGPR), static_cast<int8_t>(valueGPR), static_cast<int8_t>(slowPathScratch));
 
-    m_jit.addPropertyAccess(functionCall, checkImmToCall, callToCheck, callToStore);
+    if (scratchGPR == baseGPR && slowPathScratch != InvalidGPRReg)
+        unlock(slowPathScratch);
 }
 
 #ifndef NDEBUG

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h (90062 => 90063)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h	2011-06-29 23:42:03 UTC (rev 90062)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h	2011-06-29 23:45:28 UTC (rev 90063)
@@ -233,7 +233,7 @@
     void clearSamplingFlag(int32_t flag);
 #endif
 
-    void addPropertyAccess(JITCompiler::Call functionCall, int16_t deltaCheckImmToCall, int16_t deltaCallToStructCheck, int16_t deltaCallToLoadOrStore, int16_t deltaCallToSlowCase = 0, int16_t deltaCallToDone = 0, int8_t baseGPR = 0, int8_t valueGPR = 0, int8_t scratchGPR = 0)
+    void addPropertyAccess(JITCompiler::Call functionCall, int16_t deltaCheckImmToCall, int16_t deltaCallToStructCheck, int16_t deltaCallToLoadOrStore, int16_t deltaCallToSlowCase, int16_t deltaCallToDone, int8_t baseGPR, int8_t valueGPR, int8_t scratchGPR)
     {
         m_propertyAccesses.append(PropertyAccessRecord(functionCall, deltaCheckImmToCall, deltaCallToStructCheck, deltaCallToLoadOrStore, deltaCallToSlowCase, deltaCallToDone,  baseGPR, valueGPR, scratchGPR));
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp (90062 => 90063)


--- trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2011-06-29 23:42:03 UTC (rev 90062)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2011-06-29 23:45:28 UTC (rev 90063)
@@ -30,6 +30,7 @@
 
 #include "DFGJITCodeGenerator.h"
 #include "LinkBuffer.h"
+#include "Operations.h"
 #include "RepatchBuffer.h"
 
 namespace JSC { namespace DFG {
@@ -250,6 +251,17 @@
     return operationPutByIdNonStrict;
 }
 
+static void testPrototype(MacroAssembler &stubJit, GPRReg scratchGPR, JSValue prototype, MacroAssembler::JumpList& failureCases)
+{
+    if (prototype.isNull())
+        return;
+    
+    ASSERT(prototype.isCell());
+    
+    stubJit.move(MacroAssembler::TrustedImmPtr(prototype.asCell()), scratchGPR);
+    failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(scratchGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(prototype.asCell()->structure())));
+}
+
 static bool tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier&, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
 {
     CodeBlock* codeBlock = exec->codeBlock();
@@ -259,6 +271,8 @@
         return false;
     JSCell* baseCell = baseValue.asCell();
     Structure* structure = baseCell->structure();
+    Structure* oldStructure = structure->previousID();
+    
     if (!slot.isCacheable())
         return false;
     if (structure->isUncacheableDictionary())
@@ -266,9 +280,83 @@
 
     // Optimize self access.
     if (slot.base() == baseValue) {
-        if (slot.type() == PutPropertySlot::NewProperty)
-            return false;
+        if (slot.type() == PutPropertySlot::NewProperty) {
+            if (structure->isDictionary())
+                return false;
+            
+            // skip optimizing the case where we need a realloc
+            if (oldStructure->propertyStorageCapacity() != structure->propertyStorageCapacity())
+                return false;
+            
+            normalizePrototypeChain(exec, baseCell);
+            
+            StructureChain* prototypeChain = structure->prototypeChain(exec);
+            
+            GPRReg baseGPR = static_cast<GPRReg>(stubInfo.baseGPR);
+            GPRReg valueGPR = static_cast<GPRReg>(stubInfo.valueGPR);
+            GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.u.unset.scratchGPR);
+            bool needToRestoreScratch = false;
+            
+            ASSERT(scratchGPR != baseGPR);
+            
+            MacroAssembler stubJit;
+            
+            MacroAssembler::JumpList failureCases;
+            
+            if (scratchGPR == InvalidGPRReg) {
+                scratchGPR = JITCodeGenerator::selectScratchGPR(baseGPR, valueGPR);
+                stubJit.push(scratchGPR);
+                needToRestoreScratch = true;
+            }
+            
+            failureCases.append(stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(oldStructure)));
+            
+            testPrototype(stubJit, scratchGPR, oldStructure->storedPrototype(), failureCases);
+            
+            if (putKind == NotDirect) {
+                for (WriteBarrier<Structure>* it = prototypeChain->head(); *it; ++it)
+                    testPrototype(stubJit, scratchGPR, (*it)->storedPrototype(), failureCases);
+            }
+            
+            stubJit.storePtr(MacroAssembler::TrustedImmPtr(structure), MacroAssembler::Address(baseGPR, JSCell::structureOffset()));
+            if (structure->isUsingInlineStorage())
+                stubJit.storePtr(valueGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + slot.cachedOffset() * sizeof(JSValue)));
+            else {
+                stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
+                stubJit.storePtr(valueGPR, MacroAssembler::Address(scratchGPR, slot.cachedOffset() * sizeof(JSValue)));
+            }
+            
+            MacroAssembler::Jump success;
+            MacroAssembler::Jump failure;
+            
+            if (needToRestoreScratch) {
+                stubJit.pop(scratchGPR);
+                success = stubJit.jump();
 
+                failureCases.link(&stubJit);
+                stubJit.pop(scratchGPR);
+                failure = stubJit.jump();
+            } else
+                success = stubJit.jump();
+            
+            LinkBuffer patchBuffer(*globalData, &stubJit, codeBlock->executablePool());
+            patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone));
+            if (needToRestoreScratch)
+                patchBuffer.link(failure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase));
+            else
+                patchBuffer.link(failureCases, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase));
+            
+            CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+            stubInfo.stubRoutine = entryLabel;
+            
+            CodeLocationLabel hotPathBegin = stubInfo.hotPathBegin;
+            RepatchBuffer repatchBuffer(codeBlock);
+            repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck), entryLabel);
+            repatchBuffer.relink(stubInfo.callReturnLocation, appropriatePutByIdFunction(slot, putKind));
+            
+            return true;
+        }
+
         dfgRepatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), appropriatePutByIdFunction(slot, putKind), false);
         stubInfo.initPutByIdReplace(*globalData, codeBlock->ownerExecutable(), structure);
         return true;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to