Changeset 96527 in webkit


Ignore:
Timestamp:
Oct 3, 2011 12:25:16 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG should speculate more aggressively on obvious cases on
polymorphic get_by_id
https://bugs.webkit.org/show_bug.cgi?id=69235

Reviewed by Oliver Hunt.

This implements trivial polymorphic get_by_id. It also fixes
problems in the CSE for CheckStructure in the put_by_id
transition case.

Doing this required knowing whether a polymorphic get_by_id stub
was doing a direct access rather than a call of some kind.

Slight speed-up on Kraken and SunSpider. 0.5% speed-up in the
scaled mean of all benchmarks.

  • GNUmakefile.list.am:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/Instruction.h:

(JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set):
(JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::cellConstant):
(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump):

  • dfg/DFGGraph.h:

(JSC::DFG::Graph::addStructureSet):
(JSC::DFG::Graph::addStructureTransitionData):

  • dfg/DFGNode.h:

(JSC::DFG::StructureTransitionData::StructureTransitionData):
(JSC::DFG::Node::hasStructureTransitionData):
(JSC::DFG::Node::structureTransitionData):
(JSC::DFG::Node::hasStructureSet):
(JSC::DFG::Node::structureSet):

  • dfg/DFGPropagator.cpp:

(JSC::DFG::Propagator::checkStructureLoadElimination):
(JSC::DFG::Propagator::performNodeCSE):

  • dfg/DFGRepatch.cpp:

(JSC::DFG::tryBuildGetByIDList):
(JSC::DFG::tryBuildGetByIDProtoList):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGStructureSet.h: Added.

(JSC::DFG::StructureSet::StructureSet):
(JSC::DFG::StructureSet::add):
(JSC::DFG::StructureSet::addAll):
(JSC::DFG::StructureSet::remove):
(JSC::DFG::StructureSet::contains):
(JSC::DFG::StructureSet::isSubsetOf):
(JSC::DFG::StructureSet::isSupersetOf):
(JSC::DFG::StructureSet::size):
(JSC::DFG::StructureSet::at):
(JSC::DFG::StructureSet::operator[]):
(JSC::DFG::StructureSet::last):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::privateCompileGetByIdSelfList):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::privateCompileGetByIdSelfList):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):
(JSC::getPolymorphicAccessStructureListSlot):

Location:
trunk/Source/JavaScriptCore
Files:
1 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r96526 r96527  
     12011-10-02  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG should speculate more aggressively on obvious cases on
     4        polymorphic get_by_id
     5        https://bugs.webkit.org/show_bug.cgi?id=69235
     6
     7        Reviewed by Oliver Hunt.
     8       
     9        This implements trivial polymorphic get_by_id. It also fixes
     10        problems in the CSE for CheckStructure in the put_by_id
     11        transition case.
     12       
     13        Doing this required knowing whether a polymorphic get_by_id stub
     14        was doing a direct access rather than a call of some kind.
     15       
     16        Slight speed-up on Kraken and SunSpider. 0.5% speed-up in the
     17        scaled mean of all benchmarks.
     18
     19        * GNUmakefile.list.am:
     20        * JavaScriptCore.xcodeproj/project.pbxproj:
     21        * bytecode/Instruction.h:
     22        (JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set):
     23        (JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList):
     24        * dfg/DFGByteCodeParser.cpp:
     25        (JSC::DFG::ByteCodeParser::cellConstant):
     26        (JSC::DFG::ByteCodeParser::parseBlock):
     27        * dfg/DFGGraph.cpp:
     28        (JSC::DFG::Graph::dump):
     29        * dfg/DFGGraph.h:
     30        (JSC::DFG::Graph::addStructureSet):
     31        (JSC::DFG::Graph::addStructureTransitionData):
     32        * dfg/DFGNode.h:
     33        (JSC::DFG::StructureTransitionData::StructureTransitionData):
     34        (JSC::DFG::Node::hasStructureTransitionData):
     35        (JSC::DFG::Node::structureTransitionData):
     36        (JSC::DFG::Node::hasStructureSet):
     37        (JSC::DFG::Node::structureSet):
     38        * dfg/DFGPropagator.cpp:
     39        (JSC::DFG::Propagator::checkStructureLoadElimination):
     40        (JSC::DFG::Propagator::performNodeCSE):
     41        * dfg/DFGRepatch.cpp:
     42        (JSC::DFG::tryBuildGetByIDList):
     43        (JSC::DFG::tryBuildGetByIDProtoList):
     44        * dfg/DFGSpeculativeJIT32_64.cpp:
     45        (JSC::DFG::SpeculativeJIT::compile):
     46        * dfg/DFGSpeculativeJIT64.cpp:
     47        (JSC::DFG::SpeculativeJIT::compile):
     48        * dfg/DFGStructureSet.h: Added.
     49        (JSC::DFG::StructureSet::StructureSet):
     50        (JSC::DFG::StructureSet::add):
     51        (JSC::DFG::StructureSet::addAll):
     52        (JSC::DFG::StructureSet::remove):
     53        (JSC::DFG::StructureSet::contains):
     54        (JSC::DFG::StructureSet::isSubsetOf):
     55        (JSC::DFG::StructureSet::isSupersetOf):
     56        (JSC::DFG::StructureSet::size):
     57        (JSC::DFG::StructureSet::at):
     58        (JSC::DFG::StructureSet::operator[]):
     59        (JSC::DFG::StructureSet::last):
     60        * jit/JITPropertyAccess.cpp:
     61        (JSC::JIT::privateCompileGetByIdSelfList):
     62        (JSC::JIT::privateCompileGetByIdProtoList):
     63        (JSC::JIT::privateCompileGetByIdChainList):
     64        * jit/JITPropertyAccess32_64.cpp:
     65        (JSC::JIT::privateCompileGetByIdSelfList):
     66        (JSC::JIT::privateCompileGetByIdProtoList):
     67        (JSC::JIT::privateCompileGetByIdChainList):
     68        * jit/JITStubs.cpp:
     69        (JSC::DEFINE_STUB_FUNCTION):
     70        (JSC::getPolymorphicAccessStructureListSlot):
     71
    1722011-10-03  Jer Noble  <jer.noble@apple.com>
    273
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r96505 r96527  
    135135        Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp \
    136136        Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h \
     137        Source/JavaScriptCore/dfg/DFGStructureSet.h \
    137138        Source/JavaScriptCore/heap/AllocationSpace.cpp \
    138139        Source/JavaScriptCore/heap/AllocationSpace.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r96465 r96527  
    8484                0FE228ED1436AB2700196C48 /* Heuristics.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE228EB1436AB2300196C48 /* Heuristics.h */; settings = {ATTRIBUTES = (Private, ); }; };
    8585                0FE228EE1436AB2C00196C48 /* Heuristics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Heuristics.cpp */; };
     86                0FFF4BB4143955E900655BC0 /* DFGStructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFF4BB2143955E600655BC0 /* DFGStructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
    8687                1400067712A6F7830064D123 /* OSAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1400067612A6F7830064D123 /* OSAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
    8788                1400069312A6F9E10064D123 /* OSAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */; };
     
    842843                0FE228EA1436AB2300196C48 /* Heuristics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Heuristics.cpp; sourceTree = "<group>"; };
    843844                0FE228EB1436AB2300196C48 /* Heuristics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Heuristics.h; sourceTree = "<group>"; };
     845                0FFF4BB2143955E600655BC0 /* DFGStructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureSet.h; path = dfg/DFGStructureSet.h; sourceTree = "<group>"; };
    844846                1400067612A6F7830064D123 /* OSAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSAllocator.h; sourceTree = "<group>"; };
    845847                1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSAllocatorPosix.cpp; sourceTree = "<group>"; };
     
    22772279                        isa = PBXGroup;
    22782280                        children = (
     2281                                0FFF4BB2143955E600655BC0 /* DFGStructureSet.h */,
    22792282                                86EC9DB41328DF82002B2AD7 /* DFGByteCodeParser.cpp */,
    22802283                                86EC9DB51328DF82002B2AD7 /* DFGByteCodeParser.h */,
     
    28682871                                86880F1E14328BB900B08D42 /* DFGJITCompilerInlineMethods.h in Headers */,
    28692872                                0FE228ED1436AB2700196C48 /* Heuristics.h in Headers */,
     2873                                0FFF4BB4143955E900655BC0 /* DFGStructureSet.h in Headers */,
    28702874                        );
    28712875                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/JavaScriptCore/bytecode/Instruction.h

    r95901 r96527  
    5959        struct PolymorphicStubInfo {
    6060            bool isChain;
     61            bool isDirect;
    6162            PolymorphicAccessStructureListStubRoutineType stubRoutine;
    6263            WriteBarrier<Structure> base;
     
    7172            }
    7273
    73             void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base)
     74            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, bool isDirect)
    7475            {
    7576                stubRoutine = _stubRoutine;
     
    7778                u.proto.clear();
    7879                isChain = false;
     80                this->isDirect = isDirect;
    7981            }
    8082           
    81             void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto)
     83            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, Structure* _proto, bool isDirect)
    8284            {
    8385                stubRoutine = _stubRoutine;
     
    8587                u.proto.set(globalData, owner, _proto);
    8688                isChain = false;
     89                this->isDirect = isDirect;
    8790            }
    8891           
    89             void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain)
     92            void set(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType _stubRoutine, Structure* _base, StructureChain* _chain, bool isDirect)
    9093            {
    9194                stubRoutine = _stubRoutine;
     
    9396                u.chain.set(globalData, owner, _chain);
    9497                isChain = true;
     98                this->isDirect = isDirect;
    9599            }
    96100        } list[POLYMORPHIC_LIST_CACHE_SIZE];
    97101       
    98         PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase)
     102        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, bool isDirect)
    99103        {
    100             list[0].set(globalData, owner, stubRoutine, firstBase);
     104            list[0].set(globalData, owner, stubRoutine, firstBase, isDirect);
    101105        }
    102106
    103         PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto)
     107        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, Structure* firstProto, bool isDirect)
    104108        {
    105             list[0].set(globalData, owner, stubRoutine, firstBase, firstProto);
     109            list[0].set(globalData, owner, stubRoutine, firstBase, firstProto, isDirect);
    106110        }
    107111
    108         PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain)
     112        PolymorphicAccessStructureList(JSGlobalData& globalData, JSCell* owner, PolymorphicAccessStructureListStubRoutineType stubRoutine, Structure* firstBase, StructureChain* firstChain, bool isDirect)
    109113        {
    110             list[0].set(globalData, owner, stubRoutine, firstBase, firstChain);
     114            list[0].set(globalData, owner, stubRoutine, firstBase, firstChain, isDirect);
    111115        }
    112116
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r96443 r96527  
    415415        m_constants.append(ConstantRecord());
    416416        ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
     417       
     418        m_cellConstants.add(cell, m_codeBlock->numberOfConstantRegisters() - 1);
    417419       
    418420        return getJSConstant(m_codeBlock->numberOfConstantRegisters() - 1);
     
    11611163            unsigned identifierNumber = currentInstruction[3].u.operand;
    11621164           
     1165            Identifier identifier = m_codeBlock->identifier(identifierNumber);
    11631166            StructureStubInfo& stubInfo = m_profiledBlock->getStubInfo(m_currentIndex);
    11641167           
    1165             NodeIndex getById = NoNode;
    1166             if (stubInfo.seen && stubInfo.accessType == access_get_by_id_self) {
    1167                 Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
    1168                 Identifier identifier = m_codeBlock->identifier(identifierNumber);
    1169                 size_t offset = structure->get(*m_globalData, identifier);
    1170                
    1171                 if (offset != notFound) {
    1172                     addToGraph(CheckStructure, OpInfo(structure), base);
    1173                     getById = addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(GetPropertyStorage, base));
     1168            size_t offset = notFound;
     1169            StructureSet structureSet;
     1170            if (stubInfo.seen) {
     1171                switch (stubInfo.accessType) {
     1172                case access_get_by_id_self: {
     1173                    Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
     1174                    offset = structure->get(*m_globalData, identifier);
    11741175                   
    1175                     StorageAccessData storageAccessData;
    1176                     storageAccessData.offset = offset;
    1177                     storageAccessData.identifierNumber = identifierNumber;
    1178                     m_graph.m_storageAccessData.append(storageAccessData);
     1176                    if (offset != notFound)
     1177                        structureSet.add(structure);
     1178
     1179                    if (offset != notFound)
     1180                        ASSERT(structureSet.size());
     1181                    break;
     1182                }
     1183                   
     1184                case access_get_by_id_self_list: {
     1185                    PolymorphicAccessStructureList* list = stubInfo.u.getByIdProtoList.structureList;
     1186                    unsigned size = stubInfo.u.getByIdProtoList.listSize;
     1187                    for (unsigned i = 0; i < size; ++i) {
     1188                        if (!list->list[i].isDirect) {
     1189                            offset = notFound;
     1190                            break;
     1191                        }
     1192                       
     1193                        Structure* structure = list->list[i].base.get();
     1194                        size_t myOffset = structure->get(*m_globalData, identifier);
     1195                   
     1196                        if (myOffset == notFound) {
     1197                            offset = notFound;
     1198                            break;
     1199                        }
     1200                   
     1201                        if (!i)
     1202                            offset = myOffset;
     1203                        else if (offset != myOffset) {
     1204                            offset = notFound;
     1205                            break;
     1206                        }
     1207                   
     1208                        structureSet.add(structure);
     1209                    }
     1210                   
     1211                    if (offset != notFound)
     1212                        ASSERT(structureSet.size());
     1213                    break;
     1214                }
     1215                   
     1216                default:
     1217                    ASSERT(offset == notFound);
     1218                    break;
    11791219                }
    11801220            }
    1181            
    1182             if (getById == NoNode)
    1183                 getById = addToGraph(GetById, OpInfo(identifierNumber), OpInfo(prediction), base);
    1184            
    1185             set(currentInstruction[1].u.operand, getById);
     1221                       
     1222            if (offset != notFound) {
     1223                ASSERT(structureSet.size());
     1224                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structureSet)), base);
     1225                set(currentInstruction[1].u.operand, addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(GetPropertyStorage, base)));
     1226               
     1227                StorageAccessData storageAccessData;
     1228                storageAccessData.offset = offset;
     1229                storageAccessData.identifierNumber = identifierNumber;
     1230                m_graph.m_storageAccessData.append(storageAccessData);
     1231            } else
     1232                set(currentInstruction[1].u.operand, addToGraph(GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
    11861233
    11871234            NEXT_OPCODE(op_get_by_id);
     
    12081255                   
    12091256                    if (offset != notFound) {
    1210                         addToGraph(CheckStructure, OpInfo(structure), base);
     1257                        addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), base);
    12111258                        addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
    12121259                       
     
    12341281                   
    12351282                    if (offset != notFound) {
    1236                         addToGraph(CheckStructure, OpInfo(previousStructure), base);
     1283                        addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(previousStructure)), base);
    12371284                        if (!direct) {
    12381285                            for (WriteBarrier<Structure>* it = structureChain->head(); *it; ++it) {
     
    12411288                                    continue;
    12421289                                ASSERT(prototype.isCell());
    1243                                 addToGraph(CheckStructure, OpInfo(prototype.asCell()->structure()), cellConstant(prototype.asCell()));
     1290                                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(prototype.asCell()->structure())), cellConstant(prototype.asCell()));
    12441291                            }
    12451292                        }
    1246                         addToGraph(PutStructure, OpInfo(newStructure), base);
     1293                        addToGraph(PutStructure, OpInfo(m_graph.addStructureTransitionData(StructureTransitionData(previousStructure, newStructure))), base);
    12471294                       
    12481295                        addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r96443 r96527  
    150150        hasPrinted = true;
    151151    }
    152     if (node.hasStructure()) {
    153         printf("%sstruct(%p)", hasPrinted ? ", " : "", node.structure());
     152    if (node.hasStructureSet()) {
     153        for (size_t i = 0; i < node.structureSet().size(); ++i) {
     154            printf("%sstruct(%p)", hasPrinted ? ", " : "", node.structureSet()[i]);
     155            hasPrinted = true;
     156        }
     157    }
     158    if (node.hasStructureTransitionData()) {
     159        printf("%sstruct(%p -> %p)", hasPrinted ? ", " : "", node.structureTransitionData().previousStructure, node.structureTransitionData().newStructure);
    154160        hasPrinted = true;
    155161    }
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r96375 r96527  
    330330
    331331    void predictArgumentTypes(ExecState*, CodeBlock*);
     332   
     333    StructureSet* addStructureSet(const StructureSet& structureSet)
     334    {
     335        ASSERT(structureSet.size());
     336        m_structureSet.append(structureSet);
     337        return &m_structureSet.last();
     338    }
     339   
     340    StructureTransitionData* addStructureTransitionData(const StructureTransitionData& structureTransitionData)
     341    {
     342        m_structureTransitionData.append(structureTransitionData);
     343        return &m_structureTransitionData.last();
     344    }
    332345
    333346    Vector< OwnPtr<BasicBlock> , 8> m_blocks;
     
    338351    Vector<NodeIndex, 8> m_arguments;
    339352    SegmentedVector<VariableAccessData, 16> m_variableAccessData;
     353    SegmentedVector<StructureSet, 16> m_structureSet;
     354    SegmentedVector<StructureTransitionData, 8> m_structureTransitionData;
    340355    unsigned m_preservedVars;
    341356    unsigned m_localVars;
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r96461 r96527  
    2727#define DFGNode_h
    2828
     29#include "DFGStructureSet.h"
    2930#include <wtf/BoundsCheckedPointer.h>
    3031#include <wtf/Platform.h>
     
    155156};
    156157
     158struct StructureTransitionData {
     159    Structure* previousStructure;
     160    Structure* newStructure;
     161   
     162    StructureTransitionData() { }
     163   
     164    StructureTransitionData(Structure* previousStructure, Structure* newStructure)
     165        : previousStructure(previousStructure)
     166        , newStructure(newStructure)
     167    {
     168    }
     169};
     170
    157171typedef unsigned ArithNodeFlags;
    158172#define NodeUseBottom      0x00
     
    785799    }
    786800   
    787     bool hasStructure()
    788     {
    789         return op == CheckStructure || op == PutStructure;
    790     }
    791    
    792     Structure* structure()
    793     {
    794         return reinterpret_cast<Structure*>(m_opInfo);
     801    bool hasStructureTransitionData()
     802    {
     803        return op == PutStructure;
     804    }
     805   
     806    StructureTransitionData& structureTransitionData()
     807    {
     808        ASSERT(hasStructureTransitionData());
     809        return *reinterpret_cast<StructureTransitionData*>(m_opInfo);
     810    }
     811   
     812    bool hasStructureSet()
     813    {
     814        return op == CheckStructure;
     815    }
     816   
     817    StructureSet& structureSet()
     818    {
     819        ASSERT(hasStructureSet());
     820        return *reinterpret_cast<StructureSet*>(m_opInfo);
    795821    }
    796822   
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r96482 r96527  
    10141014    }
    10151015   
    1016     bool checkStructureLoadElimination(Structure* structure, NodeIndex child1)
     1016    bool checkStructureLoadElimination(const StructureSet& structureSet, NodeIndex child1)
    10171017    {
    10181018        NodeIndex start = startIndexForChildren(child1);
     
    10221022            case CheckStructure:
    10231023                if (node.child1() == child1
    1024                     && node.structure() == structure)
     1024                    && structureSet.isSupersetOf(node.structureSet()))
    10251025                    return true;
    10261026                break;
     
    10281028            case PutStructure:
    10291029                if (node.child1() == child1
    1030                     && node.structure() == structure)
     1030                    && structureSet.contains(node.structureTransitionData().newStructure))
    10311031                    return true;
    1032                 return false;
     1032                if (structureSet.contains(node.structureTransitionData().previousStructure))
     1033                    return false;
     1034                break;
    10331035               
    10341036            case PutByOffset:
     
    12941296           
    12951297        case CheckStructure:
    1296             if (checkStructureLoadElimination(node.structure(), node.child1()))
     1298            if (checkStructureLoadElimination(node.structureSet(), node.child1()))
    12971299                eliminate();
    12981300            break;
  • trunk/Source/JavaScriptCore/dfg/DFGRepatch.cpp

    r96171 r96527  
    348348    if (stubInfo.accessType == access_get_by_id_self) {
    349349        ASSERT(!stubInfo.stubRoutine);
    350         polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), MacroAssemblerCodeRef::createSelfManagedCodeRef(stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase)), stubInfo.u.getByIdSelf.baseObjectStructure.get());
     350        polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), MacroAssemblerCodeRef::createSelfManagedCodeRef(stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase)), stubInfo.u.getByIdSelf.baseObjectStructure.get(), true);
    351351        stubInfo.initGetByIdSelfList(polymorphicStructureList, 1);
    352352    } else {
     
    388388        MacroAssemblerCodeRef stubRoutine = patchBuffer.finalizeCode();
    389389       
    390         polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure);
     390        polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure, true);
    391391       
    392392        CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck);
     
    435435    if (stubInfo.accessType == access_get_by_id_chain) {
    436436        ASSERT(!!stubInfo.stubRoutine);
    437         polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), stubInfo.stubRoutine, stubInfo.u.getByIdChain.baseObjectStructure.get(), stubInfo.u.getByIdChain.chain.get());
     437        polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), stubInfo.stubRoutine, stubInfo.u.getByIdChain.baseObjectStructure.get(), stubInfo.u.getByIdChain.chain.get(), true);
    438438        stubInfo.stubRoutine = MacroAssemblerCodeRef();
    439439        stubInfo.initGetByIdProtoList(polymorphicStructureList, 1);
     
    454454        generateProtoChainAccessStub(exec, stubInfo, prototypeChain, count, offset, structure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone), lastProtoBegin, stubRoutine);
    455455       
    456         polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure);
     456        polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure, true);
    457457       
    458458        CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r96461 r96527  
    16751675        SpeculateCellOperand base(this, node.child1());
    16761676       
    1677         GPRReg baseGPR = base.gpr();
    1678        
    1679         speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structure())));
     1677        ASSERT(node.structureSet().size());
     1678       
     1679        if (node.structureSet().size() == 1)
     1680            speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(base.gpr(), JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structureSet()[0])));
     1681        else {
     1682            GPRTemporary structure(this);
     1683           
     1684            m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
     1685           
     1686            JITCompiler::JumpList done;
     1687           
     1688            for (size_t i = 0; i < node.structureSet().size() - 1; ++i)
     1689                done.append(m_jit.branchPtr(JITCompiler::Equal, structure.gpr(), JITCompiler::TrustedImmPtr(node.structureSet()[i])));
     1690           
     1691            speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, structure.gpr(), JITCompiler::TrustedImmPtr(node.structureSet().last())));
     1692           
     1693            done.link(&m_jit);
     1694        }
    16801695       
    16811696        noResult(m_compileIndex);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r96461 r96527  
    17351735        SpeculateCellOperand base(this, node.child1());
    17361736       
    1737         GPRReg baseGPR = base.gpr();
    1738        
    1739         speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structure())));
     1737        ASSERT(node.structureSet().size());
     1738       
     1739        if (node.structureSet().size() == 1)
     1740            speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(base.gpr(), JSCell::structureOffset()), JITCompiler::TrustedImmPtr(node.structureSet()[0])));
     1741        else {
     1742            GPRTemporary structure(this);
     1743           
     1744            m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
     1745           
     1746            JITCompiler::JumpList done;
     1747           
     1748            for (size_t i = 0; i < node.structureSet().size() - 1; ++i)
     1749                done.append(m_jit.branchPtr(JITCompiler::Equal, structure.gpr(), JITCompiler::TrustedImmPtr(node.structureSet()[i])));
     1750           
     1751            speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, structure.gpr(), JITCompiler::TrustedImmPtr(node.structureSet().last())));
     1752           
     1753            done.link(&m_jit);
     1754        }
    17401755       
    17411756        noResult(m_compileIndex);
     
    17491764#if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
    17501765        // Must always emit this write barrier as the structure transition itself requires it
    1751         writeBarrier(baseGPR, node.structure(), WriteBarrierForGenericAccess);
     1766        writeBarrier(baseGPR, node.structureTransitionData().newStructure, WriteBarrierForGenericAccess);
    17521767#endif
    17531768       
    1754         m_jit.storePtr(MacroAssembler::TrustedImmPtr(node.structure()), MacroAssembler::Address(baseGPR, JSCell::structureOffset()));
     1769        m_jit.storePtr(MacroAssembler::TrustedImmPtr(node.structureTransitionData().newStructure), MacroAssembler::Address(baseGPR, JSCell::structureOffset()));
    17551770       
    17561771        noResult(m_compileIndex);
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r96372 r96527  
    703703    Jump failureCase = checkStructure(regT0, structure);
    704704    bool needsStubLink = false;
     705    bool isDirect = false;
    705706    if (slot.cachedPropertyType() == PropertySlot::Getter) {
    706707        needsStubLink = true;
     
    719720        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    720721        stubCall.call();
    721     } else
     722    } else {
     723        isDirect = true;
    722724        compileGetDirectOffset(regT0, regT0, cachedOffset);
     725    }
    723726    Jump success = jump();
    724727
     
    744747    MacroAssemblerCodeRef stubCode = patchBuffer.finalizeCode();
    745748
    746     polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure);
     749    polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, isDirect);
    747750
    748751    // Finally patch the jump to slow case back in the hot path to jump here instead.
     
    767770    // Checks out okay!
    768771    bool needsStubLink = false;
     772    bool isDirect = false;
    769773    if (slot.cachedPropertyType() == PropertySlot::Getter) {
    770774        needsStubLink = true;
     
    783787        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    784788        stubCall.call();
    785     } else
     789    } else {
     790        isDirect = true;
    786791        compileGetDirectOffset(protoObject, regT0, cachedOffset);
     792    }
    787793
    788794    Jump success = jump();
     
    806812
    807813    MacroAssemblerCodeRef stubCode = patchBuffer.finalizeCode();
    808     prototypeStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, prototypeStructure);
     814    prototypeStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, prototypeStructure, isDirect);
    809815
    810816    // Finally patch the jump to slow case back in the hot path to jump here instead.
     
    833839    ASSERT(protoObject);
    834840   
     841    bool needsStubLink = false;
     842    bool isDirect = false;
     843    if (slot.cachedPropertyType() == PropertySlot::Getter) {
     844        needsStubLink = true;
     845        compileGetDirectOffset(protoObject, regT1, cachedOffset);
     846        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     847        stubCall.addArgument(regT1);
     848        stubCall.addArgument(regT0);
     849        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
     850        stubCall.call();
     851    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     852        needsStubLink = true;
     853        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     854        stubCall.addArgument(TrustedImmPtr(protoObject));
     855        stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
     856        stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
     857        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
     858        stubCall.call();
     859    } else {
     860        isDirect = true;
     861        compileGetDirectOffset(protoObject, regT0, cachedOffset);
     862    }
     863    Jump success = jump();
     864
     865    LinkBuffer patchBuffer(*m_globalData, this);
     866   
     867    if (needsStubLink) {
     868        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
     869            if (iter->to)
     870                patchBuffer.link(iter->from, FunctionPtr(iter->to));
     871        }
     872    }
     873
     874    // Use the patch information to link the failure cases back to the original slow case routine.
     875    CodeLocationLabel lastProtoBegin = CodeLocationLabel(prototypeStructures->list[currentIndex - 1].stubRoutine.code());
     876
     877    patchBuffer.link(bucketsOfFail, lastProtoBegin);
     878
     879    // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     880    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
     881
     882    CodeRef stubRoutine = patchBuffer.finalizeCode();
     883
     884    // Track the stub we have created so that it will be deleted later.
     885    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain, isDirect);
     886
     887    // Finally patch the jump to slow case back in the hot path to jump here instead.
     888    CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
     889    RepatchBuffer repatchBuffer(m_codeBlock);
     890    repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
     891}
     892
     893void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
     894{
     895    ASSERT(count);
     896
     897    JumpList bucketsOfFail;
     898
     899    // Check eax is an object of the right Structure.
     900    bucketsOfFail.append(checkStructure(regT0, structure));
     901
     902    Structure* currStructure = structure;
     903    WriteBarrier<Structure>* it = chain->head();
     904    JSObject* protoObject = 0;
     905    for (unsigned i = 0; i < count; ++i, ++it) {
     906        protoObject = asObject(currStructure->prototypeForLookup(callFrame));
     907        currStructure = it->get();
     908        testPrototype(protoObject, bucketsOfFail);
     909    }
     910    ASSERT(protoObject);
     911
    835912    bool needsStubLink = false;
    836913    if (slot.cachedPropertyType() == PropertySlot::Getter) {
     
    855932
    856933    LinkBuffer patchBuffer(*m_globalData, this);
    857    
    858     if (needsStubLink) {
    859         for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
    860             if (iter->to)
    861                 patchBuffer.link(iter->from, FunctionPtr(iter->to));
    862         }
    863     }
    864 
    865     // Use the patch information to link the failure cases back to the original slow case routine.
    866     CodeLocationLabel lastProtoBegin = CodeLocationLabel(prototypeStructures->list[currentIndex - 1].stubRoutine.code());
    867 
    868     patchBuffer.link(bucketsOfFail, lastProtoBegin);
    869 
    870     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
    871     patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
    872 
    873     CodeRef stubRoutine = patchBuffer.finalizeCode();
    874 
    875     // Track the stub we have created so that it will be deleted later.
    876     prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain);
    877 
    878     // Finally patch the jump to slow case back in the hot path to jump here instead.
    879     CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase);
    880     RepatchBuffer repatchBuffer(m_codeBlock);
    881     repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code()));
    882 }
    883 
    884 void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
    885 {
    886     ASSERT(count);
    887 
    888     JumpList bucketsOfFail;
    889 
    890     // Check eax is an object of the right Structure.
    891     bucketsOfFail.append(checkStructure(regT0, structure));
    892 
    893     Structure* currStructure = structure;
    894     WriteBarrier<Structure>* it = chain->head();
    895     JSObject* protoObject = 0;
    896     for (unsigned i = 0; i < count; ++i, ++it) {
    897         protoObject = asObject(currStructure->prototypeForLookup(callFrame));
    898         currStructure = it->get();
    899         testPrototype(protoObject, bucketsOfFail);
    900     }
    901     ASSERT(protoObject);
    902 
    903     bool needsStubLink = false;
    904     if (slot.cachedPropertyType() == PropertySlot::Getter) {
    905         needsStubLink = true;
    906         compileGetDirectOffset(protoObject, regT1, cachedOffset);
    907         JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
    908         stubCall.addArgument(regT1);
    909         stubCall.addArgument(regT0);
    910         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    911         stubCall.call();
    912     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
    913         needsStubLink = true;
    914         JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
    915         stubCall.addArgument(TrustedImmPtr(protoObject));
    916         stubCall.addArgument(TrustedImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
    917         stubCall.addArgument(TrustedImmPtr(const_cast<Identifier*>(&ident)));
    918         stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    919         stubCall.call();
    920     } else
    921         compileGetDirectOffset(protoObject, regT0, cachedOffset);
    922     Jump success = jump();
    923 
    924     LinkBuffer patchBuffer(*m_globalData, this);
    925934
    926935    if (needsStubLink) {
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r96238 r96527  
    701701    Jump failureCase = checkStructure(regT0, structure);
    702702    bool needsStubLink = false;
     703    bool isDirect = false;
    703704    if (slot.cachedPropertyType() == PropertySlot::Getter) {
    704705        needsStubLink = true;
     
    717718        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    718719        stubCall.call();
    719     } else
     720    } else {
     721        isDirect = true;
    720722        compileGetDirectOffset(regT0, regT1, regT0, cachedOffset);
     723    }
    721724
    722725    Jump success = jump();
     
    741744    CodeRef stubRoutine = patchBuffer.finalizeCode();
    742745
    743     polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubRoutine, structure);
     746    polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubRoutine, structure, isDirect);
    744747   
    745748    // Finally patch the jump to slow case back in the hot path to jump here instead.
     
    765768   
    766769    bool needsStubLink = false;
     770    bool isDirect = false;
    767771    if (slot.cachedPropertyType() == PropertySlot::Getter) {
    768772        needsStubLink = true;
     
    781785        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    782786        stubCall.call();
    783     } else
     787    } else {
     788        isDirect = true;
    784789        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     790    }
    785791   
    786792    Jump success = jump();
     
    803809    CodeRef stubRoutine = patchBuffer.finalizeCode();
    804810
    805     prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, prototypeStructure);
     811    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, prototypeStructure, isDirect);
    806812   
    807813    // Finally patch the jump to slow case back in the hot path to jump here instead.
     
    832838   
    833839    bool needsStubLink = false;
     840    bool isDirect = false;
    834841    if (slot.cachedPropertyType() == PropertySlot::Getter) {
    835842        needsStubLink = true;
     
    848855        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    849856        stubCall.call();
    850     } else
     857    } else {
     858        isDirect = true;
    851859        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     860    }
    852861
    853862    Jump success = jump();
     
    871880   
    872881    // Track the stub we have created so that it will be deleted later.
    873     prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain);
     882    prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain, isDirect);
    874883   
    875884    // Finally patch the jump to slow case back in the hot path to jump here instead.
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r96164 r96527  
    16991699        if (stubInfo->accessType == access_get_by_id_self) {
    17001700            ASSERT(!stubInfo->stubRoutine);
    1701             polymorphicStructureList = new PolymorphicAccessStructureList(callFrame->globalData(), codeBlock->ownerExecutable(), MacroAssemblerCodeRef(), stubInfo->u.getByIdSelf.baseObjectStructure.get());
     1701            polymorphicStructureList = new PolymorphicAccessStructureList(callFrame->globalData(), codeBlock->ownerExecutable(), MacroAssemblerCodeRef(), stubInfo->u.getByIdSelf.baseObjectStructure.get(), true);
    17021702            stubInfo->initGetByIdSelfList(polymorphicStructureList, 1);
    17031703        } else {
     
    17241724    switch (stubInfo->accessType) {
    17251725    case access_get_by_id_proto:
    1726         prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure.get(), stubInfo->u.getByIdProto.prototypeStructure.get());
     1726        prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure.get(), stubInfo->u.getByIdProto.prototypeStructure.get(), true);
    17271727        stubInfo->stubRoutine = MacroAssemblerCodeRef();
    17281728        stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
    17291729        break;
    17301730    case access_get_by_id_chain:
    1731         prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure.get(), stubInfo->u.getByIdChain.chain.get());
     1731        prototypeStructureList = new PolymorphicAccessStructureList(globalData, owner, stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure.get(), stubInfo->u.getByIdChain.chain.get(), true);
    17321732        stubInfo->stubRoutine = MacroAssemblerCodeRef();
    17331733        stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
Note: See TracChangeset for help on using the changeset viewer.