Title: [96443] trunk/Source/_javascript_Core
Revision
96443
Author
fpi...@apple.com
Date
2011-09-30 17:58:15 -0700 (Fri, 30 Sep 2011)

Log Message

DFG does not speculate aggressively enough on put_by_id
https://bugs.webkit.org/show_bug.cgi?id=69114

Reviewed by Oliver Hunt.

This adds new nodes along with optimizations for those nodes:
        
GetPropertyStorage: CheckStructure used to do both the structure
check and retrieve the storage pointer. Now CheckStructure just
checks the structure, and GetPropertyStorage retrieves the
storage pointer.
        
PutStructure: Changes the structure, and has the expected store
to load optimization with CheckStructure.
        
PutByOffset: Directly sets the value. Has store to load
optimization with GetByOffset.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::cellConstant):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGJITCodeGenerator.cpp:
(JSC::DFG::JITCodeGenerator::writeBarrier):
* dfg/DFGJITCodeGenerator.h:
* dfg/DFGNode.h:
(JSC::DFG::Node::hasStructure):
(JSC::DFG::Node::hasStorageAccessData):
* dfg/DFGPropagator.cpp:
(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::impureCSE):
(JSC::DFG::Propagator::checkStructureLoadElimination):
(JSC::DFG::Propagator::getByOffsetLoadElimination):
(JSC::DFG::Propagator::getPropertyStorageLoadElimination):
(JSC::DFG::Propagator::eliminate):
(JSC::DFG::Propagator::performNodeCSE):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (96442 => 96443)


--- trunk/Source/_javascript_Core/ChangeLog	2011-10-01 00:46:50 UTC (rev 96442)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-10-01 00:58:15 UTC (rev 96443)
@@ -1,3 +1,47 @@
+2011-09-30  Filip Pizlo  <fpi...@apple.com>
+
+        DFG does not speculate aggressively enough on put_by_id
+        https://bugs.webkit.org/show_bug.cgi?id=69114
+
+        Reviewed by Oliver Hunt.
+
+        This adds new nodes along with optimizations for those nodes:
+        
+        GetPropertyStorage: CheckStructure used to do both the structure
+        check and retrieve the storage pointer. Now CheckStructure just
+        checks the structure, and GetPropertyStorage retrieves the
+        storage pointer.
+        
+        PutStructure: Changes the structure, and has the expected store
+        to load optimization with CheckStructure.
+        
+        PutByOffset: Directly sets the value. Has store to load
+        optimization with GetByOffset.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::cellConstant):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+        * dfg/DFGJITCodeGenerator.cpp:
+        (JSC::DFG::JITCodeGenerator::writeBarrier):
+        * dfg/DFGJITCodeGenerator.h:
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasStructure):
+        (JSC::DFG::Node::hasStorageAccessData):
+        * dfg/DFGPropagator.cpp:
+        (JSC::DFG::Propagator::propagateNodePredictions):
+        (JSC::DFG::Propagator::impureCSE):
+        (JSC::DFG::Propagator::checkStructureLoadElimination):
+        (JSC::DFG::Propagator::getByOffsetLoadElimination):
+        (JSC::DFG::Propagator::getPropertyStorageLoadElimination):
+        (JSC::DFG::Propagator::eliminate):
+        (JSC::DFG::Propagator::performNodeCSE):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+
 2011-09-30  Gavin Barraclough  <barraclo...@apple.com>
 
         StringRecursionChecker should not work in terms of EncodedJSValue

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (96442 => 96443)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2011-10-01 00:46:50 UTC (rev 96442)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2011-10-01 00:58:15 UTC (rev 96443)
@@ -30,6 +30,7 @@
 
 #include "DFGCapabilities.h"
 #include "CodeBlock.h"
+#include <wtf/HashMap.h>
 #include <wtf/MathExtras.h>
 
 namespace JSC { namespace DFG {
@@ -404,6 +405,19 @@
         return getJSConstant(m_constantNaN);
     }
     
+    NodeIndex cellConstant(JSCell* cell)
+    {
+        HashMap<JSCell*, unsigned>::iterator iter = m_cellConstants.find(cell);
+        if (iter != m_cellConstants.end())
+            return getJSConstant(iter->second);
+        
+        m_codeBlock->addConstant(cell);
+        m_constants.append(ConstantRecord());
+        ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
+        
+        return getJSConstant(m_codeBlock->numberOfConstantRegisters() - 1);
+    }
+    
     CodeOrigin currentCodeOrigin()
     {
         return CodeOrigin(m_currentIndex);
@@ -576,6 +590,7 @@
     unsigned m_constantNull;
     unsigned m_constantNaN;
     unsigned m_constant1;
+    HashMap<JSCell*, unsigned> m_cellConstants;
 
     // A constant in the constant pool may be represented by more than one
     // node in the graph, depending on the context in which it is being used.
@@ -1154,7 +1169,8 @@
                 size_t offset = structure->get(*m_globalData, identifier);
                 
                 if (offset != notFound) {
-                    getById = addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(CheckStructure, OpInfo(structure), base));
+                    addToGraph(CheckStructure, OpInfo(structure), base);
+                    getById = addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(GetPropertyStorage, base));
                     
                     StorageAccessData storageAccessData;
                     storageAccessData.offset = offset;
@@ -1174,13 +1190,84 @@
         case op_put_by_id: {
             NodeIndex value = get(currentInstruction[3].u.operand);
             NodeIndex base = get(currentInstruction[1].u.operand);
-            unsigned identifier = currentInstruction[2].u.operand;
+            unsigned identifierNumber = currentInstruction[2].u.operand;
             bool direct = currentInstruction[8].u.operand;
 
-            if (direct)
-                addToGraph(PutByIdDirect, OpInfo(identifier), base, value);
-            else
-                addToGraph(PutById, OpInfo(identifier), base, value);
+            StructureStubInfo& stubInfo = m_profiledBlock->getStubInfo(m_currentIndex);
+            if (!stubInfo.seen)
+                addToGraph(ForceOSRExit);
+            
+            bool alreadyGenerated = false;
+            
+            if (stubInfo.seen && !m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)) {
+                switch (stubInfo.accessType) {
+                case access_put_by_id_replace: {
+                    Structure* structure = stubInfo.u.putByIdReplace.baseObjectStructure.get();
+                    Identifier identifier = m_codeBlock->identifier(identifierNumber);
+                    size_t offset = structure->get(*m_globalData, identifier);
+                    
+                    if (offset != notFound) {
+                        addToGraph(CheckStructure, OpInfo(structure), base);
+                        addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
+                        
+                        StorageAccessData storageAccessData;
+                        storageAccessData.offset = offset;
+                        storageAccessData.identifierNumber = identifierNumber;
+                        m_graph.m_storageAccessData.append(storageAccessData);
+                        
+                        alreadyGenerated = true;
+                    }
+                    break;
+                }
+                    
+                case access_put_by_id_transition: {
+                    Structure* previousStructure = stubInfo.u.putByIdTransition.previousStructure.get();
+                    Structure* newStructure = stubInfo.u.putByIdTransition.structure.get();
+                    
+                    if (previousStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
+                        break;
+                    
+                    StructureChain* structureChain = stubInfo.u.putByIdTransition.chain.get();
+                    
+                    Identifier identifier = m_codeBlock->identifier(identifierNumber);
+                    size_t offset = newStructure->get(*m_globalData, identifier);
+                    
+                    if (offset != notFound) {
+                        addToGraph(CheckStructure, OpInfo(previousStructure), base);
+                        if (!direct) {
+                            for (WriteBarrier<Structure>* it = structureChain->head(); *it; ++it) {
+                                JSValue prototype = (*it)->storedPrototype();
+                                if (prototype.isNull())
+                                    continue;
+                                ASSERT(prototype.isCell());
+                                addToGraph(CheckStructure, OpInfo(prototype.asCell()->structure()), cellConstant(prototype.asCell()));
+                            }
+                        }
+                        addToGraph(PutStructure, OpInfo(newStructure), base);
+                        
+                        addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
+                        
+                        StorageAccessData storageAccessData;
+                        storageAccessData.offset = offset;
+                        storageAccessData.identifierNumber = identifierNumber;
+                        m_graph.m_storageAccessData.append(storageAccessData);
+                        
+                        alreadyGenerated = true;
+                    }
+                    break;
+                }
+                    
+                default:
+                    break;
+                }
+            }
+            
+            if (!alreadyGenerated) {
+                if (direct)
+                    addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
+                else
+                    addToGraph(PutById, OpInfo(identifierNumber), base, value);
+            }
 
             NEXT_OPCODE(op_put_by_id);
         }

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.cpp (96442 => 96443)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.cpp	2011-10-01 00:46:50 UTC (rev 96442)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.cpp	2011-10-01 00:58:15 UTC (rev 96443)
@@ -149,6 +149,20 @@
             printf("%sid%u", hasPrinted ? ", " : "", node.identifierNumber());
         hasPrinted = true;
     }
+    if (node.hasStructure()) {
+        printf("%sstruct(%p)", hasPrinted ? ", " : "", node.structure());
+        hasPrinted = true;
+    }
+    if (node.hasStorageAccessData()) {
+        StorageAccessData& storageAccessData = m_storageAccessData[node.storageAccessDataIndex()];
+        if (codeBlock)
+            printf("%sid%u{%s}", hasPrinted ? ", " : "", storageAccessData.identifierNumber, codeBlock->identifier(storageAccessData.identifierNumber).ustring().utf8().data());
+        else
+            printf("%sid%u", hasPrinted ? ", " : "", storageAccessData.identifierNumber);
+        
+        printf(", %lu", storageAccessData.offset);
+        hasPrinted = true;
+    }
     ASSERT(node.hasVariableAccessData() == node.hasLocal());
     if (node.hasVariableAccessData()) {
         VariableAccessData* variableAccessData = node.variableAccessData();

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp (96442 => 96443)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-10-01 00:46:50 UTC (rev 96442)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.cpp	2011-10-01 00:58:15 UTC (rev 96443)
@@ -267,6 +267,39 @@
 #endif
 }
 
+void JITCodeGenerator::writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
+{
+    UNUSED_PARAM(ownerGPR);
+    UNUSED_PARAM(value);
+    UNUSED_PARAM(scratch1);
+    UNUSED_PARAM(scratch2);
+    UNUSED_PARAM(useKind);
+    
+    if (Heap::isMarked(value))
+        return;
+
+#if ENABLE(WRITE_BARRIER_PROFILING)
+    JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));
+#endif
+
+#if ENABLE(GGC)
+    GPRTemporary temp1;
+    GPRTemporary temp2;
+    if (scratch1 == InvalidGPRReg) {
+        GPRTemporary scratchGPR(this);
+        temp1.adopt(scratchGPR);
+        scratch1 = temp1.gpr();
+    }
+    if (scratch2 == InvalidGPRReg) {
+        GPRTemporary scratchGPR(this);
+        temp2.adopt(scratchGPR);
+        scratch2 = temp2.gpr();
+    }
+
+    markCellCard(m_jit, ownerGPR, scratch1, scratch2);
+#endif
+}
+
 void JITCodeGenerator::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind useKind, GPRReg scratch)
 {
     UNUSED_PARAM(owner);

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h (96442 => 96443)


--- trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-10-01 00:46:50 UTC (rev 96442)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCodeGenerator.h	2011-10-01 00:58:15 UTC (rev 96443)
@@ -214,6 +214,7 @@
     static void writeBarrier(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, WriteBarrierUseKind);
 
     void writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg);
+    void writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg);
     void writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg);
 
     static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg)

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (96442 => 96443)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2011-10-01 00:46:50 UTC (rev 96442)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2011-10-01 00:58:15 UTC (rev 96443)
@@ -313,8 +313,11 @@
     macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
     macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
     macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
-    macro(CheckStructure, NodeResultStorage | NodeMustGenerate) \
+    macro(CheckStructure, NodeMustGenerate) \
+    macro(PutStructure, NodeMustGenerate | NodeClobbersWorld) \
+    macro(GetPropertyStorage, NodeResultStorage) \
     macro(GetByOffset, NodeResultJS) \
+    macro(PutByOffset, NodeMustGenerate | NodeClobbersWorld) \
     macro(GetArrayLength, NodeResultInt32) \
     macro(GetMethod, NodeResultJS | NodeMustGenerate) \
     macro(CheckMethod, NodeResultJS | NodeMustGenerate) \
@@ -782,7 +785,7 @@
     
     bool hasStructure()
     {
-        return op == CheckStructure;
+        return op == CheckStructure || op == PutStructure;
     }
     
     Structure* structure()
@@ -792,7 +795,7 @@
     
     bool hasStorageAccessData()
     {
-        return op == GetByOffset;
+        return op == GetByOffset || op == PutByOffset;
     }
     
     unsigned storageAccessDataIndex()

Modified: trunk/Source/_javascript_Core/dfg/DFGPropagator.cpp (96442 => 96443)


--- trunk/Source/_javascript_Core/dfg/DFGPropagator.cpp	2011-10-01 00:46:50 UTC (rev 96442)
+++ trunk/Source/_javascript_Core/dfg/DFGPropagator.cpp	2011-10-01 00:58:15 UTC (rev 96443)
@@ -448,7 +448,7 @@
             break;
         }
             
-        case CheckStructure: {
+        case GetPropertyStorage: {
             changed |= setPrediction(PredictOther);
             break;
         }
@@ -583,6 +583,9 @@
         case PutByValAlias:
         case PutById:
         case PutByIdDirect:
+        case CheckStructure:
+        case PutStructure:
+        case PutByOffset:
             break;
             
         // This gets ignored because it doesn't do anything.
@@ -888,6 +891,39 @@
         }
     }
     
+    NodeIndex impureCSE(Node& node)
+    {
+        NodeIndex child1 = canonicalize(node.child1());
+        NodeIndex child2 = canonicalize(node.child2());
+        NodeIndex child3 = canonicalize(node.child3());
+        
+        NodeIndex start = startIndex();
+        for (NodeIndex index = m_compileIndex; index-- > start;) {
+            Node& otherNode = m_graph[index];
+            if (node.op == otherNode.op
+                && node.arithNodeFlagsForCompare() == otherNode.arithNodeFlagsForCompare()) {
+                NodeIndex otherChild = canonicalize(otherNode.child1());
+                if (otherChild == NoNode)
+                    return index;
+                if (otherChild == child1) {
+                    otherChild = canonicalize(otherNode.child2());
+                    if (otherChild == NoNode)
+                        return index;
+                    if (otherChild == child2) {
+                        otherChild = canonicalize(otherNode.child3());
+                        if (otherChild == NoNode)
+                            return index;
+                        if (otherChild == child3)
+                            return index;
+                    }
+                }
+            }
+            if (clobbersWorld(index))
+                break;
+        }
+        return NoNode;
+    }
+    
     NodeIndex globalVarLoadElimination(unsigned varNumber)
     {
         NodeIndex start = startIndexForChildren();
@@ -950,19 +986,35 @@
         return NoNode;
     }
     
-    NodeIndex checkStructureLoadElimination(Structure* structure, NodeIndex child1)
+    bool checkStructureLoadElimination(Structure* structure, NodeIndex child1)
     {
         NodeIndex start = startIndexForChildren(child1);
         for (NodeIndex index = m_compileIndex; index-- > start;) {
             Node& node = m_graph[index];
-            if (node.op == CheckStructure
-                && node.child1() == child1
-                && node.structure() == structure)
-                return index;
-            if (clobbersWorld(index))
+            switch (node.op) {
+            case CheckStructure:
+                if (node.child1() == child1
+                    && node.structure() == structure)
+                    return true;
                 break;
+                
+            case PutStructure:
+                if (node.child1() == child1
+                    && node.structure() == structure)
+                    return true;
+                return false;
+                
+            case PutByOffset:
+                // Setting a property cannot change the structure.
+                break;
+                
+            default:
+                if (clobbersWorld(index))
+                    return false;
+                break;
+            }
         }
-        return NoNode;
+        return false;
     }
     
     NodeIndex getByOffsetLoadElimination(unsigned identifierNumber, NodeIndex child1)
@@ -970,16 +1022,60 @@
         NodeIndex start = startIndexForChildren(child1);
         for (NodeIndex index = m_compileIndex; index-- > start;) {
             Node& node = m_graph[index];
-            if (node.op == GetByOffset
-                && node.child1() == child1
-                && m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber)
-                return index;
-            if (clobbersWorld(index))
+            switch (node.op) {
+            case GetByOffset:
+                if (node.child1() == child1
+                    && m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber)
+                    return index;
                 break;
+                
+            case PutByOffset:
+                if (m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber) {
+                    if (node.child2() == child1)
+                        return node.child3();
+                    return NoNode;
+                }
+                break;
+                
+            case PutStructure:
+                // Changing the structure cannot change the outcome of a property get.
+                break;
+                
+            default:
+                if (clobbersWorld(index))
+                    return NoNode;
+                break;
+            }
         }
         return NoNode;
     }
     
+    NodeIndex getPropertyStorageLoadElimination(NodeIndex child1)
+    {
+        NodeIndex start = startIndexForChildren(child1);
+        for (NodeIndex index = m_compileIndex; index-- > start;) {
+            Node& node = m_graph[index];
+            switch (node.op) {
+            case GetPropertyStorage:
+                if (node.child1() == child1)
+                    return index;
+                break;
+                
+            case PutByOffset:
+            case PutStructure:
+                // Changing the structure or putting to the storage cannot
+                // change the property storage pointer.
+                break;
+                
+            default:
+                if (clobbersWorld(index))
+                    return NoNode;
+                break;
+            }
+        }
+        return NoNode;
+    }
+    
     NodeIndex getScopeChainLoadElimination(unsigned depth)
     {
         NodeIndex start = startIndexForChildren();
@@ -1034,6 +1130,18 @@
         m_replacements[m_compileIndex] = replacement;
     }
     
+    void eliminate()
+    {
+#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
+        printf("   Eliminating @%u", m_compileIndex);
+#endif
+        
+        Node& node = m_graph[m_compileIndex];
+        ASSERT(node.refCount() == 1);
+        ASSERT(node.mustGenerate());
+        node.op = Phantom;
+    }
+    
     void performNodeCSE(Node& node)
     {
         if (node.op & NodeHasVarArgs) {
@@ -1133,9 +1241,14 @@
             break;
             
         case CheckStructure:
-            setReplacement(checkStructureLoadElimination(node.structure(), node.child1()));
+            if (checkStructureLoadElimination(node.structure(), node.child1()))
+                eliminate();
             break;
             
+        case GetPropertyStorage:
+            setReplacement(getPropertyStorageLoadElimination(node.child1()));
+            break;
+            
         case GetByOffset:
             setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber, node.child1()));
             break;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (96442 => 96443)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2011-10-01 00:46:50 UTC (rev 96442)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2011-10-01 00:58:15 UTC (rev 96443)
@@ -1657,13 +1657,37 @@
 
     case CheckStructure: {
         SpeculateCellOperand base(this, node.child1());
+        
+        GPRReg baseGPR = base.gpr();
+        
+        speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structure())));
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case PutStructure: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRReg baseGPR = base.gpr();
+        
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+        // Must always emit this write barrier as the structure transition itself requires it
+        writeBarrier(baseGPR, node.structure(), WriteBarrierForGenericAccess);
+#endif
+        
+        m_jit.storePtr(MacroAssembler::TrustedImmPtr(node.structure()), MacroAssembler::Address(baseGPR, JSCell::structureOffset()));
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case GetPropertyStorage: {
+        SpeculateCellOperand base(this, node.child1());
         GPRTemporary result(this, base);
         
         GPRReg baseGPR = base.gpr();
         GPRReg resultGPR = result.gpr();
         
-        speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structure())));
-        
         m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
         
         storageResult(resultGPR, m_compileIndex);
@@ -1688,6 +1712,30 @@
         break;
     }
         
+    case PutByOffset: {
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+        SpeculateCellOperand base(this, node.child1());
+#endif
+        StorageOperand storage(this, node.child2());
+        JSValueOperand value(this, node.child3());
+
+        GPRReg storageGPR = storage.gpr();
+        GPRReg valueTagGPR = value.tagGPR();
+        GPRReg valuePayloadGPR = value.payloadGPR();
+        
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+        writeBarrier(base.gpr(), valueTagGPR, node.child3(), WriteBarrierForPropertyAccess);
+#endif
+
+        StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
+        
+        m_jit.storePtr(valueTagGPR, JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
+        m_jit.storePtr(valuePayloadGPR, JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
     case GetMethod: {
         SpeculateCellOperand base(this, node.child1());
         GPRTemporary resultTag(this, base);

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (96442 => 96443)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2011-10-01 00:46:50 UTC (rev 96442)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2011-10-01 00:58:15 UTC (rev 96443)
@@ -1717,13 +1717,37 @@
 
     case CheckStructure: {
         SpeculateCellOperand base(this, node.child1());
+        
+        GPRReg baseGPR = base.gpr();
+        
+        speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structure())));
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case PutStructure: {
+        SpeculateCellOperand base(this, node.child1());
+        GPRReg baseGPR = base.gpr();
+        
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+        // Must always emit this write barrier as the structure transition itself requires it
+        writeBarrier(baseGPR, node.structure(), WriteBarrierForGenericAccess);
+#endif
+        
+        m_jit.storePtr(MacroAssembler::TrustedImmPtr(node.structure()), MacroAssembler::Address(baseGPR, JSCell::structureOffset()));
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
+    case GetPropertyStorage: {
+        SpeculateCellOperand base(this, node.child1());
         GPRTemporary result(this, base);
         
         GPRReg baseGPR = base.gpr();
         GPRReg resultGPR = result.gpr();
         
-        speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structure())));
-        
         m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
         
         storageResult(resultGPR, m_compileIndex);
@@ -1745,6 +1769,28 @@
         break;
     }
         
+    case PutByOffset: {
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+        SpeculateCellOperand base(this, node.child1());
+#endif
+        StorageOperand storage(this, node.child2());
+        JSValueOperand value(this, node.child3());
+
+        GPRReg storageGPR = storage.gpr();
+        GPRReg valueGPR = value.gpr();
+        
+#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
+        writeBarrier(base.gpr(), value.gpr(), node.child3(), WriteBarrierForPropertyAccess);
+#endif
+
+        StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
+        
+        m_jit.storePtr(valueGPR, JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue)));
+        
+        noResult(m_compileIndex);
+        break;
+    }
+        
     case GetMethod: {
         SpeculateCellOperand base(this, node.child1());
         GPRTemporary result(this, base);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to