Title: [89861] trunk/Source/_javascript_Core
Revision
89861
Author
[email protected]
Date
2011-06-27 14:38:09 -0700 (Mon, 27 Jun 2011)

Log Message

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

        Reviewed by Gavin Barraclough.

        DFG JIT does not perform put_by_id caching.
        https://bugs.webkit.org/show_bug.cgi?id=63409

        * bytecode/StructureStubInfo.h:
        * dfg/DFGJITCodeGenerator.cpp:
        (JSC::DFG::JITCodeGenerator::cachedPutById):
        * dfg/DFGJITCodeGenerator.h:
        * dfg/DFGJITCompiler.cpp:
        (JSC::DFG::JITCompiler::compileFunction):
        * dfg/DFGJITCompiler.h:
        (JSC::DFG::JITCompiler::addPropertyAccess):
        (JSC::DFG::JITCompiler::PropertyAccessRecord::PropertyAccessRecord):
        * dfg/DFGNonSpeculativeJIT.cpp:
        (JSC::DFG::NonSpeculativeJIT::compile):
        * dfg/DFGOperations.cpp:
        * dfg/DFGOperations.h:
        * dfg/DFGRepatch.cpp:
        (JSC::DFG::dfgRepatchByIdSelfAccess):
        (JSC::DFG::tryCacheGetByID):
        (JSC::DFG::appropriatePutByIdFunction):
        (JSC::DFG::tryCachePutByID):
        (JSC::DFG::dfgRepatchPutByID):
        * dfg/DFGRepatch.h:
        * dfg/DFGSpeculativeJIT.cpp:
        (JSC::DFG::SpeculativeJIT::compile):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (89860 => 89861)


--- trunk/Source/_javascript_Core/ChangeLog	2011-06-27 21:24:55 UTC (rev 89860)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-06-27 21:38:09 UTC (rev 89861)
@@ -1,3 +1,33 @@
+2011-06-27  Filip Pizlo  <[email protected]>
+
+        Reviewed by Gavin Barraclough.
+
+        DFG JIT does not perform put_by_id caching.
+        https://bugs.webkit.org/show_bug.cgi?id=63409
+
+        * bytecode/StructureStubInfo.h:
+        * dfg/DFGJITCodeGenerator.cpp:
+        (JSC::DFG::JITCodeGenerator::cachedPutById):
+        * dfg/DFGJITCodeGenerator.h:
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::compileFunction):
+        * dfg/DFGJITCompiler.h:
+        (JSC::DFG::JITCompiler::addPropertyAccess):
+        (JSC::DFG::JITCompiler::PropertyAccessRecord::PropertyAccessRecord):
+        * dfg/DFGNonSpeculativeJIT.cpp:
+        (JSC::DFG::NonSpeculativeJIT::compile):
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGRepatch.cpp:
+        (JSC::DFG::dfgRepatchByIdSelfAccess):
+        (JSC::DFG::tryCacheGetByID):
+        (JSC::DFG::appropriatePutByIdFunction):
+        (JSC::DFG::tryCachePutByID):
+        (JSC::DFG::dfgRepatchPutByID):
+        * dfg/DFGRepatch.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+
 2011-06-27  Gustavo Noronha Silva  <[email protected]>
 
         Unreviewed build fix. One more filed missing during distcheck, for

Modified: trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h (89860 => 89861)


--- trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h	2011-06-27 21:24:55 UTC (rev 89860)
+++ trunk/Source/_javascript_Core/bytecode/StructureStubInfo.h	2011-06-27 21:38:09 UTC (rev 89861)
@@ -133,7 +133,7 @@
         union {
             struct {
                 intptr_t deltaCheckToCall;
-                intptr_t deltaCallToLoad;
+                intptr_t deltaCallToLoadOrStore;
             } unset;
             struct {
                 WriteBarrierBase<Structure> baseObjectStructure;

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp (89860 => 89861)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-06-27 21:24:55 UTC (rev 89860)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-06-27 21:38:09 UTC (rev 89861)
@@ -350,6 +350,47 @@
     m_jit.addPropertyAccess(functionCall, checkToCall, callToLoad);
 }
 
+void JITCodeGenerator::cachedPutById(GPRReg baseGPR, GPRReg valueGPR, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
+{
+    JITCompiler::DataLabelPtr structureToCompare;
+    JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::Equal, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
+    
+    if (slowPathTarget.isSet())
+        slowPathTarget.link(&m_jit);
+
+    silentSpillAllRegisters(InvalidGPRReg, baseGPR, valueGPR);
+    setupTwoStubArgs<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2>(valueGPR, baseGPR);
+    m_jit.move(JITCompiler::ImmPtr(identifier(identifierNumber)), GPRInfo::argumentGPR3);
+    m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    V_DFGOperation_EJJI optimizedCall;
+    if (m_jit.codeBlock()->isStrictMode()) {
+        if (putKind == Direct)
+            optimizedCall = operationPutByIdDirectStrictOptimize;
+        else
+            optimizedCall = operationPutByIdStrictOptimize;
+    } else {
+        if (putKind == Direct)
+            optimizedCall = operationPutByIdDirectNonStrictOptimize;
+        else
+            optimizedCall = operationPutByIdNonStrictOptimize;
+    }
+    JITCompiler::Call functionCall = appendCallWithExceptionCheck(optimizedCall);
+    silentFillAllRegisters(InvalidGPRReg);
+
+    JITCompiler::Jump handledByC = m_jit.jump();
+    structureCheck.link(&m_jit);
+
+    m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), scratchGPR);
+    JITCompiler::DataLabel32 storeWithPatch = m_jit.storePtrWithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));
+
+    intptr_t checkToCall = m_jit.differenceBetween(structureToCompare, functionCall);
+    intptr_t callToStore = m_jit.differenceBetween(functionCall, storeWithPatch);
+
+    handledByC.link(&m_jit);
+
+    m_jit.addPropertyAccess(functionCall, checkToCall, callToStore);
+}
+
 #ifndef NDEBUG
 static const char* dataFormatString(DataFormat format)
 {

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h (89860 => 89861)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-06-27 21:24:55 UTC (rev 89860)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-06-27 21:38:09 UTC (rev 89861)
@@ -501,6 +501,7 @@
     }
 
     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());
 
     // Called once a node has completed code generation but prior to setting
     // its result, to free up its children. (This must happen prior to setting

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (89860 => 89861)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2011-06-27 21:24:55 UTC (rev 89860)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2011-06-27 21:38:09 UTC (rev 89861)
@@ -388,7 +388,7 @@
         StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
         info.callReturnLocation = linkBuffer.locationOf(m_propertyAccesses[i].m_functionCall);
         info.u.unset.deltaCheckToCall = m_propertyAccesses[i].m_deltaCheckToCall;
-        info.u.unset.deltaCallToLoad = m_propertyAccesses[i].m_deltaCallToLoad;
+        info.u.unset.deltaCallToLoadOrStore = m_propertyAccesses[i].m_deltaCallToLoadOrStore;
     }
 
     // FIXME: switch the register file check & arity check over to DFGOpertaion style calls, not JIT stubs.

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h (89860 => 89861)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h	2011-06-27 21:24:55 UTC (rev 89860)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.h	2011-06-27 21:38:09 UTC (rev 89861)
@@ -232,9 +232,9 @@
     void clearSamplingFlag(int32_t flag);
 #endif
 
-    void addPropertyAccess(JITCompiler::Call functionCall, intptr_t deltaCheckToCall, intptr_t deltaCallToLoad)
+    void addPropertyAccess(JITCompiler::Call functionCall, intptr_t deltaCheckToCall, intptr_t deltaCallToLoadOrStore)
     {
-        m_propertyAccesses.append(PropertyAccessRecord(functionCall, deltaCheckToCall, deltaCallToLoad));
+        m_propertyAccesses.append(PropertyAccessRecord(functionCall, deltaCheckToCall, deltaCallToLoadOrStore));
     }
 
 private:
@@ -258,16 +258,16 @@
     Vector<CallRecord> m_calls;
 
     struct PropertyAccessRecord {
-        PropertyAccessRecord(JITCompiler::Call functionCall, intptr_t deltaCheckToCall, intptr_t deltaCallToLoad)
+        PropertyAccessRecord(JITCompiler::Call functionCall, intptr_t deltaCheckToCall, intptr_t deltaCallToLoadOrStore)
             : m_functionCall(functionCall)
             , m_deltaCheckToCall(deltaCheckToCall)
-            , m_deltaCallToLoad(deltaCallToLoad)
+            , m_deltaCallToLoadOrStore(deltaCallToLoadOrStore)
         {
         }
 
         JITCompiler::Call m_functionCall;
         intptr_t m_deltaCheckToCall;
-        intptr_t m_deltaCallToLoad;
+        intptr_t m_deltaCallToLoadOrStore;
     };
 
     Vector<PropertyAccessRecord, 4> m_propertyAccesses;

Modified: trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp (89860 => 89861)


--- trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp	2011-06-27 21:24:55 UTC (rev 89860)
+++ trunk/Source/_javascript_Core/dfg/DFGNonSpeculativeJIT.cpp	2011-06-27 21:38:09 UTC (rev 89861)
@@ -770,11 +770,14 @@
     case PutById: {
         JSValueOperand base(this, node.child1);
         JSValueOperand value(this, node.child2);
+        GPRTemporary scratch(this, base);
         GPRReg valueGPR = value.gpr();
         GPRReg baseGPR = base.gpr();
-        flushRegisters();
+        
+        JITCompiler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, baseGPR, GPRInfo::tagMaskRegister);
 
-        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdStrict : operationPutByIdNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
+        cachedPutById(baseGPR, valueGPR, scratch.gpr(), node.identifierNumber(), NotDirect, notCell);
+
         noResult(m_compileIndex);
         break;
     }
@@ -782,11 +785,14 @@
     case PutByIdDirect: {
         JSValueOperand base(this, node.child1);
         JSValueOperand value(this, node.child2);
+        GPRTemporary scratch(this, base);
         GPRReg valueGPR = value.gpr();
         GPRReg baseGPR = base.gpr();
-        flushRegisters();
+        
+        JITCompiler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, baseGPR, GPRInfo::tagMaskRegister);
 
-        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdDirectStrict : operationPutByIdDirectNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
+        cachedPutById(baseGPR, valueGPR, scratch.gpr(), node.identifierNumber(), Direct, notCell);
+
         noResult(m_compileIndex);
         break;
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (89860 => 89861)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-06-27 21:24:55 UTC (rev 89860)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2011-06-27 21:38:09 UTC (rev 89861)
@@ -43,6 +43,7 @@
         "jmp _" STRINGIZE(function) "WithReturnAddress" "\n" \
     );
 #define FUNCTION_WRAPPER_WITH_ARG4_RETURN_ADDRESS(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, rcx)
+#define FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(function) FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, r8)
 
 namespace JSC { namespace DFG {
 
@@ -284,6 +285,74 @@
     JSValue::decode(encodedBase).putDirect(exec, *propertyName, JSValue::decode(encodedValue), slot);
 }
 
+void operationPutByIdStrictOptimizeWithReturnAddress(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr);
+FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(operationPutByIdStrictOptimize);
+void operationPutByIdStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
+{
+    JSValue value = JSValue::decode(encodedValue);
+    JSValue base = JSValue::decode(encodedBase);
+    PutPropertySlot slot(true);
+    
+    base.put(exec, *propertyName, value, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    if (stubInfo.seen)
+        dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, NotDirect);
+    else
+        stubInfo.seen = true;
+}
+
+void operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr);
+FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(operationPutByIdNonStrictOptimize);
+void operationPutByIdNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
+{
+    JSValue value = JSValue::decode(encodedValue);
+    JSValue base = JSValue::decode(encodedBase);
+    PutPropertySlot slot(false);
+    
+    base.put(exec, *propertyName, value, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    if (stubInfo.seen)
+        dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, NotDirect);
+    else
+        stubInfo.seen = true;
+}
+
+void operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr);
+FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(operationPutByIdDirectStrictOptimize);
+void operationPutByIdDirectStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
+{
+    JSValue value = JSValue::decode(encodedValue);
+    JSValue base = JSValue::decode(encodedBase);
+    PutPropertySlot slot(true);
+    
+    base.putDirect(exec, *propertyName, value, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    if (stubInfo.seen)
+        dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct);
+    else
+        stubInfo.seen = true;
+}
+
+void operationPutByIdDirectNonStrictOptimizeWithReturnAddress(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr);
+FUNCTION_WRAPPER_WITH_ARG5_RETURN_ADDRESS(operationPutByIdDirectNonStrictOptimize);
+void operationPutByIdDirectNonStrictOptimizeWithReturnAddress(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier* propertyName, ReturnAddressPtr returnAddress)
+{
+    JSValue value = JSValue::decode(encodedValue);
+    JSValue base = JSValue::decode(encodedBase);
+    PutPropertySlot slot(false);
+    
+    base.putDirect(exec, *propertyName, value, slot);
+    
+    StructureStubInfo& stubInfo = exec->codeBlock()->getStubInfo(returnAddress);
+    if (stubInfo.seen)
+        dfgRepatchPutByID(exec, base, *propertyName, slot, stubInfo, Direct);
+    else
+        stubInfo.seen = true;
+}
+
 bool operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
     return jsLess(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (89860 => 89861)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.h	2011-06-27 21:24:55 UTC (rev 89860)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h	2011-06-27 21:38:09 UTC (rev 89861)
@@ -31,6 +31,9 @@
 #include <dfg/DFGJITCompiler.h>
 
 namespace JSC { namespace DFG {
+
+enum PutKind { Direct, NotDirect };
+
 extern "C" {
 
 // These typedefs provide typechecking when generating calls out to helper routines;
@@ -64,6 +67,10 @@
 void operationPutByIdNonStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
 void operationPutByIdDirectStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
 void operationPutByIdDirectNonStrict(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
+void operationPutByIdStrictOptimize(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
+void operationPutByIdNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
+void operationPutByIdDirectStrictOptimize(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
+void operationPutByIdDirectNonStrictOptimize(ExecState*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, Identifier*);
 bool operationCompareLess(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
 bool operationCompareLessEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);
 bool operationCompareEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2);

Modified: trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp (89860 => 89861)


--- trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2011-06-27 21:24:55 UTC (rev 89860)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2011-06-27 21:38:09 UTC (rev 89861)
@@ -28,7 +28,6 @@
 
 #if ENABLE(DFG_JIT)
 
-#include "DFGOperations.h"
 #include "RepatchBuffer.h"
 
 namespace JSC { namespace DFG {
@@ -39,16 +38,19 @@
     repatchBuffer.relink(call, newCalleeFunction);
 }
 
-static void dfgRepatchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo& stubInfo, Structure* structure, size_t offset)
+static void dfgRepatchByIdSelfAccess(CodeBlock* codeBlock, StructureStubInfo& stubInfo, Structure* structure, size_t offset, const FunctionPtr &slowPathFunction, bool compact)
 {
     RepatchBuffer repatchBuffer(codeBlock);
 
     // Only optimize once!
-    repatchBuffer.relink(stubInfo.callReturnLocation, operationGetById);
+    repatchBuffer.relink(stubInfo.callReturnLocation, slowPathFunction);
 
     // Patch the structure check & the offset of the load.
     repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(intptr_t)stubInfo.u.unset.deltaCheckToCall), structure);
-    repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.u.unset.deltaCallToLoad), sizeof(JSValue) * offset);
+    if (compact)
+        repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.u.unset.deltaCallToLoadOrStore), sizeof(JSValue) * offset);
+    else
+        repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.u.unset.deltaCallToLoadOrStore), sizeof(JSValue) * offset);
 }
 
 static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier&, const PropertySlot& slot, StructureStubInfo& stubInfo)
@@ -76,7 +78,7 @@
         if ((slot.cachedPropertyType() != PropertySlot::Value) || ((slot.cachedOffset() * sizeof(JSValue)) > (unsigned)MacroAssembler::MaximumCompactPtrAlignedAddressOffset))
             return false;
 
-        dfgRepatchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset());
+        dfgRepatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), operationGetById, true);
         stubInfo.initGetByIdSelf(*globalData, codeBlock->ownerExecutable(), structure);
         return true;
     }
@@ -92,6 +94,53 @@
         dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, operationGetById);
 }
 
+static V_DFGOperation_EJJI appropriatePutByIdFunction(const PutPropertySlot &slot, PutKind putKind)
+{
+    if (slot.isStrictMode()) {
+        if (putKind == Direct)
+            return operationPutByIdDirectStrict;
+        return operationPutByIdStrict;
+    }
+    if (putKind == Direct)
+        return operationPutByIdDirectNonStrict;
+    return operationPutByIdNonStrict;
+}
+
+static bool tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier&, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
+{
+    CodeBlock* codeBlock = exec->codeBlock();
+    JSGlobalData* globalData = &exec->globalData();
+
+    if (!baseValue.isCell())
+        return false;
+    JSCell* baseCell = baseValue.asCell();
+    Structure* structure = baseCell->structure();
+    if (!slot.isCacheable())
+        return false;
+    if (structure->isUncacheableDictionary())
+        return false;
+
+    // Optimize self access.
+    if (slot.base() == baseValue) {
+        if (slot.type() == PutPropertySlot::NewProperty)
+            return false;
+
+        dfgRepatchByIdSelfAccess(codeBlock, stubInfo, structure, slot.cachedOffset(), appropriatePutByIdFunction(slot, putKind), false);
+        stubInfo.initPutByIdReplace(*globalData, codeBlock->ownerExecutable(), structure);
+        return true;
+    }
+
+    // FIXME: should support the transition case!
+    return false;
+}
+
+void dfgRepatchPutByID(ExecState* exec, JSValue baseValue, const Identifier& propertyName, const PutPropertySlot& slot, StructureStubInfo& stubInfo, PutKind putKind)
+{
+    bool cached = tryCachePutByID(exec, baseValue, propertyName, slot, stubInfo, putKind);
+    if (!cached)
+        dfgRepatchCall(exec->codeBlock(), stubInfo.callReturnLocation, appropriatePutByIdFunction(slot, putKind));
+}
+
 } } // namespace JSC::DFG
 
 #endif

Modified: trunk/Source/_javascript_Core/dfg/DFGRepatch.h (89860 => 89861)


--- trunk/Source/_javascript_Core/dfg/DFGRepatch.h	2011-06-27 21:24:55 UTC (rev 89860)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.h	2011-06-27 21:38:09 UTC (rev 89861)
@@ -29,10 +29,12 @@
 #if ENABLE(DFG_JIT)
 
 #include <dfg/DFGJITCompiler.h>
+#include <dfg/DFGOperations.h>
 
 namespace JSC { namespace DFG {
 
 void dfgRepatchGetByID(ExecState*, JSValue, const Identifier&, const PropertySlot&, StructureStubInfo&);
+void dfgRepatchPutByID(ExecState*, JSValue, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
 
 } } // namespace JSC::DFG
 

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (89860 => 89861)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-06-27 21:24:55 UTC (rev 89860)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2011-06-27 21:38:09 UTC (rev 89861)
@@ -863,25 +863,23 @@
     }
 
     case PutById: {
-        JSValueOperand base(this, node.child1);
+        SpeculateCellOperand base(this, node.child1);
         JSValueOperand value(this, node.child2);
-        GPRReg valueGPR = value.gpr();
-        GPRReg baseGPR = base.gpr();
-        flushRegisters();
+        GPRTemporary scratch(this, base);
 
-        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdStrict : operationPutByIdNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
+        cachedPutById(base.gpr(), value.gpr(), scratch.gpr(), node.identifierNumber(), NotDirect);
+        
         noResult(m_compileIndex);
         break;
     }
 
     case PutByIdDirect: {
-        JSValueOperand base(this, node.child1);
+        SpeculateCellOperand base(this, node.child1);
         JSValueOperand value(this, node.child2);
-        GPRReg valueGPR = value.gpr();
-        GPRReg baseGPR = base.gpr();
-        flushRegisters();
+        GPRTemporary scratch(this, base);
 
-        callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByIdDirectStrict : operationPutByIdDirectNonStrict, valueGPR, baseGPR, identifier(node.identifierNumber()));
+        cachedPutById(base.gpr(), value.gpr(), scratch.gpr(), node.identifierNumber(), Direct);
+
         noResult(m_compileIndex);
         break;
     }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to