Changeset 125637 in webkit


Ignore:
Timestamp:
Aug 14, 2012 7:48:35 PM (12 years ago)
Author:
fpizlo@apple.com
Message:

Array checks should use the structure, not the class info
https://bugs.webkit.org/show_bug.cgi?id=93150

Reviewed by Mark Hahnenberg.

This changes all array checks used in array accesses (get, put, get length,
push, pop) to use the structure, not the class info. Additionally, these
checks in the LLInt and baseline JIT record the structure in an ArrayProfile,
so that the DFG can know exactly what structure to check for.

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Target.pri:
  • bytecode/ArrayProfile.cpp: Added.

(JSC):
(JSC::ArrayProfile::computeUpdatedPrediction):

  • bytecode/ArrayProfile.h: Added.

(JSC):
(JSC::arrayModeFromStructure):
(ArrayProfile):
(JSC::ArrayProfile::ArrayProfile):
(JSC::ArrayProfile::bytecodeOffset):
(JSC::ArrayProfile::addressOfLastSeenStructure):
(JSC::ArrayProfile::observeStructure):
(JSC::ArrayProfile::expectedStructure):
(JSC::ArrayProfile::structureIsPolymorphic):
(JSC::ArrayProfile::hasDefiniteStructure):
(JSC::ArrayProfile::observedArrayModes):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dump):
(JSC::CodeBlock::getArrayProfile):
(JSC):
(JSC::CodeBlock::getOrAddArrayProfile):
(JSC::CodeBlock::updateAllPredictionsAndCountLiveness):

  • bytecode/CodeBlock.h:

(JSC::CodeBlock::executionEntryCount):
(JSC::CodeBlock::numberOfArrayProfiles):
(JSC::CodeBlock::arrayProfiles):
(JSC::CodeBlock::addArrayProfile):
(CodeBlock):

  • bytecode/Instruction.h:

(JSC):
(JSC::Instruction::Instruction):

  • bytecode/Opcode.h:

(JSC):
(JSC::padOpcodeName):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitGetArgumentByVal):
(JSC::BytecodeGenerator::emitGetByVal):
(JSC::BytecodeGenerator::emitPutByVal):

  • dfg/DFGAbstractState.cpp:

(JSC::DFG::AbstractState::initialize):
(JSC::DFG::AbstractState::execute):

  • dfg/DFGAbstractValue.h:

(JSC::DFG::StructureAbstractValue::hasSingleton):
(StructureAbstractValue):
(JSC::DFG::StructureAbstractValue::singleton):

  • dfg/DFGArgumentsSimplificationPhase.cpp:

(JSC::DFG::ArgumentsSimplificationPhase::run):

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::speculateArray):
(DFG):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::checkArgumentTypes):
(JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):

  • dfg/DFGSpeculativeJIT.h:

(SpeculativeJIT):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • dfg/DFGStructureCheckHoistingPhase.cpp:

(JSC::DFG::StructureCheckHoistingPhase::run):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::privateCompilePatchGetArrayLength):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emit_op_get_by_val):
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::privateCompilePatchGetArrayLength):

  • llint/LLIntOffsetsExtractor.cpp:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/Structure.h:

(Structure):
(JSC::Structure::classInfoOffset):

Location:
trunk/Source/JavaScriptCore
Files:
2 added
30 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r124404 r125637  
    4040    assembler/LinkBuffer.cpp
    4141
     42    bytecode/ArrayProfile.cpp
    4243    bytecode/CallLinkInfo.cpp
    4344    bytecode/CallLinkStatus.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r125541 r125637  
     12012-08-13  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Array checks should use the structure, not the class info
     4        https://bugs.webkit.org/show_bug.cgi?id=93150
     5
     6        Reviewed by Mark Hahnenberg.
     7
     8        This changes all array checks used in array accesses (get, put, get length,
     9        push, pop) to use the structure, not the class info. Additionally, these
     10        checks in the LLInt and baseline JIT record the structure in an ArrayProfile,
     11        so that the DFG can know exactly what structure to check for.
     12       
     13        * CMakeLists.txt:
     14        * GNUmakefile.list.am:
     15        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
     16        * JavaScriptCore.xcodeproj/project.pbxproj:
     17        * Target.pri:
     18        * bytecode/ArrayProfile.cpp: Added.
     19        (JSC):
     20        (JSC::ArrayProfile::computeUpdatedPrediction):
     21        * bytecode/ArrayProfile.h: Added.
     22        (JSC):
     23        (JSC::arrayModeFromStructure):
     24        (ArrayProfile):
     25        (JSC::ArrayProfile::ArrayProfile):
     26        (JSC::ArrayProfile::bytecodeOffset):
     27        (JSC::ArrayProfile::addressOfLastSeenStructure):
     28        (JSC::ArrayProfile::observeStructure):
     29        (JSC::ArrayProfile::expectedStructure):
     30        (JSC::ArrayProfile::structureIsPolymorphic):
     31        (JSC::ArrayProfile::hasDefiniteStructure):
     32        (JSC::ArrayProfile::observedArrayModes):
     33        * bytecode/CodeBlock.cpp:
     34        (JSC::CodeBlock::dump):
     35        (JSC::CodeBlock::getArrayProfile):
     36        (JSC):
     37        (JSC::CodeBlock::getOrAddArrayProfile):
     38        (JSC::CodeBlock::updateAllPredictionsAndCountLiveness):
     39        * bytecode/CodeBlock.h:
     40        (JSC::CodeBlock::executionEntryCount):
     41        (JSC::CodeBlock::numberOfArrayProfiles):
     42        (JSC::CodeBlock::arrayProfiles):
     43        (JSC::CodeBlock::addArrayProfile):
     44        (CodeBlock):
     45        * bytecode/Instruction.h:
     46        (JSC):
     47        (JSC::Instruction::Instruction):
     48        * bytecode/Opcode.h:
     49        (JSC):
     50        (JSC::padOpcodeName):
     51        * bytecompiler/BytecodeGenerator.cpp:
     52        (JSC::BytecodeGenerator::emitGetArgumentByVal):
     53        (JSC::BytecodeGenerator::emitGetByVal):
     54        (JSC::BytecodeGenerator::emitPutByVal):
     55        * dfg/DFGAbstractState.cpp:
     56        (JSC::DFG::AbstractState::initialize):
     57        (JSC::DFG::AbstractState::execute):
     58        * dfg/DFGAbstractValue.h:
     59        (JSC::DFG::StructureAbstractValue::hasSingleton):
     60        (StructureAbstractValue):
     61        (JSC::DFG::StructureAbstractValue::singleton):
     62        * dfg/DFGArgumentsSimplificationPhase.cpp:
     63        (JSC::DFG::ArgumentsSimplificationPhase::run):
     64        * dfg/DFGByteCodeParser.cpp:
     65        (JSC::DFG::ByteCodeParser::parseBlock):
     66        * dfg/DFGFixupPhase.cpp:
     67        (JSC::DFG::FixupPhase::fixupNode):
     68        * dfg/DFGSpeculativeJIT.cpp:
     69        (JSC::DFG::SpeculativeJIT::speculateArray):
     70        (DFG):
     71        (JSC::DFG::SpeculativeJIT::compile):
     72        (JSC::DFG::SpeculativeJIT::checkArgumentTypes):
     73        (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
     74        * dfg/DFGSpeculativeJIT.h:
     75        (SpeculativeJIT):
     76        * dfg/DFGSpeculativeJIT32_64.cpp:
     77        (JSC::DFG::SpeculativeJIT::compile):
     78        * dfg/DFGSpeculativeJIT64.cpp:
     79        (JSC::DFG::SpeculativeJIT::compile):
     80        * dfg/DFGStructureCheckHoistingPhase.cpp:
     81        (JSC::DFG::StructureCheckHoistingPhase::run):
     82        * jit/JITPropertyAccess.cpp:
     83        (JSC::JIT::emit_op_get_by_val):
     84        (JSC::JIT::emit_op_put_by_val):
     85        (JSC::JIT::privateCompilePatchGetArrayLength):
     86        * jit/JITPropertyAccess32_64.cpp:
     87        (JSC::JIT::emit_op_get_by_val):
     88        (JSC::JIT::emit_op_put_by_val):
     89        (JSC::JIT::privateCompilePatchGetArrayLength):
     90        * llint/LLIntOffsetsExtractor.cpp:
     91        * llint/LowLevelInterpreter32_64.asm:
     92        * llint/LowLevelInterpreter64.asm:
     93        * runtime/Structure.h:
     94        (Structure):
     95        (JSC::Structure::classInfoOffset):
     96
    1972012-08-14  Gabor Ballabas  <gaborb@inf.u-szeged.hu>
    298
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r124757 r125637  
    8383        Source/JavaScriptCore/assembler/SH4Assembler.h \
    8484        Source/JavaScriptCore/assembler/X86Assembler.h \
     85        Source/JavaScriptCore/bytecode/ArrayProfile.cpp \
     86        Source/JavaScriptCore/bytecode/ArrayProfile.h \
    8587        Source/JavaScriptCore/bytecode/BytecodeConventions.h \
    8688        Source/JavaScriptCore/bytecode/CallLinkInfo.cpp \
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj

    r122544 r125637  
    15311531                        >
    15321532                        <File
     1533                                RelativePath="..\..\bytecode\ArrayProfile.cpp"
     1534                                >
     1535                        </File>
     1536                        <File
     1537                                RelativePath="..\..\bytecode\ArrayProfile.h"
     1538                                >
     1539                        </File>
     1540                        <File
    15331541                                RelativePath="..\..\bytecode\CallLinkInfo.cpp"
    15341542                                >
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r124404 r125637  
    141141                0F63943F15C75F19006A597C /* DFGStructureCheckHoistingPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
    142142                0F63944015C75F1D006A597C /* DFGStructureCheckHoistingPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */; };
     143                0F63945415D07055006A597C /* ArrayProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F63945115D07051006A597C /* ArrayProfile.cpp */; };
     144                0F63945515D07057006A597C /* ArrayProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F63945215D07051006A597C /* ArrayProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
    143145                0F66E16B14DF3F1600B7B2E4 /* DFGAdjacencyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */; settings = {ATTRIBUTES = (Private, ); }; };
    144146                0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    890892                0F63943C15C75F14006A597C /* DFGStructureCheckHoistingPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStructureCheckHoistingPhase.cpp; path = dfg/DFGStructureCheckHoistingPhase.cpp; sourceTree = "<group>"; };
    891893                0F63943D15C75F14006A597C /* DFGStructureCheckHoistingPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStructureCheckHoistingPhase.h; path = dfg/DFGStructureCheckHoistingPhase.h; sourceTree = "<group>"; };
     894                0F63945115D07051006A597C /* ArrayProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayProfile.cpp; sourceTree = "<group>"; };
     895                0F63945215D07051006A597C /* ArrayProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayProfile.h; sourceTree = "<group>"; };
    892896                0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAdjacencyList.h; path = dfg/DFGAdjacencyList.h; sourceTree = "<group>"; };
    893897                0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdge.h; path = dfg/DFGEdge.h; sourceTree = "<group>"; };
     
    24082412                        isa = PBXGroup;
    24092413                        children = (
     2414                                0F63945115D07051006A597C /* ArrayProfile.cpp */,
     2415                                0F63945215D07051006A597C /* ArrayProfile.h */,
    24102416                                0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */,
    24112417                                0F56A1D115000F31002992B1 /* ExecutionCounter.h */,
     
    28682874                                0F766D4615B3701F008F363E /* DFGScratchRegisterAllocator.h in Headers */,
    28692875                                0F63943F15C75F19006A597C /* DFGStructureCheckHoistingPhase.h in Headers */,
     2876                                0F63945515D07057006A597C /* ArrayProfile.h in Headers */,
    28702877                        );
    28712878                        runOnlyForDeploymentPostprocessing = 0;
     
    34663473                                0F766D3815AE4A1C008F363E /* StructureStubClearingWatchpoint.cpp in Sources */,
    34673474                                0F63944015C75F1D006A597C /* DFGStructureCheckHoistingPhase.cpp in Sources */,
     3475                                0F63945415D07055006A597C /* ArrayProfile.cpp in Sources */,
    34683476                        );
    34693477                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/JavaScriptCore/Target.pri

    r125452 r125637  
    4747    assembler/MacroAssemblerARM.cpp \
    4848    assembler/MacroAssemblerSH4.cpp \
     49    bytecode/ArrayProfile.cpp \
    4950    bytecode/CallLinkInfo.cpp \
    5051    bytecode/CallLinkStatus.cpp \
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r124729 r125637  
    11561156            dumpBytecodeCommentAndNewLine(location);
    11571157            it++;
     1158            it++;
    11581159            break;
    11591160        }
     
    11641165            dataLog("[%4d] get_argument_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
    11651166            dumpBytecodeCommentAndNewLine(location);
     1167            ++it;
    11661168            ++it;
    11671169            break;
     
    11841186            dataLog("[%4d] put_by_val\t %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
    11851187            dumpBytecodeCommentAndNewLine(location);
     1188            ++it;
    11861189            break;
    11871190        }
     
    27702773
    27712774#if ENABLE(VALUE_PROFILER)
     2775ArrayProfile* CodeBlock::getArrayProfile(unsigned bytecodeOffset)
     2776{
     2777    for (unsigned i = 0; i < m_arrayProfiles.size(); ++i) {
     2778        if (m_arrayProfiles[i].bytecodeOffset() == bytecodeOffset)
     2779            return &m_arrayProfiles[i];
     2780    }
     2781    return 0;
     2782}
     2783
     2784ArrayProfile* CodeBlock::getOrAddArrayProfile(unsigned bytecodeOffset)
     2785{
     2786    ArrayProfile* result = getArrayProfile(bytecodeOffset);
     2787    if (result)
     2788        return result;
     2789    return addArrayProfile(bytecodeOffset);
     2790}
     2791
    27722792void CodeBlock::updateAllPredictionsAndCountLiveness(
    27732793    OperationInProgress operation, unsigned& numberOfLiveNonArgumentValueProfiles, unsigned& numberOfSamplesInProfiles)
     
    27932813    m_lazyOperandValueProfiles.computeUpdatedPredictions(operation);
    27942814#endif
     2815   
     2816    // Don't count the array profiles towards statistics, since each array profile
     2817    // site also has a value profile site - so we already know whether or not it's
     2818    // live.
     2819    for (unsigned i = m_arrayProfiles.size(); i--;)
     2820        m_arrayProfiles[i].computeUpdatedPrediction(operation);
    27952821}
    27962822
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r123042 r125637  
    3131#define CodeBlock_h
    3232
     33#include "ArrayProfile.h"
    3334#include "BytecodeConventions.h"
    3435#include "CallLinkInfo.h"
     
    752753       
    753754        unsigned executionEntryCount() const { return m_executionEntryCount; }
    754 #endif
    755 
     755
     756        unsigned numberOfArrayProfiles() const { return m_arrayProfiles.size(); }
     757        const ArrayProfileVector& arrayProfiles() { return m_arrayProfiles; }
     758        ArrayProfile* addArrayProfile(unsigned bytecodeOffset)
     759        {
     760            m_arrayProfiles.append(ArrayProfile(bytecodeOffset));
     761            return &m_arrayProfiles.last();
     762        }
     763        ArrayProfile* getArrayProfile(unsigned bytecodeOffset);
     764        ArrayProfile* getOrAddArrayProfile(unsigned bytecodeOffset);
     765#endif
     766       
    756767        unsigned globalResolveInfoCount() const
    757768        {
     
    13341345        SegmentedVector<RareCaseProfile, 8> m_rareCaseProfiles;
    13351346        SegmentedVector<RareCaseProfile, 8> m_specialFastCaseProfiles;
     1347        ArrayProfileVector m_arrayProfiles;
    13361348        unsigned m_executionEntryCount;
    13371349#endif
  • trunk/Source/JavaScriptCore/bytecode/Instruction.h

    r122166 r125637  
    4747    // solution for now - will need to something smarter if/when we actually want mixed-mode operation.
    4848
     49    class ArrayProfile;
    4950    class JSCell;
    5051    class Structure;
     
    191192       
    192193        Instruction(ValueProfile* profile) { u.profile = profile; }
     194        Instruction(ArrayProfile* profile) { u.arrayProfile = profile; }
    193195       
    194196        Instruction(WriteBarrier<Unknown>* registerPointer) { u.registerPointer = registerPointer; }
     
    206208            LLIntCallLinkInfo* callLinkInfo;
    207209            ValueProfile* profile;
     210            ArrayProfile* arrayProfile;
    208211            void* pointer;
    209212            bool* predicatePointer;
  • trunk/Source/JavaScriptCore/bytecode/Opcode.h

    r124729 r125637  
    133133        macro(op_put_by_id_generic, 9) \
    134134        macro(op_del_by_id, 4) \
    135         macro(op_get_by_val, 5) /* has value profiling */ \
    136         macro(op_get_argument_by_val, 5) /* must be the same size as op_get_by_val */ \
     135        macro(op_get_by_val, 6) /* has value profiling */ \
     136        macro(op_get_argument_by_val, 6) /* must be the same size as op_get_by_val */ \
    137137        macro(op_get_by_pname, 7) \
    138         macro(op_put_by_val, 4) \
     138        macro(op_put_by_val, 5) \
    139139        macro(op_del_by_val, 4) \
    140140        macro(op_put_by_index, 4) \
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r124729 r125637  
    708708}
    709709#endif
     710
     711ArrayProfile* BytecodeGenerator::newArrayProfile()
     712{
     713#if ENABLE(VALUE_PROFILER)
     714    return m_codeBlock->addArrayProfile(instructions().size());
     715#else
     716    return 0;
     717#endif
     718}
    710719
    711720ValueProfile* BytecodeGenerator::emitProfiledOpcode(OpcodeID opcodeID)
     
    16701679RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
    16711680{
     1681    ArrayProfile* arrayProfile = newArrayProfile();
    16721682    ValueProfile* profile = emitProfiledOpcode(op_get_argument_by_val);
    16731683    instructions().append(dst->index());
     
    16751685    instructions().append(base->index());
    16761686    instructions().append(property->index());
     1687    instructions().append(arrayProfile);
    16771688    instructions().append(profile);
    16781689    return dst;
     
    16941705        }
    16951706    }
     1707    ArrayProfile* arrayProfile = newArrayProfile();
    16961708    ValueProfile* profile = emitProfiledOpcode(op_get_by_val);
    16971709    instructions().append(dst->index());
    16981710    instructions().append(base->index());
    16991711    instructions().append(property->index());
     1712    instructions().append(arrayProfile);
    17001713    instructions().append(profile);
    17011714    return dst;
     
    17041717RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* property, RegisterID* value)
    17051718{
     1719    ArrayProfile* arrayProfile = newArrayProfile();
    17061720    emitOpcode(op_put_by_val);
    17071721    instructions().append(base->index());
    17081722    instructions().append(property->index());
    17091723    instructions().append(value->index());
     1724    instructions().append(arrayProfile);
    17101725    return value;
    17111726}
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r124729 r125637  
    556556
    557557        void emitOpcode(OpcodeID);
     558        ArrayProfile* newArrayProfile();
    558559        ValueProfile* emitProfiledOpcode(OpcodeID);
    559560        void retrieveLastBinaryOp(int& dstIndex, int& src1Index, int& src2Index);
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp

    r124404 r125637  
    107107        if (isInt32Speculation(prediction))
    108108            root->valuesAtHead.argument(i).set(SpecInt32);
    109         else if (isArraySpeculation(prediction))
    110             root->valuesAtHead.argument(i).set(SpecArray);
    111109        else if (isBooleanSpeculation(prediction))
    112110            root->valuesAtHead.argument(i).set(SpecBoolean);
     
    291289        if (isInt32Speculation(predictedType))
    292290            speculateInt32Unary(node);
    293         else if (isArraySpeculation(predictedType)) {
    294             node.setCanExit(!isArraySpeculation(forNode(node.child1()).m_type));
    295             forNode(node.child1()).filter(SpecArray);
    296         } else if (isCellSpeculation(predictedType)) {
     291        else if (isCellSpeculation(predictedType)) {
    297292            node.setCanExit(!isCellSpeculation(forNode(node.child1()).m_type));
    298293            forNode(node.child1()).filter(SpecCell);
     
    868863            break;
    869864        }
    870         if (!isActionableArraySpeculation(m_graph[node.child1()].prediction()) || !m_graph[node.child2()].shouldSpeculateInteger()) {
     865        if (!m_graph[node.child2()].shouldSpeculateInteger() || (!node.child3() && !m_graph[node.child1()].shouldSpeculateArguments())) {
    871866            clobberWorld(node.codeOrigin, indexInBlock);
    872867            forNode(nodeIndex).makeTop();
     
    943938            break;
    944939        }
    945         ASSERT(m_graph[node.child1()].shouldSpeculateArray());
    946         forNode(node.child1()).filter(SpecArray);
     940        forNode(node.child1()).filter(SpecCell);
    947941        forNode(node.child2()).filter(SpecInt32);
    948942        forNode(nodeIndex).makeTop();
     
    10541048            break;
    10551049        }
    1056         ASSERT(m_graph[child1].shouldSpeculateArray());
    1057         forNode(child1).filter(SpecArray);
     1050        forNode(child1).filter(SpecCell);
    10581051        forNode(child2).filter(SpecInt32);
    10591052        if (node.op() == PutByValSafe)
     
    10641057    case ArrayPush:
    10651058        node.setCanExit(true);
    1066         forNode(node.child1()).filter(SpecArray);
     1059        forNode(node.child1()).filter(SpecCell);
    10671060        forNode(nodeIndex).set(SpecNumber);
    10681061        break;
     
    10701063    case ArrayPop:
    10711064        node.setCanExit(true);
    1072         forNode(node.child1()).filter(SpecArray);
     1065        forNode(node.child1()).filter(SpecCell);
    10731066        forNode(nodeIndex).makeTop();
    10741067        break;
     
    13551348    case GetArrayLength:
    13561349        node.setCanExit(true);
    1357         forNode(node.child1()).filter(SpecArray);
     1350        forNode(node.child1()).filter(SpecCell);
    13581351        forNode(nodeIndex).set(SpecInt32);
    13591352        break;
     
    14541447        break;
    14551448    case GetIndexedPropertyStorage: {
     1449        ASSERT(m_graph[node.child1()].prediction());
     1450        ASSERT(m_graph[node.child2()].shouldSpeculateInteger());
    14561451        node.setCanExit(true); // Lies, but this is (almost) always followed by GetByVal, which does exit. So no point in trying to be more precise.
    1457         SpeculatedType basePrediction = m_graph[node.child2()].prediction();
    1458         if (!(basePrediction & SpecInt32) && basePrediction) {
    1459             forNode(nodeIndex).clear();
    1460             break;
    1461         }
    14621452        if (m_graph[node.child1()].shouldSpeculateArguments()) {
    14631453            ASSERT_NOT_REACHED();
     
    15151505            break;
    15161506        }
    1517         forNode(node.child1()).filter(SpecArray);
     1507        forNode(node.child1()).filter(SpecCell);
    15181508        forNode(nodeIndex).clear();
    15191509        break;
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h

    r124404 r125637  
    283283    }
    284284   
     285    bool hasSingleton() const
     286    {
     287        return isNeitherClearNorTop();
     288    }
     289   
     290    Structure* singleton() const
     291    {
     292        ASSERT(isNeitherClearNorTop());
     293        return m_structure;
     294    }
     295   
    285296    bool operator==(const StructureAbstractValue& other) const
    286297    {
  • trunk/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp

    r121717 r125637  
    318318                    break;
    319319                   
     320                case CheckStructure:
     321                case StructureTransitionWatchpoint:
     322                    // We don't care about these because if we get uses of the relevant
     323                    // variable then we can safely get rid of these, too. This of course
     324                    // relies on there not being any information transferred by the CFA
     325                    // from a CheckStructure on one variable to the information about the
     326                    // structures of another variable.
     327                    break;
     328                   
    320329                default:
    321330                    observeBadArgumentsUses(node);
     
    472481                }
    473482                   
     483                case CheckStructure:
     484                case StructureTransitionWatchpoint: {
     485                    // We can just get rid of this node, if it references a phantom argument.
     486                    if (!isOKToOptimize(m_graph[node.child1()]))
     487                        break;
     488                    m_graph.deref(node.child1());
     489                    node.setOpAndDefaultFlags(Phantom);
     490                    node.children.setChild1(Edge());
     491                    break;
     492                }
     493                   
    474494                case GetByVal: {
    475495                    if (!node.prediction()
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r124667 r125637  
    21502150            NodeIndex base = get(currentInstruction[2].u.operand);
    21512151            NodeIndex property = get(currentInstruction[3].u.operand);
     2152            ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     2153            profile->computeUpdatedPrediction();
     2154            if (profile->hasDefiniteStructure())
     2155                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(profile->expectedStructure())), base);
    21522156            NodeIndex propertyStorage = addToGraph(GetIndexedPropertyStorage, base, property);
    21532157            NodeIndex getByVal = addToGraph(GetByVal, OpInfo(0), OpInfo(prediction), base, property, propertyStorage);
     
    21612165            NodeIndex property = get(currentInstruction[2].u.operand);
    21622166            NodeIndex value = get(currentInstruction[3].u.operand);
     2167           
     2168            ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
     2169            profile->computeUpdatedPrediction();
     2170            if (profile->hasDefiniteStructure())
     2171                addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(profile->expectedStructure())), base);
     2172
     2173#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
     2174            dataLog("Slow case profile for bc#%u: %u\n", m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter);
     2175#endif
    21632176
    21642177            bool makeSafe =
  • trunk/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp

    r122541 r125637  
    614614                ASSERT(node.shouldGenerate());
    615615                Node& possibleLocalOp = m_graph[node.child1()];
    616                 if (possibleLocalOp.hasLocal() && !possibleLocalOp.variableAccessData()->isCaptured()) {
     616                if (possibleLocalOp.op() != GetLocal
     617                    && possibleLocalOp.hasLocal()
     618                    && !possibleLocalOp.variableAccessData()->isCaptured()) {
    617619                    NodeIndex setLocalIndex =
    618620                        firstBlock->variablesAtTail.operand(possibleLocalOp.local());
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r122541 r125637  
    104104               
    105105            m_state.execute(indexInBlock);
    106             if (!node.shouldGenerate()
    107                 || m_state.didClobber()
    108                 || node.hasConstant())
     106            if (!node.shouldGenerate() || m_state.didClobber() || node.hasConstant())
    109107                continue;
    110108            JSValue value = m_state.forNode(nodeIndex).value();
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r124398 r125637  
    9797            dataLog("  @%u -> %s", m_compileIndex, isArray ? "GetArrayLength" : "GetStringLength");
    9898#endif
    99             if (isArray)
     99            if (isArray) {
    100100                node.setOp(GetArrayLength);
    101             else if (isArguments)
     101                ASSERT(node.flags() & NodeMustGenerate);
     102                node.clearFlags(NodeMustGenerate);
     103                m_graph.deref(m_compileIndex);
     104               
     105                ArrayProfile* arrayProfile =
     106                    m_graph.baselineCodeBlockFor(node.codeOrigin)->getArrayProfile(
     107                        node.codeOrigin.bytecodeIndex);
     108                if (!arrayProfile)
     109                    break;
     110                arrayProfile->computeUpdatedPrediction();
     111                if (!arrayProfile->hasDefiniteStructure())
     112                    break;
     113                m_graph.ref(node.child1());
     114                Node checkStructure(CheckStructure, node.codeOrigin, OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())), node.child1().index());
     115                checkStructure.ref();
     116                NodeIndex checkStructureIndex = m_graph.size();
     117                m_graph.append(checkStructure);
     118                m_insertionSet.append(m_indexInBlock, checkStructureIndex);
     119                break;
     120            }
     121            if (isArguments)
    102122                node.setOp(GetArgumentsLength);
    103123            else if (isString)
     
    130150        }
    131151        case GetIndexedPropertyStorage: {
    132             SpeculatedType basePrediction = m_graph[node.child2()].prediction();
    133             if ((!(basePrediction & SpecInt32) && basePrediction)
    134                 || m_graph[node.child1()].shouldSpeculateArguments()
    135                 || !isActionableArraySpeculation(m_graph[node.child1()].prediction())) {
     152            if (!m_graph[node.child1()].prediction()
     153                || !m_graph[node.child2()].shouldSpeculateInteger()
     154                || m_graph[node.child1()].shouldSpeculateArguments()) {
    136155                node.setOpAndDefaultFlags(Nop);
    137156                m_graph.clearAndDerefChild1(node);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r124476 r125637  
    156156
    157157    Node* nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1));
     158    if (nextNode->op() == Jump && nextNode->codeOrigin == at(m_compileIndex).codeOrigin) {
     159        // We're at an inlined return. Use a backward speculation instead.
     160        return;
     161    }
    158162    ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin);
    159163       
     
    245249    m_gprs = RegisterBank<GPRInfo>();
    246250    m_fprs = RegisterBank<FPRInfo>();
     251}
     252
     253void SpeculativeJIT::speculateArray(Edge edge, GPRReg baseReg)
     254{
     255    AbstractValue& arrayValue = m_state.forNode(edge);
     256    if (arrayValue.m_structure.hasSingleton()
     257        && arrayValue.m_structure.singleton()->classInfo() == &JSArray::s_info)
     258        return;
     259   
     260    GPRTemporary temp(this);
     261    m_jit.loadPtr(
     262        MacroAssembler::Address(baseReg, JSCell::structureOffset()), temp.gpr());
     263    speculationCheck(
     264        Uncountable, JSValueRegs(), NoNode,
     265        m_jit.branchPtr(
     266            MacroAssembler::NotEqual,
     267            MacroAssembler::Address(temp.gpr(), Structure::classInfoOffset()),
     268            MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
    247269}
    248270
     
    12211243                        else if (isInt32Speculation(argumentPosition.prediction()))
    12221244                            valueSource = ValueSource(Int32InRegisterFile);
    1223                         else if (isArraySpeculation(argumentPosition.prediction()) || isCellSpeculation(argumentPosition.prediction()))
     1245                        else if (isCellSpeculation(argumentPosition.prediction()))
    12241246                            valueSource = ValueSource(CellInRegisterFile);
    12251247                        else if (isBooleanSpeculation(argumentPosition.prediction()))
     
    13441366        if (isInt32Speculation(predictedType))
    13451367            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
    1346         else if (isArraySpeculation(predictedType)) {
    1347             GPRTemporary temp(this);
    1348             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
    1349             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
    1350             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
    1351         } else if (isBooleanSpeculation(predictedType)) {
     1368        else if (isBooleanSpeculation(predictedType)) {
    13521369            GPRTemporary temp(this);
    13531370            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
     
    14041421        if (isInt32Speculation(predictedType))
    14051422            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
    1406         else if (isArraySpeculation(predictedType)) {
    1407             GPRTemporary temp(this);
    1408             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
    1409             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
    1410             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
    1411             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
    1412         } else if (isBooleanSpeculation(predictedType))
     1423        else if (isBooleanSpeculation(predictedType))
    14131424            speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
    14141425        else if (isInt8ArraySpeculation(predictedType)) {
     
    15921603
    15931604    if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) {
    1594         ASSERT(!(at(node.child1()).prediction() & SpecString));
    15951605        terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
    15961606        noResult(m_compileIndex);
     
    30383048void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
    30393049{
    3040     if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) {
    3041         terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
    3042         return;
    3043     }
     3050    ASSERT(at(node.child1()).prediction());
     3051    ASSERT(at(node.child2()).shouldSpeculateInteger());
    30443052       
    30453053    SpeculateCellOperand base(this, node.child1());
    30463054    GPRReg baseReg = base.gpr();
    3047    
    3048     SpeculatedType basePrediction = at(node.child2()).prediction();
    3049     if (!(basePrediction & SpecInt32) && basePrediction) {
    3050         ASSERT_NOT_REACHED();
    3051         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
    3052         noResult(m_compileIndex);
    3053         return;
    3054     }
    30553055   
    30563056    GPRTemporary storage(this);
     
    31143114        m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
    31153115    } else {
    3116         if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
    3117             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
     3116        speculateArray(node.child1(), baseReg);
    31183117        m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
    31193118    }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r124422 r125637  
    21922192    void terminateSpeculativeExecutionWithConditionalDirection(ExitKind, JSValueRegs, NodeIndex, bool isForward);
    21932193   
     2194    void speculateArray(Edge baseEdge, GPRReg baseReg);
     2195   
    21942196    template<bool strict>
    21952197    GPRReg fillSpeculateIntInternal(NodeIndex, DataFormat& returnFormat);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r124476 r125637  
    19191919            }
    19201920
    1921             if (isArraySpeculation(value.m_type) || isCellSpeculation(value.m_type)) {
     1921            if (isCellSpeculation(value.m_type)) {
    19221922                GPRTemporary result(this);
    19231923                m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
     
    20372037                break;
    20382038            }
    2039             if (isArraySpeculation(predictedType)) {
    2040                 SpeculateCellOperand cell(this, node.child1());
    2041                 GPRReg cellGPR = cell.gpr();
    2042                 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
    2043                     speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
    2044                 m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local()));
    2045                 noResult(m_compileIndex);
    2046                 recordSetLocal(node.local(), ValueSource(CellInRegisterFile));
    2047                 break;
    2048             }
    20492039            if (isCellSpeculation(predictedType)) {
    20502040                SpeculateCellOperand cell(this, node.child1());
     
    23572347        }
    23582348       
    2359         if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArraySpeculation(at(node.child1()).prediction())) {
     2349        if (!at(node.child2()).shouldSpeculateInteger() || (!node.child3() && !at(node.child1()).shouldSpeculateArguments())) {
    23602350            SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right.
    23612351            JSValueOperand property(this, node.child2());
     
    24502440        }
    24512441       
    2452         ASSERT(at(node.child1()).shouldSpeculateArray());
    2453 
    24542442        SpeculateStrictInt32Operand property(this, node.child2());
    24552443        StorageOperand storage(this, node.child3());
     
    24652453            SpeculateCellOperand base(this, node.child1());
    24662454            GPRReg baseReg = base.gpr();
    2467             if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
    2468                 speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
     2455            // We've already speculated that it's some kind of array, at this point.
    24692456            speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
    24702457        }
     
    24732460        GPRTemporary resultPayload(this);
    24742461
    2475         // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache
    2476         // the storage pointer - especially if there happens to be another register free right now. If we do so,
    2477         // then we'll need to allocate a new temporary for result.
    24782462        m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
    24792463        speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag)));
     
    24962480       
    24972481        if (!at(child2).shouldSpeculateInteger()
    2498             || !isActionableMutableArraySpeculation(at(child1).prediction())
    24992482            || at(child1).shouldSpeculateArguments()) {
    25002483            SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right.
     
    25792562        }
    25802563       
    2581         ASSERT(at(child1).shouldSpeculateArray());
    2582 
    25832564        JSValueOperand value(this, child3);
    2584         GPRTemporary scratch(this);
    2585 
    25862565        // Map base, property & value into registers, allocate a scratch register.
    25872566        GPRReg baseReg = base.gpr();
     
    25892568        GPRReg valueTagReg = value.tagGPR();
    25902569        GPRReg valuePayloadReg = value.payloadGPR();
    2591         GPRReg scratchReg = scratch.gpr();
    25922570       
    25932571        if (!m_compileOkay)
    25942572            return;
    2595        
    2596         writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratchReg);
    2597 
    2598         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
    2599         // If we have predicted the base to be type array, we can skip the check.
    2600         if (!isArraySpeculation(m_state.forNode(child1).m_type))
    2601             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), child1, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
     2573
     2574        {
     2575            GPRTemporary scratch(this);
     2576            GPRReg scratchReg = scratch.gpr();
     2577            writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratchReg);
     2578        }
     2579
     2580        speculateArray(child1, baseReg);
    26022581
    26032582        MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
     
    26102589       
    26112590        // Get the array storage.
    2612         GPRReg storageReg = scratchReg;
     2591        GPRTemporary storage(this);
     2592        GPRReg storageReg = storage.gpr();
    26132593        m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
    26142594
     
    27962776        SpeculateCellOperand base(this, node.child1());
    27972777        JSValueOperand value(this, node.child2());
    2798         GPRTemporary storage(this);
    27992778        GPRTemporary storageLength(this);
    28002779       
     
    28022781        GPRReg valueTagGPR = value.tagGPR();
    28032782        GPRReg valuePayloadGPR = value.payloadGPR();
     2783        GPRReg storageLengthGPR = storageLength.gpr();
     2784       
     2785        {
     2786            GPRTemporary scratch(this);
     2787            writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
     2788        }
     2789
     2790        speculateArray(node.child1(), baseGPR);
     2791       
     2792        GPRTemporary storage(this);
    28042793        GPRReg storageGPR = storage.gpr();
    2805         GPRReg storageLengthGPR = storageLength.gpr();
    2806        
    2807         writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
    2808 
    2809         if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
    2810             speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
    2811        
     2794
    28122795        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
    28132796        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
     
    28452828        GPRReg storageLengthGPR = storageLength.gpr();
    28462829       
    2847         if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
    2848             speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
     2830        speculateArray(node.child1(), baseGPR);
    28492831       
    28502832        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
     
    33963378        GPRReg baseGPR = base.gpr();
    33973379       
    3398         if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
    3399             speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
     3380        speculateArray(node.child1(), baseGPR);
    34003381       
    34013382        GPRTemporary result(this);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r124555 r125637  
    20732073                break;
    20742074            }
    2075             if (isArraySpeculation(predictedType)) {
    2076                 SpeculateCellOperand cell(this, node.child1());
    2077                 GPRReg cellGPR = cell.gpr();
    2078                 if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
    2079                     speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
    2080                 m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
    2081                 noResult(m_compileIndex);
    2082                 recordSetLocal(node.local(), ValueSource(CellInRegisterFile));
    2083                 break;
    2084             }
    20852075            if (isCellSpeculation(predictedType)) {
    20862076                SpeculateCellOperand cell(this, node.child1());
     
    23902380        }
    23912381       
    2392         if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArraySpeculation(at(node.child1()).prediction())) {
     2382        if (!at(node.child2()).shouldSpeculateInteger() || (!node.child3() && !at(node.child1()).shouldSpeculateArguments())) {
    23932383            JSValueOperand base(this, node.child1());
    23942384            JSValueOperand property(this, node.child2());
     
    24812471        }
    24822472       
    2483         ASSERT(at(node.child1()).shouldSpeculateArray());
    2484 
    24852473        SpeculateCellOperand base(this, node.child1());
    24862474        SpeculateStrictInt32Operand property(this, node.child2());
     
    24942482            return;
    24952483
    2496         if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
    2497             speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
     2484        // We will have already speculated that the base is some kind of array,
     2485        // at this point.
     2486       
    24982487        speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
    24992488
    2500         // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache
    2501         // the storage pointer - especially if there happens to be another register free right now. If we do so,
    2502         // then we'll need to allocate a new temporary for result.
    25032489        GPRTemporary result(this);
    25042490        m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
     
    25202506        }
    25212507       
    2522         if (!at(child2).shouldSpeculateInteger() || !isActionableMutableArraySpeculation(at(child1).prediction())) {
     2508        if (!at(child2).shouldSpeculateInteger()) {
    25232509            JSValueOperand arg1(this, child1);
    25242510            JSValueOperand arg2(this, child2);
     
    25382524        SpeculateStrictInt32Operand property(this, child2);
    25392525        if (at(child1).shouldSpeculateArguments()) {
     2526            dataLog(" in here ");
    25402527            JSValueOperand value(this, child3);
    2541             SpeculateCellOperand base(this, child1);
    2542             SpeculateStrictInt32Operand property(this, child2);
    25432528            GPRTemporary scratch(this);
    25442529            GPRTemporary scratch2(this);
     
    26572642        }
    26582643           
    2659         ASSERT(at(child1).shouldSpeculateArray());
    2660 
    26612644        JSValueOperand value(this, child3);
    26622645        GPRTemporary scratch(this);
     
    26732656        writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratchReg);
    26742657
    2675         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
    2676         // If we have predicted the base to be type array, we can skip the check.
    2677         if (!isArraySpeculation(m_state.forNode(child1).m_type))
    2678             speculationCheck(BadType, JSValueRegs(baseReg), child1, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
    2679        
     2658        speculateArray(child1, baseReg);
     2659
    26802660        MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
    26812661        if (node.op() == PutByVal)
     
    28802860        writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
    28812861
    2882         if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
    2883             speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
    2884        
     2862        speculateArray(node.child1(), baseGPR);
     2863
    28852864        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
    28862865        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
     
    29182897        GPRReg storageLengthGPR = storageLength.gpr();
    29192898       
    2920         if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
    2921             speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
    2922        
     2899        speculateArray(node.child1(), baseGPR);
     2900
    29232901        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
    29242902        m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
     
    34163394        GPRReg resultGPR = result.gpr();
    34173395       
    3418         if (!isArraySpeculation(m_state.forNode(node.child1()).m_type))
    3419             speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
    3420        
     3396        speculateArray(node.child1(), baseGPR);
     3397
    34213398        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
    34223399        m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR);
  • trunk/Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp

    r124655 r125637  
    9595                case ReallocatePropertyStorage:
    9696                case GetPropertyStorage:
     97                case GetByVal:
     98                case PutByVal:
     99                case PutByValAlias:
     100                case GetArrayLength:
     101                case Phantom:
    97102                    // Don't count these uses.
    98103                    break;
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r124476 r125637  
    111111
    112112    emitJumpSlowCaseIfNotJSCell(regT0, base);
    113     addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
     113    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
     114    storePtr(regT2, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure());
     115    addSlowCase(branchPtr(NotEqual, Address(regT2, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
    114116
    115117    loadPtr(Address(regT0, JSArray::storageOffset()), regT2);
     
    232234    zeroExtend32ToPtr(regT1, regT1);
    233235    emitJumpSlowCaseIfNotJSCell(regT0, base);
    234     addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
     236    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
     237    storePtr(regT2, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure());
     238    addSlowCase(branchPtr(NotEqual, Address(regT2, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
    235239    addSlowCase(branch32(AboveOrEqual, regT1, Address(regT0, JSArray::vectorLengthOffset())));
    236240
     
    646650
    647651    // Check eax is an array
    648     Jump failureCases1 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info));
     652    loadPtr(Address(regT0, JSCell::structureOffset()), regT3);
     653    storePtr(regT3, m_codeBlock->getOrAddArrayProfile(stubInfo->bytecodeIndex)->addressOfLastSeenStructure());
     654    Jump failureCases1 = branchPtr(NotEqual, Address(regT3, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info));
    649655
    650656    // Checks out okay! - get the length from the storage
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r124476 r125637  
    210210    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
    211211    emitJumpSlowCaseIfNotJSCell(base, regT1);
    212     addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
     212    loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
     213    storePtr(regT1, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure());
     214    addSlowCase(branchPtr(NotEqual, Address(regT1, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
    213215   
    214216    loadPtr(Address(regT0, JSArray::storageOffset()), regT3);
     
    265267    addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
    266268    emitJumpSlowCaseIfNotJSCell(base, regT1);
    267     addSlowCase(branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
     269    loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
     270    storePtr(regT1, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure());
     271    addSlowCase(branchPtr(NotEqual, Address(regT1, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info)));
    268272    addSlowCase(branch32(AboveOrEqual, regT2, Address(regT0, JSArray::vectorLengthOffset())));
    269273
     
    609613   
    610614    // Check for array
    611     Jump failureCases1 = branchPtr(NotEqual, Address(regT0, JSCell::classInfoOffset()), TrustedImmPtr(&JSArray::s_info));
     615    loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
     616    storePtr(regT2, m_codeBlock->getOrAddArrayProfile(stubInfo->bytecodeIndex)->addressOfLastSeenStructure());
     617    Jump failureCases1 = branchPtr(NotEqual, Address(regT2, Structure::classInfoOffset()), TrustedImmPtr(&JSArray::s_info));
    612618   
    613619    // Checks out okay! - get the length from the storage
  • trunk/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp

    r109678 r125637  
    2626#include "config.h"
    2727
     28#include "ArrayProfile.h"
    2829#include "CodeBlock.h"
    2930#include "Executable.h"
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r123417 r125637  
    12561256_llint_op_get_by_val:
    12571257    traceExecution()
    1258     loadp CodeBlock[cfr], t1
    12591258    loadi 8[PC], t2
    12601259    loadi 12[PC], t3
    1261     loadp CodeBlock::m_globalData[t1], t1
    12621260    loadConstantOrVariablePayload(t2, CellTag, t0, .opGetByValSlow)
    1263     loadp JSGlobalData::jsArrayClassInfo[t1], t2
    12641261    loadConstantOrVariablePayload(t3, Int32Tag, t1, .opGetByValSlow)
    1265     bpneq [t0], t2, .opGetByValSlow
     1262    loadp JSCell::m_structure[t0], t3
     1263    loadp 16[PC], t2
     1264    storep t3, ArrayProfile::m_lastSeenStructure[t2]
     1265    loadp CodeBlock[cfr], t2
     1266    loadp CodeBlock::m_globalData[t2], t2
     1267    loadp JSGlobalData::jsArrayClassInfo[t2], t2
     1268    bpneq Structure::m_classInfo[t3], t2, .opGetByValSlow
    12661269    loadp JSArray::m_storage[t0], t3
    12671270    biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow
     
    12721275    storei t2, TagOffset[cfr, t0, 8]
    12731276    storei t1, PayloadOffset[cfr, t0, 8]
    1274     loadi 16[PC], t0
     1277    loadi 20[PC], t0
    12751278    valueProfile(t2, t1, t0)
    1276     dispatch(5)
     1279    dispatch(6)
    12771280
    12781281.opGetByValSlow:
    12791282    callSlowPath(_llint_slow_path_get_by_val)
    1280     dispatch(5)
     1283    dispatch(6)
    12811284
    12821285
    12831286_llint_op_get_argument_by_val:
     1287    # FIXME: At some point we should array profile this. Right now it isn't necessary
     1288    # since the DFG will never turn a get_argument_by_val into a GetByVal.
    12841289    traceExecution()
    12851290    loadi 8[PC], t0
     
    12941299    loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0
    12951300    loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t1
    1296     loadi 16[PC], t2
     1301    loadi 20[PC], t2
    12971302    storei t0, TagOffset[cfr, t3, 8]
    12981303    storei t1, PayloadOffset[cfr, t3, 8]
    12991304    valueProfile(t0, t1, t2)
    1300     dispatch(5)
     1305    dispatch(6)
    13011306
    13021307.opGetArgumentByValSlow:
    13031308    callSlowPath(_llint_slow_path_get_argument_by_val)
    1304     dispatch(5)
     1309    dispatch(6)
    13051310
    13061311
     
    13391344    loadi 8[PC], t0
    13401345    loadConstantOrVariablePayload(t0, Int32Tag, t2, .opPutByValSlow)
     1346    loadp JSCell::m_structure[t1], t3
     1347    loadp 16[PC], t0
     1348    storep t3, ArrayProfile::m_lastSeenStructure[t0]
    13411349    loadp CodeBlock[cfr], t0
    13421350    loadp CodeBlock::m_globalData[t0], t0
    13431351    loadp JSGlobalData::jsArrayClassInfo[t0], t0
    1344     bpneq [t1], t0, .opPutByValSlow
     1352    bpneq Structure::m_classInfo[t3], t0, .opPutByValSlow
    13451353    biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow
    13461354    loadp JSArray::m_storage[t1], t0
     
    13521360    storei t1, ArrayStorage::m_vector + TagOffset[t0, t2, 8]
    13531361    storei t3, ArrayStorage::m_vector + PayloadOffset[t0, t2, 8]
    1354     dispatch(4)
     1362    dispatch(5)
    13551363
    13561364.opPutByValEmpty:
     
    13631371.opPutByValSlow:
    13641372    callSlowPath(_llint_slow_path_put_by_val)
    1365     dispatch(4)
     1373    dispatch(5)
    13661374
    13671375
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r123417 r125637  
    11001100_llint_op_get_by_val:
    11011101    traceExecution()
    1102     loadp CodeBlock[cfr], t1
    11031102    loadis 16[PB, PC, 8], t2
    11041103    loadis 24[PB, PC, 8], t3
    1105     loadp CodeBlock::m_globalData[t1], t1
    11061104    loadConstantOrVariableCell(t2, t0, .opGetByValSlow)
    1107     loadp JSGlobalData::jsArrayClassInfo[t1], t2
    11081105    loadConstantOrVariableInt32(t3, t1, .opGetByValSlow)
    11091106    sxi2p t1, t1
    1110     bpneq [t0], t2, .opGetByValSlow
     1107    loadp JSCell::m_structure[t0], t3
     1108    loadp 32[PB, PC, 8], t2
     1109    storep t3, ArrayProfile::m_lastSeenStructure[t2]
     1110    loadp CodeBlock[cfr], t2
     1111    loadp CodeBlock::m_globalData[t2], t2
     1112    loadp JSGlobalData::jsArrayClassInfo[t2], t2
     1113    bpneq Structure::m_classInfo[t3], t2, .opGetByValSlow
    11111114    loadp JSArray::m_storage[t0], t3
    11121115    biaeq t1, JSArray::m_vectorLength[t0], .opGetByValSlow
     
    11151118    btpz t2, .opGetByValSlow
    11161119    storep t2, [cfr, t0, 8]
    1117     loadp 32[PB, PC, 8], t0
     1120    loadp 40[PB, PC, 8], t0
    11181121    valueProfile(t2, t0)
    1119     dispatch(5)
     1122    dispatch(6)
    11201123
    11211124.opGetByValSlow:
    11221125    callSlowPath(_llint_slow_path_get_by_val)
    1123     dispatch(5)
     1126    dispatch(6)
    11241127
    11251128
    11261129_llint_op_get_argument_by_val:
     1130    # FIXME: At some point we should array profile this. Right now it isn't necessary
     1131    # since the DFG will never turn a get_argument_by_val into a GetByVal.
    11271132    traceExecution()
    11281133    loadis 16[PB, PC, 8], t0
     
    11401145    storep t0, [cfr, t3, 8]
    11411146    valueProfile(t0, t1)
    1142     dispatch(5)
     1147    dispatch(6)
    11431148
    11441149.opGetArgumentByValSlow:
    11451150    callSlowPath(_llint_slow_path_get_argument_by_val)
    1146     dispatch(5)
     1151    dispatch(6)
    11471152
    11481153
     
    11831188    loadConstantOrVariableInt32(t0, t2, .opPutByValSlow)
    11841189    sxi2p t2, t2
     1190    loadp JSCell::m_structure[t1], t3
     1191    loadp 32[PB, PC, 8], t0
     1192    storep t3, ArrayProfile::m_lastSeenStructure[t0]
    11851193    loadp CodeBlock[cfr], t0
    11861194    loadp CodeBlock::m_globalData[t0], t0
    11871195    loadp JSGlobalData::jsArrayClassInfo[t0], t0
    1188     bpneq [t1], t0, .opPutByValSlow
     1196    bpneq Structure::m_classInfo[t3], t0, .opPutByValSlow
    11891197    biaeq t2, JSArray::m_vectorLength[t1], .opPutByValSlow
    11901198    loadp JSArray::m_storage[t1], t0
     
    11951203    writeBarrier(t1)
    11961204    storep t1, ArrayStorage::m_vector[t0, t2, 8]
    1197     dispatch(4)
     1205    dispatch(5)
    11981206
    11991207.opPutByValEmpty:
     
    12061214.opPutByValSlow:
    12071215    callSlowPath(_llint_slow_path_put_by_val)
    1208     dispatch(4)
     1216    dispatch(5)
    12091217
    12101218
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r124355 r125637  
    323323            return OBJECT_OFFSETOF(Structure, m_typeInfo) + TypeInfo::typeOffset();
    324324        }
     325       
     326        static ptrdiff_t classInfoOffset()
     327        {
     328            return OBJECT_OFFSETOF(Structure, m_classInfo);
     329        }
    325330
    326331        static Structure* createStructure(JSGlobalData&);
Note: See TracChangeset for help on using the changeset viewer.