Title: [90601] trunk/Source/_javascript_Core
Revision
90601
Author
[email protected]
Date
2011-07-07 16:48:39 -0700 (Thu, 07 Jul 2011)

Log Message

DFG JIT does not implement get_by_id prototype caching.
https://bugs.webkit.org/show_bug.cgi?id=64077

Patch by Filip Pizlo <[email protected]> on 2011-07-07
Reviewed by Gavin Barraclough.

* dfg/DFGRepatch.cpp:
(JSC::DFG::emitRestoreScratch):
(JSC::DFG::linkRestoreScratch):
(JSC::DFG::tryCacheGetByID):
* runtime/JSObject.h:
(JSC::JSObject::addressOfPropertyAtOffset):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (90600 => 90601)


--- trunk/Source/_javascript_Core/ChangeLog	2011-07-07 23:17:55 UTC (rev 90600)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-07-07 23:48:39 UTC (rev 90601)
@@ -1,5 +1,19 @@
 2011-07-07  Filip Pizlo  <[email protected]>
 
+        DFG JIT does not implement get_by_id prototype caching.
+        https://bugs.webkit.org/show_bug.cgi?id=64077
+
+        Reviewed by Gavin Barraclough.
+
+        * dfg/DFGRepatch.cpp:
+        (JSC::DFG::emitRestoreScratch):
+        (JSC::DFG::linkRestoreScratch):
+        (JSC::DFG::tryCacheGetByID):
+        * runtime/JSObject.h:
+        (JSC::JSObject::addressOfPropertyAtOffset):
+
+2011-07-07  Filip Pizlo  <[email protected]>
+
         DFG JIT method_check implementation does not link to optimized get_by_id
         slow path.
         https://bugs.webkit.org/show_bug.cgi?id=64073

Modified: trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp (90600 => 90601)


--- trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2011-07-07 23:17:55 UTC (rev 90600)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2011-07-07 23:48:39 UTC (rev 90601)
@@ -56,6 +56,44 @@
         repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.u.unset.deltaCallToLoadOrStore), sizeof(JSValue) * offset);
 }
 
+static void emitRestoreScratch(MacroAssembler& stubJit, bool needToRestoreScratch, GPRReg scratchGPR, MacroAssembler::Jump& success, MacroAssembler::Jump& fail, MacroAssembler::Jump failureCase1, MacroAssembler::Jump failureCase2)
+{
+    if (needToRestoreScratch) {
+        stubJit.pop(scratchGPR);
+        
+        success = stubJit.jump();
+        
+        // link failure cases here, so we can pop scratchGPR, and then jump back.
+        failureCase1.link(&stubJit);
+        failureCase2.link(&stubJit);
+        
+        stubJit.pop(scratchGPR);
+        
+        fail = stubJit.jump();
+        return;
+    }
+    
+    success = stubJit.jump();
+}
+
+static void linkRestoreScratch(LinkBuffer& patchBuffer, bool needToRestoreScratch, StructureStubInfo& stubInfo, MacroAssembler::Jump& success, MacroAssembler::Jump& fail, MacroAssembler::Jump failureCase1, MacroAssembler::Jump failureCase2)
+{
+    CodeLocationLabel slowCaseBegin = stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase);
+    
+    patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone));
+        
+    patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone));
+    
+    if (needToRestoreScratch) {
+        patchBuffer.link(fail, slowCaseBegin);
+        return;
+    }
+    
+    // link failure cases directly back to normal path
+    patchBuffer.link(failureCase1, slowCaseBegin);
+    patchBuffer.link(failureCase2, slowCaseBegin);
+}
+            
 static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
 {
     // FIXME: Write a test that proves we need to check for recursion here just
@@ -88,35 +126,12 @@
 
         MacroAssembler::Jump success, fail;
         
-        if (needToRestoreScratch) {
-            stubJit.pop(scratchGPR);
-            
-            success = stubJit.jump();
-            
-            // link failure cases here, so we can pop scratchGPR, and then jump back.
-            failureCase1.link(&stubJit);
-            failureCase2.link(&stubJit);
-            
-            stubJit.pop(scratchGPR);
-            
-            fail = stubJit.jump();
-        } else
-            success = stubJit.jump();
+        emitRestoreScratch(stubJit, needToRestoreScratch, scratchGPR, success, fail, failureCase1, failureCase2);
         
         LinkBuffer patchBuffer(*globalData, &stubJit, codeBlock->executablePool());
         
-        CodeLocationLabel slowCaseBegin = stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase);
+        linkRestoreScratch(patchBuffer, needToRestoreScratch, stubInfo, success, fail, failureCase1, failureCase2);
         
-        patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone));
-        
-        if (needToRestoreScratch)
-            patchBuffer.link(fail, slowCaseBegin);
-        else {
-            // link failure cases directly back to normal path
-            patchBuffer.link(failureCase1, slowCaseBegin);
-            patchBuffer.link(failureCase2, slowCaseBegin);
-        }
-        
         CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
         stubInfo.stubRoutine = entryLabel;
         
@@ -150,7 +165,73 @@
         return true;
     }
     
-    // FIXME: should support prototype & chain accesses!
+    if (structure->isDictionary())
+        return false;
+    
+    // Optimize accesses on the direct prototype
+    if (slot.slotBase() == structure->prototypeForLookup(exec)) {
+        if (slot.cachedPropertyType() != PropertySlot::Value)
+            return false;
+        
+        ASSERT(slot.slotBase().isObject());
+        
+        JSObject* slotBaseObject = asObject(slot.slotBase());
+        size_t offset = slot.cachedOffset();
+        
+        if (slotBaseObject->structure()->isDictionary()) {
+            slotBaseObject->flattenDictionaryObject(*globalData);
+            offset = slotBaseObject->structure()->get(*globalData, propertyName);
+        }
+        
+        ASSERT(!structure->isDictionary());
+        ASSERT(!slotBaseObject->structure()->isDictionary());
+        
+        ASSERT(asObject(structure->prototypeForLookup(exec)) == slotBaseObject);
+        
+        GPRReg baseGPR = static_cast<GPRReg>(stubInfo.baseGPR);
+        GPRReg resultGPR = static_cast<GPRReg>(stubInfo.valueGPR);
+        GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.u.unset.scratchGPR);
+        bool needToRestoreScratch = false;
+        
+        MacroAssembler stubJit;
+        
+        if (scratchGPR == InvalidGPRReg) {
+            scratchGPR = JITCodeGenerator::selectScratchGPR(baseGPR, resultGPR);
+            stubJit.push(scratchGPR);
+            needToRestoreScratch = true;
+        }
+        
+        MacroAssembler::Jump failureCase1 = stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(structure));
+        
+        stubJit.move(MacroAssembler::TrustedImmPtr(slotBaseObject), scratchGPR);
+        MacroAssembler::Jump failureCase2 = stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(scratchGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(slotBaseObject->structure()));
+        
+        if (slotBaseObject->structure()->isUsingInlineStorage())
+            stubJit.loadPtr(MacroAssembler::Address(scratchGPR, JSObject::offsetOfInlineStorage() + offset * sizeof(JSValue)), resultGPR);
+        else
+            stubJit.loadPtr(slotBaseObject->addressOfPropertyAtOffset(offset), resultGPR);
+        
+        MacroAssembler::Jump success, fail;
+        
+        emitRestoreScratch(stubJit, needToRestoreScratch, scratchGPR, success, fail, failureCase1, failureCase2);
+        
+        LinkBuffer patchBuffer(*globalData, &stubJit, codeBlock->executablePool());
+        
+        linkRestoreScratch(patchBuffer, needToRestoreScratch, stubInfo, success, fail, failureCase1, failureCase2);
+        
+        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, operationGetById);
+        
+        stubInfo.initGetByIdProto(*globalData, codeBlock->ownerExecutable(), structure, slotBaseObject->structure());
+        return true;
+    }
+    
+    // FIXME: should support chain accesses!
     return false;
 }
 

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (90600 => 90601)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2011-07-07 23:17:55 UTC (rev 90600)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2011-07-07 23:48:39 UTC (rev 90601)
@@ -219,6 +219,11 @@
 
         void allocatePropertyStorage(size_t oldSize, size_t newSize);
         bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage) == static_cast<const void*>(this + 1); }
+        
+        void* addressOfPropertyAtOffset(size_t offset)
+        {
+            return static_cast<void*>(&m_propertyStorage[offset]);
+        }
 
         static const unsigned baseExternalStorageCapacity = 16;
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to