2011-06-29 Filip Pizlo <fpizlo@apple.com>
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 Jun 2011 19:46:28 +0000 (19:46 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 Jun 2011 19:46:28 +0000 (19:46 +0000)
        Reviewed by Gavin Barraclough.

        DFG JIT does not perform get_by_id self list caching.
        https://bugs.webkit.org/show_bug.cgi?id=63605

        * bytecode/StructureStubInfo.h:
        * dfg/DFGJITCompiler.cpp:
        (JSC::DFG::JITCompiler::compileFunction):
        * dfg/DFGOperations.cpp:
        * dfg/DFGOperations.h:
        * dfg/DFGRepatch.cpp:
        (JSC::DFG::tryCacheGetByID):
        (JSC::DFG::tryBuildGetByIDList):
        (JSC::DFG::dfgBuildGetByIDList):
        * dfg/DFGRepatch.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@90035 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/StructureStubInfo.h
Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/dfg/DFGOperations.h
Source/JavaScriptCore/dfg/DFGRepatch.cpp
Source/JavaScriptCore/dfg/DFGRepatch.h

index 23c7b7c..12059b1 100644 (file)
@@ -1,3 +1,21 @@
+2011-06-29  Filip Pizlo  <fpizlo@apple.com>
+
+        Reviewed by Gavin Barraclough.
+
+        DFG JIT does not perform get_by_id self list caching.
+        https://bugs.webkit.org/show_bug.cgi?id=63605
+
+        * bytecode/StructureStubInfo.h:
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::compileFunction):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGRepatch.cpp:
+        (JSC::DFG::tryCacheGetByID):
+        (JSC::DFG::tryBuildGetByIDList):
+        (JSC::DFG::dfgBuildGetByIDList):
+        * dfg/DFGRepatch.h:
+
 2011-06-28  Filip Pizlo  <fpizlo@apple.com>
 
         Reviewed by Gavin Barraclough.
index 6597776..924648a 100644 (file)
@@ -127,18 +127,21 @@ namespace JSC {
             seen = true;
         }
 
-        signed accessType : 31;
-        unsigned seen : 1;
+        int8_t accessType;
+        int8_t seen;
+        
+#if ENABLE(DFG_JIT)
+        int8_t baseGPR;
+        int8_t valueGPR;
+        int8_t deltaCallToDone;
+        int8_t deltaCallToStructCheck;
+        int8_t deltaCallToSlowCase;
+#endif
 
         union {
             struct {
                 int8_t deltaCheckImmToCall;
-                int8_t deltaCallToStructCheck;
                 int8_t deltaCallToLoadOrStore;
-                int8_t deltaCallToSlowCase;
-                int8_t deltaCallToDone;
-                int8_t baseGPR;
-                int8_t valueGPR;
                 int8_t scratchGPR;
             } unset;
             struct {
index 1351c5e..c5863a8 100644 (file)
@@ -388,12 +388,12 @@ void JITCompiler::compileFunction(JITCode& entry, MacroAssemblerCodePtr& entryWi
         StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
         info.callReturnLocation = linkBuffer.locationOf(m_propertyAccesses[i].m_functionCall);
         info.u.unset.deltaCheckImmToCall = m_propertyAccesses[i].m_deltaCheckImmToCall;
-        info.u.unset.deltaCallToStructCheck = m_propertyAccesses[i].m_deltaCallToStructCheck;
+        info.deltaCallToStructCheck = m_propertyAccesses[i].m_deltaCallToStructCheck;
         info.u.unset.deltaCallToLoadOrStore = m_propertyAccesses[i].m_deltaCallToLoadOrStore;
-        info.u.unset.deltaCallToSlowCase = m_propertyAccesses[i].m_deltaCallToSlowCase;
-        info.u.unset.deltaCallToDone = m_propertyAccesses[i].m_deltaCallToDone;
-        info.u.unset.baseGPR = m_propertyAccesses[i].m_baseGPR;
-        info.u.unset.valueGPR = m_propertyAccesses[i].m_valueGPR;
+        info.deltaCallToSlowCase = m_propertyAccesses[i].m_deltaCallToSlowCase;
+        info.deltaCallToDone = m_propertyAccesses[i].m_deltaCallToDone;
+        info.baseGPR = m_propertyAccesses[i].m_baseGPR;
+        info.valueGPR = m_propertyAccesses[i].m_valueGPR;
         info.u.unset.scratchGPR = m_propertyAccesses[i].m_scratchGPR;
     }
 
index c86b90d..050c382 100644 (file)
@@ -244,6 +244,20 @@ EncodedJSValue operationGetByIdOptimizeWithReturnAddress(ExecState* exec, Encode
     return JSValue::encode(result);
 }
 
+EncodedJSValue operationGetByIdBuildListWithReturnAddress(ExecState*, EncodedJSValue, Identifier*, ReturnAddressPtr);
+FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(operationGetByIdBuildList);
+EncodedJSValue operationGetByIdBuildListWithReturnAddress(ExecState* exec, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
+{
+    JSValue baseValue = JSValue::decode(encodedBase);
+    PropertySlot slot(baseValue);
+    JSValue result = baseValue.get(exec, *propertyName, slot);
+
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    dfgBuildGetByIDList(exec, baseValue, *propertyName, slot, stubInfo);
+
+    return JSValue::encode(result);
+}
+
 void operationPutByValStrict(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue)
 {
     operationPutByValInternal<true>(exec, encodedBase, encodedProperty, encodedValue);
index b62500a..c29c8b7 100644 (file)
@@ -59,6 +59,7 @@ EncodedJSValue operationArithDiv(EncodedJSValue encodedOp1, EncodedJSValue encod
 EncodedJSValue operationArithMod(EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
 EncodedJSValue operationGetByVal(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty);
 EncodedJSValue operationGetById(ExecState*, EncodedJSValue encodedBase, Identifier*);
+EncodedJSValue operationGetByIdBuildList(ExecState*, EncodedJSValue encodedBase, Identifier*);
 EncodedJSValue operationGetByIdOptimize(ExecState*, EncodedJSValue encodedBase, Identifier*);
 void operationPutByValStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
 void operationPutByValNonStrict(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedProperty, EncodedJSValue encodedValue);
index b10f10e..d60bbc1 100644 (file)
@@ -64,8 +64,8 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
     JSGlobalData* globalData = &exec->globalData();
     
     if (isJSArray(globalData, baseValue) && propertyName == exec->propertyNames().length) {
-        GPRReg baseGPR = static_cast<GPRReg>(stubInfo.u.unset.baseGPR);
-        GPRReg resultGPR = static_cast<GPRReg>(stubInfo.u.unset.valueGPR);
+        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;
         
@@ -104,9 +104,9 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
         
         LinkBuffer patchBuffer(*globalData, &stubJit, codeBlock->executablePool());
         
-        CodeLocationLabel slowCaseBegin = stubInfo.callReturnLocation.labelAtOffset(stubInfo.u.unset.deltaCallToSlowCase);
+        CodeLocationLabel slowCaseBegin = stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase);
         
-        patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.u.unset.deltaCallToDone));
+        patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone));
         
         if (needToRestoreScratch)
             patchBuffer.link(fail, slowCaseBegin);
@@ -121,7 +121,7 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
         
         CodeLocationLabel hotPathBegin = stubInfo.hotPathBegin;
         RepatchBuffer repatchBuffer(codeBlock);
-        repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.u.unset.deltaCallToStructCheck), entryLabel);
+        repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck), entryLabel);
         repatchBuffer.relink(stubInfo.callReturnLocation, operationGetById);
         
         return true;
@@ -144,11 +144,11 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier
         if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset))
             return false;
 
-        dfgRepatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), operationGetById, true);
+        dfgRepatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), operationGetByIdBuildList, true);
         stubInfo.initGetByIdSelf(*globalData, codeBlock->ownerExecutable(), structure);
         return true;
     }
-
+    
     // FIXME: should support prototype & chain accesses!
     return false;
 }
@@ -160,6 +160,84 @@ void dfgRepatchGetByID(ExecState* exec, JSValue baseValue, const Identifier& pro
         dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, operationGetById);
 }
 
+static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identifier&, const PropertySlot& slot, StructureStubInfo& stubInfo)
+{
+    if (!baseValue.isCell()
+        || !slot.isCacheable()
+        || baseValue.asCell()->structure()->isUncacheableDictionary()
+        || slot.slotBase() != baseValue
+        || slot.cachedPropertyType() != PropertySlot::Value
+        || (slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset)
+        return false;
+    
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSCell* baseCell = baseValue.asCell();
+    Structure* structure = baseCell->structure();
+    JSGlobalData* globalData = &exec->globalData();
+    
+    ASSERT(slot.slotBase().isObject());
+    
+    PolymorphicAccessStructureList* polymorphicStructureList;
+    int listIndex = 1;
+    
+    if (stubInfo.accessType == access_get_by_id_self) {
+        ASSERT(!stubInfo.stubRoutine);
+        polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase), stubInfo.u.getByIdSelf.baseObjectStructure.get());
+        stubInfo.initGetByIdSelfList(polymorphicStructureList, 1);
+    } else {
+        polymorphicStructureList = stubInfo.u.getByIdSelfList.structureList;
+        listIndex = stubInfo.u.getByIdSelfList.listSize;
+    }
+    
+    if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) {
+        stubInfo.u.getByIdSelfList.listSize++;
+        
+        GPRReg baseGPR = static_cast<GPRReg>(stubInfo.baseGPR);
+        GPRReg resultGPR = static_cast<GPRReg>(stubInfo.valueGPR);
+        
+        MacroAssembler stubJit;
+        
+        MacroAssembler::Jump wrongStruct = stubJit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(structure));
+        
+        if (structure->isUsingInlineStorage())
+            stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + slot.cachedOffset() * sizeof(JSValue)), resultGPR);
+        else {
+            stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
+            stubJit.loadPtr(MacroAssembler::Address(resultGPR, slot.cachedOffset() * sizeof(JSValue)), resultGPR);
+        }
+        
+        MacroAssembler::Jump success = stubJit.jump();
+        
+        LinkBuffer patchBuffer(*globalData, &stubJit, codeBlock->executablePool());
+        
+        CodeLocationLabel lastProtoBegin = polymorphicStructureList->list[listIndex - 1].stubRoutine;
+        ASSERT(!!lastProtoBegin);
+        
+        patchBuffer.link(wrongStruct, lastProtoBegin);
+        patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone));
+        
+        CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
+        
+        polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), entryLabel, structure);
+        
+        CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck);
+        RepatchBuffer repatchBuffer(codeBlock);
+        repatchBuffer.relink(jumpLocation, entryLabel);
+        
+        if (listIndex < (POLYMORPHIC_LIST_CACHE_SIZE - 1))
+            return true;
+    }
+    
+    return false;
+}
+
+void dfgBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo& stubInfo)
+{
+    bool dontChangeCall = tryBuildGetByIDList(exec, baseValue, propertyName, slot, stubInfo);
+    if (!dontChangeCall)
+        dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, operationGetById);
+}
+
 static V_DFGOperation_EJJI appropriatePutByIdFunction(const PutPropertySlot &slot, PutKind putKind)
 {
     if (slot.isStrictMode()) {
index ab4949c..9703522 100644 (file)
@@ -34,6 +34,7 @@
 namespace JSC { namespace DFG {
 
 void dfgRepatchGetByID(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
+void dfgBuildGetByIDList(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
 void dfgRepatchPutByID(ExecState*, JSValue, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
 
 } } // namespace JSC::DFG