Changeset 96443 in webkit


Ignore:
Timestamp:
Sep 30, 2011 5:58:15 PM (13 years ago)
Author:
fpizlo@apple.com
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):

Location:
trunk/Source/JavaScriptCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r96438 r96443  
     12011-09-30  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG does not speculate aggressively enough on put_by_id
     4        https://bugs.webkit.org/show_bug.cgi?id=69114
     5
     6        Reviewed by Oliver Hunt.
     7
     8        This adds new nodes along with optimizations for those nodes:
     9       
     10        GetPropertyStorage: CheckStructure used to do both the structure
     11        check and retrieve the storage pointer. Now CheckStructure just
     12        checks the structure, and GetPropertyStorage retrieves the
     13        storage pointer.
     14       
     15        PutStructure: Changes the structure, and has the expected store
     16        to load optimization with CheckStructure.
     17       
     18        PutByOffset: Directly sets the value. Has store to load
     19        optimization with GetByOffset.
     20
     21        * dfg/DFGByteCodeParser.cpp:
     22        (JSC::DFG::ByteCodeParser::cellConstant):
     23        (JSC::DFG::ByteCodeParser::parseBlock):
     24        * dfg/DFGGraph.cpp:
     25        (JSC::DFG::Graph::dump):
     26        * dfg/DFGJITCodeGenerator.cpp:
     27        (JSC::DFG::JITCodeGenerator::writeBarrier):
     28        * dfg/DFGJITCodeGenerator.h:
     29        * dfg/DFGNode.h:
     30        (JSC::DFG::Node::hasStructure):
     31        (JSC::DFG::Node::hasStorageAccessData):
     32        * dfg/DFGPropagator.cpp:
     33        (JSC::DFG::Propagator::propagateNodePredictions):
     34        (JSC::DFG::Propagator::impureCSE):
     35        (JSC::DFG::Propagator::checkStructureLoadElimination):
     36        (JSC::DFG::Propagator::getByOffsetLoadElimination):
     37        (JSC::DFG::Propagator::getPropertyStorageLoadElimination):
     38        (JSC::DFG::Propagator::eliminate):
     39        (JSC::DFG::Propagator::performNodeCSE):
     40        * dfg/DFGSpeculativeJIT32_64.cpp:
     41        (JSC::DFG::SpeculativeJIT::compile):
     42        * dfg/DFGSpeculativeJIT64.cpp:
     43        (JSC::DFG::SpeculativeJIT::compile):
     44
    1452011-09-30  Gavin Barraclough  <barraclough@apple.com>
    246
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r96391 r96443  
    3131#include "DFGCapabilities.h"
    3232#include "CodeBlock.h"
     33#include <wtf/HashMap.h>
    3334#include <wtf/MathExtras.h>
    3435
     
    405406    }
    406407   
     408    NodeIndex cellConstant(JSCell* cell)
     409    {
     410        HashMap<JSCell*, unsigned>::iterator iter = m_cellConstants.find(cell);
     411        if (iter != m_cellConstants.end())
     412            return getJSConstant(iter->second);
     413       
     414        m_codeBlock->addConstant(cell);
     415        m_constants.append(ConstantRecord());
     416        ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
     417       
     418        return getJSConstant(m_codeBlock->numberOfConstantRegisters() - 1);
     419    }
     420   
    407421    CodeOrigin currentCodeOrigin()
    408422    {
     
    577591    unsigned m_constantNaN;
    578592    unsigned m_constant1;
     593    HashMap<JSCell*, unsigned> m_cellConstants;
    579594
    580595    // A constant in the constant pool may be represented by more than one
     
    11551170               
    11561171                if (offset != notFound) {
    1157                     getById = addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(CheckStructure, OpInfo(structure), base));
     1172                    addToGraph(CheckStructure, OpInfo(structure), base);
     1173                    getById = addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(GetPropertyStorage, base));
    11581174                   
    11591175                    StorageAccessData storageAccessData;
     
    11751191            NodeIndex value = get(currentInstruction[3].u.operand);
    11761192            NodeIndex base = get(currentInstruction[1].u.operand);
    1177             unsigned identifier = currentInstruction[2].u.operand;
     1193            unsigned identifierNumber = currentInstruction[2].u.operand;
    11781194            bool direct = currentInstruction[8].u.operand;
    11791195
    1180             if (direct)
    1181                 addToGraph(PutByIdDirect, OpInfo(identifier), base, value);
    1182             else
    1183                 addToGraph(PutById, OpInfo(identifier), base, value);
     1196            StructureStubInfo& stubInfo = m_profiledBlock->getStubInfo(m_currentIndex);
     1197            if (!stubInfo.seen)
     1198                addToGraph(ForceOSRExit);
     1199           
     1200            bool alreadyGenerated = false;
     1201           
     1202            if (stubInfo.seen && !m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)) {
     1203                switch (stubInfo.accessType) {
     1204                case access_put_by_id_replace: {
     1205                    Structure* structure = stubInfo.u.putByIdReplace.baseObjectStructure.get();
     1206                    Identifier identifier = m_codeBlock->identifier(identifierNumber);
     1207                    size_t offset = structure->get(*m_globalData, identifier);
     1208                   
     1209                    if (offset != notFound) {
     1210                        addToGraph(CheckStructure, OpInfo(structure), base);
     1211                        addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
     1212                       
     1213                        StorageAccessData storageAccessData;
     1214                        storageAccessData.offset = offset;
     1215                        storageAccessData.identifierNumber = identifierNumber;
     1216                        m_graph.m_storageAccessData.append(storageAccessData);
     1217                       
     1218                        alreadyGenerated = true;
     1219                    }
     1220                    break;
     1221                }
     1222                   
     1223                case access_put_by_id_transition: {
     1224                    Structure* previousStructure = stubInfo.u.putByIdTransition.previousStructure.get();
     1225                    Structure* newStructure = stubInfo.u.putByIdTransition.structure.get();
     1226                   
     1227                    if (previousStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
     1228                        break;
     1229                   
     1230                    StructureChain* structureChain = stubInfo.u.putByIdTransition.chain.get();
     1231                   
     1232                    Identifier identifier = m_codeBlock->identifier(identifierNumber);
     1233                    size_t offset = newStructure->get(*m_globalData, identifier);
     1234                   
     1235                    if (offset != notFound) {
     1236                        addToGraph(CheckStructure, OpInfo(previousStructure), base);
     1237                        if (!direct) {
     1238                            for (WriteBarrier<Structure>* it = structureChain->head(); *it; ++it) {
     1239                                JSValue prototype = (*it)->storedPrototype();
     1240                                if (prototype.isNull())
     1241                                    continue;
     1242                                ASSERT(prototype.isCell());
     1243                                addToGraph(CheckStructure, OpInfo(prototype.asCell()->structure()), cellConstant(prototype.asCell()));
     1244                            }
     1245                        }
     1246                        addToGraph(PutStructure, OpInfo(newStructure), base);
     1247                       
     1248                        addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
     1249                       
     1250                        StorageAccessData storageAccessData;
     1251                        storageAccessData.offset = offset;
     1252                        storageAccessData.identifierNumber = identifierNumber;
     1253                        m_graph.m_storageAccessData.append(storageAccessData);
     1254                       
     1255                        alreadyGenerated = true;
     1256                    }
     1257                    break;
     1258                }
     1259                   
     1260                default:
     1261                    break;
     1262                }
     1263            }
     1264           
     1265            if (!alreadyGenerated) {
     1266                if (direct)
     1267                    addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
     1268                else
     1269                    addToGraph(PutById, OpInfo(identifierNumber), base, value);
     1270            }
    11841271
    11851272            NEXT_OPCODE(op_put_by_id);
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r96375 r96443  
    150150        hasPrinted = true;
    151151    }
     152    if (node.hasStructure()) {
     153        printf("%sstruct(%p)", hasPrinted ? ", " : "", node.structure());
     154        hasPrinted = true;
     155    }
     156    if (node.hasStorageAccessData()) {
     157        StorageAccessData& storageAccessData = m_storageAccessData[node.storageAccessDataIndex()];
     158        if (codeBlock)
     159            printf("%sid%u{%s}", hasPrinted ? ", " : "", storageAccessData.identifierNumber, codeBlock->identifier(storageAccessData.identifierNumber).ustring().utf8().data());
     160        else
     161            printf("%sid%u", hasPrinted ? ", " : "", storageAccessData.identifierNumber);
     162       
     163        printf(", %lu", storageAccessData.offset);
     164        hasPrinted = true;
     165    }
    152166    ASSERT(node.hasVariableAccessData() == node.hasLocal());
    153167    if (node.hasVariableAccessData()) {
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp

    r96377 r96443  
    268268}
    269269
     270void JITCodeGenerator::writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
     271{
     272    UNUSED_PARAM(ownerGPR);
     273    UNUSED_PARAM(value);
     274    UNUSED_PARAM(scratch1);
     275    UNUSED_PARAM(scratch2);
     276    UNUSED_PARAM(useKind);
     277   
     278    if (Heap::isMarked(value))
     279        return;
     280
     281#if ENABLE(WRITE_BARRIER_PROFILING)
     282    JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));
     283#endif
     284
     285#if ENABLE(GGC)
     286    GPRTemporary temp1;
     287    GPRTemporary temp2;
     288    if (scratch1 == InvalidGPRReg) {
     289        GPRTemporary scratchGPR(this);
     290        temp1.adopt(scratchGPR);
     291        scratch1 = temp1.gpr();
     292    }
     293    if (scratch2 == InvalidGPRReg) {
     294        GPRTemporary scratchGPR(this);
     295        temp2.adopt(scratchGPR);
     296        scratch2 = temp2.gpr();
     297    }
     298
     299    markCellCard(m_jit, ownerGPR, scratch1, scratch2);
     300#endif
     301}
     302
    270303void JITCodeGenerator::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind useKind, GPRReg scratch)
    271304{
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h

    r96415 r96443  
    215215
    216216    void writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg);
     217    void writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg);
    217218    void writeBarrier(JSCell* owner, GPRReg valueGPR, NodeIndex valueIndex, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg);
    218219
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r96389 r96443  
    314314    macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
    315315    macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
    316     macro(CheckStructure, NodeResultStorage | NodeMustGenerate) \
     316    macro(CheckStructure, NodeMustGenerate) \
     317    macro(PutStructure, NodeMustGenerate | NodeClobbersWorld) \
     318    macro(GetPropertyStorage, NodeResultStorage) \
    317319    macro(GetByOffset, NodeResultJS) \
     320    macro(PutByOffset, NodeMustGenerate | NodeClobbersWorld) \
    318321    macro(GetArrayLength, NodeResultInt32) \
    319322    macro(GetMethod, NodeResultJS | NodeMustGenerate) \
     
    783786    bool hasStructure()
    784787    {
    785         return op == CheckStructure;
     788        return op == CheckStructure || op == PutStructure;
    786789    }
    787790   
     
    793796    bool hasStorageAccessData()
    794797    {
    795         return op == GetByOffset;
     798        return op == GetByOffset || op == PutByOffset;
    796799    }
    797800   
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r96375 r96443  
    449449        }
    450450           
    451         case CheckStructure: {
     451        case GetPropertyStorage: {
    452452            changed |= setPrediction(PredictOther);
    453453            break;
     
    584584        case PutById:
    585585        case PutByIdDirect:
     586        case CheckStructure:
     587        case PutStructure:
     588        case PutByOffset:
    586589            break;
    587590           
     
    889892    }
    890893   
     894    NodeIndex impureCSE(Node& node)
     895    {
     896        NodeIndex child1 = canonicalize(node.child1());
     897        NodeIndex child2 = canonicalize(node.child2());
     898        NodeIndex child3 = canonicalize(node.child3());
     899       
     900        NodeIndex start = startIndex();
     901        for (NodeIndex index = m_compileIndex; index-- > start;) {
     902            Node& otherNode = m_graph[index];
     903            if (node.op == otherNode.op
     904                && node.arithNodeFlagsForCompare() == otherNode.arithNodeFlagsForCompare()) {
     905                NodeIndex otherChild = canonicalize(otherNode.child1());
     906                if (otherChild == NoNode)
     907                    return index;
     908                if (otherChild == child1) {
     909                    otherChild = canonicalize(otherNode.child2());
     910                    if (otherChild == NoNode)
     911                        return index;
     912                    if (otherChild == child2) {
     913                        otherChild = canonicalize(otherNode.child3());
     914                        if (otherChild == NoNode)
     915                            return index;
     916                        if (otherChild == child3)
     917                            return index;
     918                    }
     919                }
     920            }
     921            if (clobbersWorld(index))
     922                break;
     923        }
     924        return NoNode;
     925    }
     926   
    891927    NodeIndex globalVarLoadElimination(unsigned varNumber)
    892928    {
     
    951987    }
    952988   
    953     NodeIndex checkStructureLoadElimination(Structure* structure, NodeIndex child1)
     989    bool checkStructureLoadElimination(Structure* structure, NodeIndex child1)
    954990    {
    955991        NodeIndex start = startIndexForChildren(child1);
    956992        for (NodeIndex index = m_compileIndex; index-- > start;) {
    957993            Node& node = m_graph[index];
    958             if (node.op == CheckStructure
    959                 && node.child1() == child1
    960                 && node.structure() == structure)
    961                 return index;
    962             if (clobbersWorld(index))
    963                 break;
    964         }
    965         return NoNode;
     994            switch (node.op) {
     995            case CheckStructure:
     996                if (node.child1() == child1
     997                    && node.structure() == structure)
     998                    return true;
     999                break;
     1000               
     1001            case PutStructure:
     1002                if (node.child1() == child1
     1003                    && node.structure() == structure)
     1004                    return true;
     1005                return false;
     1006               
     1007            case PutByOffset:
     1008                // Setting a property cannot change the structure.
     1009                break;
     1010               
     1011            default:
     1012                if (clobbersWorld(index))
     1013                    return false;
     1014                break;
     1015            }
     1016        }
     1017        return false;
    9661018    }
    9671019   
     
    9711023        for (NodeIndex index = m_compileIndex; index-- > start;) {
    9721024            Node& node = m_graph[index];
    973             if (node.op == GetByOffset
    974                 && node.child1() == child1
    975                 && m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber)
    976                 return index;
    977             if (clobbersWorld(index))
    978                 break;
     1025            switch (node.op) {
     1026            case GetByOffset:
     1027                if (node.child1() == child1
     1028                    && m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber)
     1029                    return index;
     1030                break;
     1031               
     1032            case PutByOffset:
     1033                if (m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber) {
     1034                    if (node.child2() == child1)
     1035                        return node.child3();
     1036                    return NoNode;
     1037                }
     1038                break;
     1039               
     1040            case PutStructure:
     1041                // Changing the structure cannot change the outcome of a property get.
     1042                break;
     1043               
     1044            default:
     1045                if (clobbersWorld(index))
     1046                    return NoNode;
     1047                break;
     1048            }
     1049        }
     1050        return NoNode;
     1051    }
     1052   
     1053    NodeIndex getPropertyStorageLoadElimination(NodeIndex child1)
     1054    {
     1055        NodeIndex start = startIndexForChildren(child1);
     1056        for (NodeIndex index = m_compileIndex; index-- > start;) {
     1057            Node& node = m_graph[index];
     1058            switch (node.op) {
     1059            case GetPropertyStorage:
     1060                if (node.child1() == child1)
     1061                    return index;
     1062                break;
     1063               
     1064            case PutByOffset:
     1065            case PutStructure:
     1066                // Changing the structure or putting to the storage cannot
     1067                // change the property storage pointer.
     1068                break;
     1069               
     1070            default:
     1071                if (clobbersWorld(index))
     1072                    return NoNode;
     1073                break;
     1074            }
    9791075        }
    9801076        return NoNode;
     
    10331129        // At this point we will eliminate all references to this node.
    10341130        m_replacements[m_compileIndex] = replacement;
     1131    }
     1132   
     1133    void eliminate()
     1134    {
     1135#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     1136        printf("   Eliminating @%u", m_compileIndex);
     1137#endif
     1138       
     1139        Node& node = m_graph[m_compileIndex];
     1140        ASSERT(node.refCount() == 1);
     1141        ASSERT(node.mustGenerate());
     1142        node.op = Phantom;
    10351143    }
    10361144   
     
    11341242           
    11351243        case CheckStructure:
    1136             setReplacement(checkStructureLoadElimination(node.structure(), node.child1()));
     1244            if (checkStructureLoadElimination(node.structure(), node.child1()))
     1245                eliminate();
     1246            break;
     1247           
     1248        case GetPropertyStorage:
     1249            setReplacement(getPropertyStorageLoadElimination(node.child1()));
    11371250            break;
    11381251           
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r96436 r96443  
    16581658    case CheckStructure: {
    16591659        SpeculateCellOperand base(this, node.child1());
     1660       
     1661        GPRReg baseGPR = base.gpr();
     1662       
     1663        speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structure())));
     1664       
     1665        noResult(m_compileIndex);
     1666        break;
     1667    }
     1668       
     1669    case PutStructure: {
     1670        SpeculateCellOperand base(this, node.child1());
     1671        GPRReg baseGPR = base.gpr();
     1672       
     1673#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
     1674        // Must always emit this write barrier as the structure transition itself requires it
     1675        writeBarrier(baseGPR, node.structure(), WriteBarrierForGenericAccess);
     1676#endif
     1677       
     1678        m_jit.storePtr(MacroAssembler::TrustedImmPtr(node.structure()), MacroAssembler::Address(baseGPR, JSCell::structureOffset()));
     1679       
     1680        noResult(m_compileIndex);
     1681        break;
     1682    }
     1683       
     1684    case GetPropertyStorage: {
     1685        SpeculateCellOperand base(this, node.child1());
    16601686        GPRTemporary result(this, base);
    16611687       
    16621688        GPRReg baseGPR = base.gpr();
    16631689        GPRReg resultGPR = result.gpr();
    1664        
    1665         speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structure())));
    16661690       
    16671691        m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
     
    16861710       
    16871711        jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex);
     1712        break;
     1713    }
     1714       
     1715    case PutByOffset: {
     1716#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
     1717        SpeculateCellOperand base(this, node.child1());
     1718#endif
     1719        StorageOperand storage(this, node.child2());
     1720        JSValueOperand value(this, node.child3());
     1721
     1722        GPRReg storageGPR = storage.gpr();
     1723        GPRReg valueTagGPR = value.tagGPR();
     1724        GPRReg valuePayloadGPR = value.payloadGPR();
     1725       
     1726#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
     1727        writeBarrier(base.gpr(), valueTagGPR, node.child3(), WriteBarrierForPropertyAccess);
     1728#endif
     1729
     1730        StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
     1731       
     1732        m_jit.storePtr(valueTagGPR, JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
     1733        m_jit.storePtr(valuePayloadGPR, JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
     1734       
     1735        noResult(m_compileIndex);
    16881736        break;
    16891737    }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r96436 r96443  
    17181718    case CheckStructure: {
    17191719        SpeculateCellOperand base(this, node.child1());
     1720       
     1721        GPRReg baseGPR = base.gpr();
     1722       
     1723        speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structure())));
     1724       
     1725        noResult(m_compileIndex);
     1726        break;
     1727    }
     1728       
     1729    case PutStructure: {
     1730        SpeculateCellOperand base(this, node.child1());
     1731        GPRReg baseGPR = base.gpr();
     1732       
     1733#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
     1734        // Must always emit this write barrier as the structure transition itself requires it
     1735        writeBarrier(baseGPR, node.structure(), WriteBarrierForGenericAccess);
     1736#endif
     1737       
     1738        m_jit.storePtr(MacroAssembler::TrustedImmPtr(node.structure()), MacroAssembler::Address(baseGPR, JSCell::structureOffset()));
     1739       
     1740        noResult(m_compileIndex);
     1741        break;
     1742    }
     1743       
     1744    case GetPropertyStorage: {
     1745        SpeculateCellOperand base(this, node.child1());
    17201746        GPRTemporary result(this, base);
    17211747       
    17221748        GPRReg baseGPR = base.gpr();
    17231749        GPRReg resultGPR = result.gpr();
    1724        
    1725         speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structure())));
    17261750       
    17271751        m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
     
    17431767       
    17441768        jsValueResult(resultGPR, m_compileIndex);
     1769        break;
     1770    }
     1771       
     1772    case PutByOffset: {
     1773#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
     1774        SpeculateCellOperand base(this, node.child1());
     1775#endif
     1776        StorageOperand storage(this, node.child2());
     1777        JSValueOperand value(this, node.child3());
     1778
     1779        GPRReg storageGPR = storage.gpr();
     1780        GPRReg valueGPR = value.gpr();
     1781       
     1782#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
     1783        writeBarrier(base.gpr(), value.gpr(), node.child3(), WriteBarrierForPropertyAccess);
     1784#endif
     1785
     1786        StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
     1787       
     1788        m_jit.storePtr(valueGPR, JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue)));
     1789       
     1790        noResult(m_compileIndex);
    17451791        break;
    17461792    }
Note: See TracChangeset for help on using the changeset viewer.