Changeset 95273 in webkit


Ignore:
Timestamp:
Sep 15, 2011 11:33:55 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG JIT does not optimize method_check
https://bugs.webkit.org/show_bug.cgi?id=68215

Reviewed by Oliver Hunt.

MethodCallLinkInfo and StructureStubInfo are now searchable by
bytecodeIndex, so that DFG::ByteCodeParser can use that information
to determine how to optimize GetMethod.

A new node op has been added to DFG: CheckMethod. This is a variant
of GetMethod that has been optimized for the case that GetMethod
always takes the fast path. CheckMethod results in only a very
small amount of code (two loads and two branches in the worst case,
one load and one branch in the best case). CheckMethod behaves as
if it were a constant.

Introduced the notion that a DFG node that is not JSConstant
behaves as a constant. CheckMethod uses this functionality.

This is a 3% speed-up on Kraken, and a small speed-up on V8.
Appears to be neutral on SunSpider.

  • bytecode/CodeBlock.h:

(JSC::getStructureStubInfoBytecodeIndex):
(JSC::getMethodCallLinkInfoBytecodeIndex):

  • bytecode/PredictedType.cpp:

(JSC::predictionFromCell):
(JSC::predictionFromValue):

  • bytecode/PredictedType.h:
  • bytecode/StructureStubInfo.h:
  • dfg/DFGAliasTracker.h:

(JSC::DFG::AliasTracker::recordGetMethod):

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGGraph.cpp:

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

  • dfg/DFGGraph.h:

(JSC::DFG::Graph::getMethodCheckPrediction):
(JSC::DFG::Graph::getPrediction):
(JSC::DFG::Graph::isConstant):
(JSC::DFG::Graph::isJSConstant):
(JSC::DFG::Graph::valueOfJSConstant):
(JSC::DFG::Graph::valueOfInt32Constant):
(JSC::DFG::Graph::valueOfNumberConstant):
(JSC::DFG::Graph::valueOfBooleanConstant):
(JSC::DFG::Graph::valueOfJSConstantNode):

  • dfg/DFGJITCodeGenerator.cpp:

(JSC::DFG::JITCodeGenerator::fillInteger):
(JSC::DFG::JITCodeGenerator::fillDouble):
(JSC::DFG::JITCodeGenerator::fillJSValue):
(JSC::DFG::JITCodeGenerator::isKnownNotInteger):
(JSC::DFG::JITCodeGenerator::isKnownNotNumber):

  • dfg/DFGJITCodeGenerator.h:

(JSC::DFG::JITCodeGenerator::silentSpillFPR):
(JSC::DFG::JITCodeGenerator::silentFillGPR):
(JSC::DFG::JITCodeGenerator::silentFillFPR):

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::fillNumericToDouble):
(JSC::DFG::JITCompiler::fillInt32ToInteger):
(JSC::DFG::JITCompiler::fillToJS):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasConstant):
(JSC::DFG::Node::hasIdentifier):
(JSC::DFG::Node::hasMethodCheckData):
(JSC::DFG::Node::methodCheckDataIndex):
(JSC::DFG::Node::valueOfJSConstant):

  • dfg/DFGPropagator.cpp:

(JSC::DFG::Propagator::propagateNode):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
(JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
(JSC::DFG::SpeculativeJIT::compile):

  • jit/JIT.cpp:

(JSC::JIT::privateCompile):

  • jit/JIT.h:

(JSC::PropertyStubCompilationInfo::PropertyStubCompilationInfo):
(JSC::MethodCallCompilationInfo::MethodCallCompilationInfo):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_method_check):
(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::emit_op_put_by_id):

  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::emit_op_method_check):
(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::emit_op_put_by_id):

  • runtime/JSCell.h:

(JSC::JSCell::JSCell::structureAddress):

Location:
trunk/Source/JavaScriptCore
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r95271 r95273  
     12011-09-15  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG JIT does not optimize method_check
     4        https://bugs.webkit.org/show_bug.cgi?id=68215
     5
     6        Reviewed by Oliver Hunt.
     7       
     8        MethodCallLinkInfo and StructureStubInfo are now searchable by
     9        bytecodeIndex, so that DFG::ByteCodeParser can use that information
     10        to determine how to optimize GetMethod.
     11       
     12        A new node op has been added to DFG: CheckMethod. This is a variant
     13        of GetMethod that has been optimized for the case that GetMethod
     14        always takes the fast path. CheckMethod results in only a very
     15        small amount of code (two loads and two branches in the worst case,
     16        one load and one branch in the best case). CheckMethod behaves as
     17        if it were a constant. 
     18       
     19        Introduced the notion that a DFG node that is not JSConstant
     20        behaves as a constant. CheckMethod uses this functionality.
     21       
     22        This is a 3% speed-up on Kraken, and a small speed-up on V8.
     23        Appears to be neutral on SunSpider.
     24
     25        * bytecode/CodeBlock.h:
     26        (JSC::getStructureStubInfoBytecodeIndex):
     27        (JSC::getMethodCallLinkInfoBytecodeIndex):
     28        * bytecode/PredictedType.cpp:
     29        (JSC::predictionFromCell):
     30        (JSC::predictionFromValue):
     31        * bytecode/PredictedType.h:
     32        * bytecode/StructureStubInfo.h:
     33        * dfg/DFGAliasTracker.h:
     34        (JSC::DFG::AliasTracker::recordGetMethod):
     35        * dfg/DFGByteCodeParser.cpp:
     36        (JSC::DFG::ByteCodeParser::parseBlock):
     37        * dfg/DFGGraph.cpp:
     38        (JSC::DFG::Graph::dump):
     39        * dfg/DFGGraph.h:
     40        (JSC::DFG::Graph::getMethodCheckPrediction):
     41        (JSC::DFG::Graph::getPrediction):
     42        (JSC::DFG::Graph::isConstant):
     43        (JSC::DFG::Graph::isJSConstant):
     44        (JSC::DFG::Graph::valueOfJSConstant):
     45        (JSC::DFG::Graph::valueOfInt32Constant):
     46        (JSC::DFG::Graph::valueOfNumberConstant):
     47        (JSC::DFG::Graph::valueOfBooleanConstant):
     48        (JSC::DFG::Graph::valueOfJSConstantNode):
     49        * dfg/DFGJITCodeGenerator.cpp:
     50        (JSC::DFG::JITCodeGenerator::fillInteger):
     51        (JSC::DFG::JITCodeGenerator::fillDouble):
     52        (JSC::DFG::JITCodeGenerator::fillJSValue):
     53        (JSC::DFG::JITCodeGenerator::isKnownNotInteger):
     54        (JSC::DFG::JITCodeGenerator::isKnownNotNumber):
     55        * dfg/DFGJITCodeGenerator.h:
     56        (JSC::DFG::JITCodeGenerator::silentSpillFPR):
     57        (JSC::DFG::JITCodeGenerator::silentFillGPR):
     58        (JSC::DFG::JITCodeGenerator::silentFillFPR):
     59        * dfg/DFGJITCompiler.cpp:
     60        (JSC::DFG::JITCompiler::fillNumericToDouble):
     61        (JSC::DFG::JITCompiler::fillInt32ToInteger):
     62        (JSC::DFG::JITCompiler::fillToJS):
     63        * dfg/DFGNode.h:
     64        (JSC::DFG::Node::hasConstant):
     65        (JSC::DFG::Node::hasIdentifier):
     66        (JSC::DFG::Node::hasMethodCheckData):
     67        (JSC::DFG::Node::methodCheckDataIndex):
     68        (JSC::DFG::Node::valueOfJSConstant):
     69        * dfg/DFGPropagator.cpp:
     70        (JSC::DFG::Propagator::propagateNode):
     71        * dfg/DFGSpeculativeJIT.cpp:
     72        (JSC::DFG::SpeculativeJIT::fillSpeculateIntInternal):
     73        (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
     74        (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
     75        (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
     76        (JSC::DFG::SpeculativeJIT::compile):
     77        * jit/JIT.cpp:
     78        (JSC::JIT::privateCompile):
     79        * jit/JIT.h:
     80        (JSC::PropertyStubCompilationInfo::PropertyStubCompilationInfo):
     81        (JSC::MethodCallCompilationInfo::MethodCallCompilationInfo):
     82        * jit/JITPropertyAccess.cpp:
     83        (JSC::JIT::emit_op_method_check):
     84        (JSC::JIT::compileGetByIdHotPath):
     85        (JSC::JIT::emit_op_put_by_id):
     86        * jit/JITPropertyAccess32_64.cpp:
     87        (JSC::JIT::emit_op_method_check):
     88        (JSC::JIT::compileGetByIdHotPath):
     89        (JSC::JIT::emit_op_put_by_id):
     90        * runtime/JSCell.h:
     91        (JSC::JSCell::JSCell::structureAddress):
     92
    1932011-09-15  Adam Barth  <abarth@webkit.org>
    294
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r95240 r95273  
    154154        }
    155155
     156        unsigned bytecodeIndex;
    156157        CodeLocationCall callReturnLocation;
    157158        JITWriteBarrier<Structure> cachedStructure;
     
    198199    }
    199200
     201    inline unsigned getStructureStubInfoBytecodeIndex(StructureStubInfo* structureStubInfo)
     202    {
     203        return structureStubInfo->bytecodeIndex;
     204    }
     205
    200206    inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo)
    201207    {
     
    206212    {
    207213        return methodCallLinkInfo->callReturnLocation.executableAddress();
     214    }
     215
     216    inline unsigned getMethodCallLinkInfoBytecodeIndex(MethodCallLinkInfo* methodCallLinkInfo)
     217    {
     218        return methodCallLinkInfo->bytecodeIndex;
    208219    }
    209220
     
    272283        }
    273284
     285        StructureStubInfo& getStubInfo(unsigned bytecodeIndex)
     286        {
     287            return *(binarySearch<StructureStubInfo, unsigned, getStructureStubInfoBytecodeIndex>(m_structureStubInfos.begin(), m_structureStubInfos.size(), bytecodeIndex));
     288        }
     289
    274290        CallLinkInfo& getCallLinkInfo(ReturnAddressPtr returnAddress)
    275291        {
     
    280296        {
    281297            return *(binarySearch<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress.value()));
     298        }
     299
     300        MethodCallLinkInfo& getMethodCallLinkInfo(unsigned bytecodeIndex)
     301        {
     302            return *(binarySearch<MethodCallLinkInfo, unsigned, getMethodCallLinkInfoBytecodeIndex>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), bytecodeIndex));
    282303        }
    283304
  • trunk/Source/JavaScriptCore/bytecode/PredictedType.cpp

    r95134 r95273  
    8383#endif
    8484
     85PredictedType predictionFromCell(JSCell* cell)
     86{
     87    const ClassInfo* classInfo = cell->structure()->classInfo();
     88   
     89    if (classInfo == &JSFinalObject::s_info)
     90        return PredictFinalObject;
     91   
     92    if (classInfo == &JSArray::s_info)
     93        return PredictArray;
     94   
     95    if (classInfo == &JSString::s_info)
     96        return PredictString;
     97   
     98    if (classInfo->isSubClassOf(&JSObject::s_info))
     99        return PredictObjectOther;
     100   
     101    return PredictCellOther;
     102}
     103
    85104PredictedType predictionFromValue(JSValue value)
    86105{
     
    89108    if (value.isDouble())
    90109        return PredictDouble;
    91     if (value.isCell()) {
    92         const ClassInfo* classInfo = value.asCell()->structure()->classInfo();
    93        
    94         if (classInfo == &JSFinalObject::s_info)
    95             return PredictFinalObject;
    96        
    97         if (classInfo == &JSArray::s_info)
    98             return PredictArray;
    99        
    100         if (classInfo == &JSString::s_info)
    101             return PredictString;
    102        
    103         if (classInfo->isSubClassOf(&JSObject::s_info))
    104             return PredictObjectOther;
    105        
    106         return PredictCellOther;
    107     }
     110    if (value.isCell())
     111        return predictionFromCell(value.asCell());
    108112    if (value.isBoolean())
    109113        return PredictBoolean;
  • trunk/Source/JavaScriptCore/bytecode/PredictedType.h

    r95134 r95273  
    151151}
    152152
     153PredictedType predictionFromCell(JSCell*);
    153154PredictedType predictionFromValue(JSValue);
    154155
  • trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h

    r94920 r95273  
    127127            seen = true;
    128128        }
     129       
     130        unsigned bytecodeIndex;
    129131
    130132        int8_t accessType;
  • trunk/Source/JavaScriptCore/dfg/DFGAliasTracker.h

    r91607 r95273  
    8686    void recordGetMethod(NodeIndex getMethod)
    8787    {
    88         ASSERT_UNUSED(getMethod, m_graph[getMethod].op == GetMethod);
     88        ASSERT_UNUSED(getMethod, m_graph[getMethod].op == GetMethod || m_graph[getMethod].op == CheckMethod);
    8989        m_candidateAliasGetByVal = NoNode;
    9090    }
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r95240 r95273  
    921921            NodeIndex base = get(getInstruction[2].u.operand);
    922922            unsigned identifier = getInstruction[3].u.operand;
    923            
    924             NodeIndex getMethod = addToGraph(GetMethod, OpInfo(identifier), OpInfo(PredictNone), base);
    925             set(getInstruction[1].u.operand, getMethod);
    926             stronglyPredict(getMethod);
    927             aliases.recordGetMethod(getMethod);
     923               
     924            // Check if the method_check was monomorphic. If so, emit a CheckXYZMethod
     925            // node, which is a lot more efficient.
     926            StructureStubInfo& stubInfo = m_profiledBlock->getStubInfo(m_currentIndex);
     927            MethodCallLinkInfo& methodCall = m_profiledBlock->getMethodCallLinkInfo(m_currentIndex);
     928           
     929            if (methodCall.seen && !!methodCall.cachedStructure && !stubInfo.seen) {
     930                // It's monomorphic as far as we can tell, since the method_check was linked
     931                // but the slow path (i.e. the normal get_by_id) never fired.
     932           
     933                NodeIndex checkMethod = addToGraph(CheckMethod, OpInfo(identifier), OpInfo(m_graph.m_methodCheckData.size()), base);
     934                set(getInstruction[1].u.operand, checkMethod);
     935               
     936                MethodCheckData methodCheckData;
     937                methodCheckData.structure = methodCall.cachedStructure.get();
     938                methodCheckData.prototypeStructure = methodCall.cachedPrototypeStructure.get();
     939                methodCheckData.function = methodCall.cachedFunction.get();
     940                methodCheckData.prototype = methodCall.cachedPrototype.get();
     941                m_graph.m_methodCheckData.append(methodCheckData);
     942               
     943                aliases.recordGetMethod(checkMethod);
     944            } else {
     945                NodeIndex getMethod = addToGraph(GetMethod, OpInfo(identifier), OpInfo(PredictNone), base);
     946                set(getInstruction[1].u.operand, getMethod);
     947                stronglyPredict(getMethod);
     948                aliases.recordGetMethod(getMethod);
     949            }
    928950           
    929951            m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id);
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r95240 r95273  
    124124        printf("%s$%u", hasPrinted ? ", " : "", node.constantNumber());
    125125        if (codeBlock) {
    126             JSValue value = node.valueOfJSConstant(codeBlock);
     126            JSValue value = valueOfJSConstant(codeBlock, nodeIndex);
    127127            printf(" = %s", value.description());
    128128        }
     
    144144        if (node.hasLocal())
    145145            printf("  predicting %s", predictionToString(getPrediction(node.local())));
    146         if (node.hasVarNumber())
     146        else if (node.hasVarNumber())
    147147            printf("  predicting %s", predictionToString(getGlobalVarPrediction(node.varNumber())));
    148         if (node.hasPrediction())
     148        else if (node.hasPrediction())
    149149            printf("  predicting %s", predictionToString(node.getPrediction()));
     150        else if (node.hasMethodCheckData()) {
     151            MethodCheckData& methodCheckData = m_methodCheckData[node.methodCheckDataIndex()];
     152            printf("  predicting function %p", methodCheckData.function);
     153        }
    150154    }
    151155   
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r95060 r95273  
    5858};
    5959
     60struct MethodCheckData {
     61    // It is safe to refer to these directly because they are shadowed by
     62    // the old JIT's CodeBlock's MethodCallLinkInfo.
     63    Structure* structure;
     64    Structure* prototypeStructure;
     65    JSObject* function;
     66    JSObject* prototype;
     67};
     68
    6069typedef Vector <BlockIndex, 2> PredecessorList;
    6170
     
    172181    }
    173182   
     183    PredictedType getMethodCheckPrediction(Node& node)
     184    {
     185        return makePrediction(predictionFromCell(m_methodCheckData[node.methodCheckDataIndex()].function), StrongPrediction);
     186    }
     187   
    174188    PredictedType getPrediction(Node& node)
    175189    {
     
    193207        case Construct:
    194208            return nodePtr->getPrediction();
     209        case CheckMethod:
     210            return getMethodCheckPrediction(*nodePtr);
    195211        default:
    196212            return PredictNone;
     
    201217    bool isConstant(NodeIndex nodeIndex)
    202218    {
    203         return at(nodeIndex).isConstant();
     219        return at(nodeIndex).hasConstant();
    204220    }
    205221    bool isJSConstant(NodeIndex nodeIndex)
    206222    {
    207         return at(nodeIndex).isConstant();
     223        return at(nodeIndex).hasConstant();
    208224    }
    209225    bool isInt32Constant(CodeBlock* codeBlock, NodeIndex nodeIndex)
     
    226242    JSValue valueOfJSConstant(CodeBlock* codeBlock, NodeIndex nodeIndex)
    227243    {
    228         return at(nodeIndex).valueOfJSConstant(codeBlock);
     244        if (at(nodeIndex).hasMethodCheckData())
     245            return JSValue(m_methodCheckData[at(nodeIndex).methodCheckDataIndex()].function);
     246        return valueOfJSConstantNode(codeBlock, nodeIndex);
    229247    }
    230248    int32_t valueOfInt32Constant(CodeBlock* codeBlock, NodeIndex nodeIndex)
    231249    {
    232         return at(nodeIndex).valueOfInt32Constant(codeBlock);
     250        return valueOfJSConstantNode(codeBlock, nodeIndex).asInt32();
    233251    }
    234252    double valueOfNumberConstant(CodeBlock* codeBlock, NodeIndex nodeIndex)
    235253    {
    236         return at(nodeIndex).valueOfNumberConstant(codeBlock);
     254        return valueOfJSConstantNode(codeBlock, nodeIndex).uncheckedGetNumber();
    237255    }
    238256    bool valueOfBooleanConstant(CodeBlock* codeBlock, NodeIndex nodeIndex)
    239257    {
    240         return at(nodeIndex).valueOfBooleanConstant(codeBlock);
     258        return valueOfJSConstantNode(codeBlock, nodeIndex).getBoolean();
    241259    }
    242260
     
    249267    Vector< OwnPtr<BasicBlock> , 8> m_blocks;
    250268    Vector<NodeIndex, 16> m_varArgChildren;
     269    Vector<MethodCheckData> m_methodCheckData;
    251270private:
     271   
     272    JSValue valueOfJSConstantNode(CodeBlock* codeBlock, NodeIndex nodeIndex)
     273    {
     274        return codeBlock->constantRegister(FirstConstantRegisterIndex + at(nodeIndex).constantNumber()).get();
     275    }
    252276
    253277    // When a node's refCount goes from 0 to 1, it must (logically) recursively ref all of its children, and vice versa.
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp

    r95240 r95273  
    5353        GPRReg gpr = allocate();
    5454
    55         if (node.isConstant()) {
     55        if (node.hasConstant()) {
    5656            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    5757            if (isInt32Constant(nodeIndex)) {
     
    125125        GPRReg gpr = allocate();
    126126
    127         if (node.isConstant()) {
     127        if (node.hasConstant()) {
    128128            if (isInt32Constant(nodeIndex)) {
    129129                // FIXME: should not be reachable?
     
    250250        GPRReg gpr = allocate();
    251251
    252         if (node.isConstant()) {
     252        if (node.hasConstant()) {
    253253            if (isInt32Constant(nodeIndex)) {
    254254                info.fillJSValue(gpr, DataFormatJSInteger);
     
    405405   
    406406    return info.isJSDouble() || info.isJSCell() || info.isJSBoolean()
    407         || (node.isConstant() && !valueOfJSConstant(nodeIndex).isInt32());
     407        || (node.hasConstant() && !valueOfJSConstant(nodeIndex).isInt32());
    408408}
    409409
     
    415415   
    416416    return (!info.isJSDouble() && !info.isJSInteger() && !info.isUnknownJS())
    417         || (node.isConstant() && !isNumberConstant(nodeIndex));
     417        || (node.hasConstant() && !isNumberConstant(nodeIndex));
    418418}
    419419
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h

    r95230 r95273  
    239239        if (!info.needsSpill()) {
    240240            // it's either a constant or it's already been spilled
    241             ASSERT(m_jit.graph()[info.nodeIndex()].isConstant() || info.spillFormat() != DataFormatNone);
     241            ASSERT(m_jit.graph()[info.nodeIndex()].hasConstant() || info.spillFormat() != DataFormatNone);
    242242            return;
    243243        }
    244244       
    245245        // it's neither a constant nor has it been spilled.
    246         ASSERT(!m_jit.graph()[info.nodeIndex()].isConstant());
     246        ASSERT(!m_jit.graph()[info.nodeIndex()].hasConstant());
    247247        ASSERT(info.spillFormat() == DataFormatNone);
    248248
     
    263263
    264264        if (registerFormat == DataFormatInteger) {
    265             if (node.isConstant()) {
     265            if (node.hasConstant()) {
    266266                ASSERT(isInt32Constant(nodeIndex));
    267267                m_jit.move(Imm32(valueOfInt32Constant(nodeIndex)), info.gpr());
     
    271271        }
    272272
    273         if (node.isConstant())
     273        if (node.hasConstant())
    274274            m_jit.move(valueOfJSConstantAsImmPtr(nodeIndex), info.gpr());
    275275        else {
     
    288288        ASSERT(info.registerFormat() == DataFormatDouble);
    289289
    290         if (node.isConstant()) {
     290        if (node.hasConstant()) {
    291291            ASSERT(isNumberConstant(nodeIndex));
    292292            m_jit.move(JITCompiler::ImmPtr(bitwise_cast<void*>(valueOfNumberConstant(nodeIndex))), canTrample);
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

    r95240 r95273  
    4444    Node& node = graph()[nodeIndex];
    4545
    46     if (node.isConstant()) {
     46    if (node.hasConstant()) {
    4747        ASSERT(isNumberConstant(nodeIndex));
    4848        move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(nodeIndex)))), temporary);
     
    6464    Node& node = graph()[nodeIndex];
    6565
    66     if (node.isConstant()) {
     66    if (node.hasConstant()) {
    6767        ASSERT(isInt32Constant(nodeIndex));
    6868        move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
     
    8282    Node& node = graph()[nodeIndex];
    8383
    84     if (node.isConstant()) {
     84    if (node.hasConstant()) {
    8585        if (isInt32Constant(nodeIndex)) {
    8686            JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r95240 r95273  
    172172    macro(PutByIdDirect, NodeMustGenerate) \
    173173    macro(GetMethod, NodeResultJS | NodeMustGenerate) \
     174    macro(CheckMethod, NodeResultJS | NodeMustGenerate) \
    174175    macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
    175176    macro(PutGlobalVar, NodeMustGenerate) \
     
    298299        return op == JSConstant;
    299300    }
     301   
     302    bool hasConstant()
     303    {
     304        return isConstant() || hasMethodCheckData();
     305    }
    300306
    301307    unsigned constantNumber()
     
    303309        ASSERT(isConstant());
    304310        return m_opInfo;
    305     }
    306    
    307     JSValue valueOfJSConstant(CodeBlock* codeBlock)
    308     {
    309         return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
    310311    }
    311312   
     
    335336    }
    336337   
    337     int32_t valueOfInt32Constant(CodeBlock* codeBlock)
    338     {
    339         ASSERT(isInt32Constant(codeBlock));
    340         return valueOfJSConstant(codeBlock).asInt32();
    341     }
    342    
    343     double valueOfNumberConstant(CodeBlock* codeBlock)
    344     {
    345         ASSERT(isNumberConstant(codeBlock));
    346         return valueOfJSConstant(codeBlock).uncheckedGetNumber();
    347     }
    348    
    349     bool valueOfBooleanConstant(CodeBlock* codeBlock)
    350     {
    351         ASSERT(isBooleanConstant(codeBlock));
    352         return valueOfJSConstant(codeBlock).getBoolean();
    353     }
    354 
    355338    bool hasLocal()
    356339    {
     
    365348
    366349#if !ASSERT_DISABLED
    367     // If we want to use this in production code, should make it faster -
    368     // e.g. make hasIdentifier a flag in the bitfield.
    369350    bool hasIdentifier()
    370351    {
    371         return op == GetById || op == PutById || op == PutByIdDirect || op == GetMethod
    372             || op == Resolve || op == ResolveBase || op == ResolveBaseStrictPut;
     352        switch (op) {
     353        case GetById:
     354        case PutById:
     355        case PutByIdDirect:
     356        case GetMethod:
     357        case CheckMethod:
     358        case Resolve:
     359        case ResolveBase:
     360        case ResolveBaseStrictPut:
     361            return true;
     362        default:
     363            return false;
     364        }
    373365    }
    374366#endif
     
    379371        return m_opInfo;
    380372    }
    381 
     373   
    382374    bool hasVarNumber()
    383375    {
     
    481473    }
    482474   
     475    bool hasMethodCheckData()
     476    {
     477        return op == CheckMethod;
     478    }
     479   
     480    unsigned methodCheckDataIndex()
     481    {
     482        ASSERT(hasMethodCheckData());
     483        return m_opInfo2;
     484    }
     485   
    483486    VirtualRegister virtualRegister()
    484487    {
     
    570573
    571574private:
     575    // This is private because it only works for the JSConstant op. The DFG is written under the
     576    // assumption that "valueOfJSConstant" can correctly return a constant for any DFG node for
     577    // which hasConstant() is true.
     578    JSValue valueOfJSConstant(CodeBlock* codeBlock)
     579    {
     580        return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
     581    }
     582
    572583    // The virtual register number (spill location) associated with this .
    573584    VirtualRegister m_virtualRegister;
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r95240 r95273  
    131131        switch (op) {
    132132        case JSConstant: {
    133             changed |= setPrediction(makePrediction(predictionFromValue(node.valueOfJSConstant(m_codeBlock)), StrongPrediction));
     133            changed |= setPrediction(makePrediction(predictionFromValue(m_graph.valueOfJSConstant(m_codeBlock, m_compileIndex)), StrongPrediction));
    134134            break;
    135135        }
     
    237237            break;
    238238        }
     239           
     240        case CheckMethod: {
     241            changed |= mergeUse(node.child1(), PredictObjectUnknown | StrongPredictionTag);
     242            changed |= setPrediction(m_graph.getMethodCheckPrediction(node));
     243            break;
     244        }
    239245
    240246        case Call:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r95240 r95273  
    4343    switch (info.registerFormat()) {
    4444    case DataFormatNone: {
    45         if (node.isConstant() && !isInt32Constant(nodeIndex)) {
     45        if (node.hasConstant() && !isInt32Constant(nodeIndex)) {
    4646            terminateSpeculativeExecution();
    4747            returnFormat = DataFormatInteger;
     
    5151        GPRReg gpr = allocate();
    5252
    53         if (node.isConstant()) {
     53        if (node.hasConstant()) {
    5454            m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    5555            ASSERT(isInt32Constant(nodeIndex));
     
    5858            returnFormat = DataFormatInteger;
    5959            return gpr;
    60         } else {
    61             DataFormat spillFormat = info.spillFormat();
    62             ASSERT(spillFormat & DataFormatJS);
    63 
    64             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
    65 
    66             if (spillFormat == DataFormatJSInteger) {
    67                 // If we know this was spilled as an integer we can fill without checking.
    68                 if (strict) {
    69                     m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
    70                     info.fillInteger(gpr);
    71                     returnFormat = DataFormatInteger;
    72                     return gpr;
    73                 }
    74                 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
    75                 info.fillJSValue(gpr, DataFormatJSInteger);
    76                 returnFormat = DataFormatJSInteger;
     60        }
     61       
     62        DataFormat spillFormat = info.spillFormat();
     63        ASSERT(spillFormat & DataFormatJS);
     64       
     65        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
     66       
     67        if (spillFormat == DataFormatJSInteger) {
     68            // If we know this was spilled as an integer we can fill without checking.
     69            if (strict) {
     70                m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
     71                info.fillInteger(gpr);
     72                returnFormat = DataFormatInteger;
    7773                return gpr;
    7874            }
    7975            m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
    80         }
     76            info.fillJSValue(gpr, DataFormatJSInteger);
     77            returnFormat = DataFormatJSInteger;
     78            return gpr;
     79        }
     80        m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
    8181
    8282        // Fill as JSValue, and fall through.
     
    237237        GPRReg gpr = allocate();
    238238
    239         if (node.isConstant()) {
     239        if (node.hasConstant()) {
    240240            if (isInt32Constant(nodeIndex)) {
    241241                FPRReg fpr = fprAllocate();
     
    260260            terminateSpeculativeExecution();
    261261            return fprAllocate();
    262         } else {
    263             DataFormat spillFormat = info.spillFormat();
    264             ASSERT(spillFormat & DataFormatJS);
    265             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
    266             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
    267             info.fillJSValue(gpr, spillFormat);
    268             unlock(gpr);
    269         }
     262        }
     263       
     264        DataFormat spillFormat = info.spillFormat();
     265        ASSERT(spillFormat & DataFormatJS);
     266        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
     267        m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
     268        info.fillJSValue(gpr, spillFormat);
     269        unlock(gpr);
    270270    }
    271271
     
    361361        GPRReg gpr = allocate();
    362362
    363         if (node.isConstant()) {
     363        if (node.hasConstant()) {
    364364            JSValue jsValue = valueOfJSConstant(nodeIndex);
    365365            if (jsValue.isCell()) {
     
    426426        GPRReg gpr = allocate();
    427427
    428         if (node.isConstant()) {
     428        if (node.hasConstant()) {
    429429            JSValue jsValue = valueOfJSConstant(nodeIndex);
    430430            if (jsValue.isBoolean()) {
     
    13951395
    13961396        jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
     1397        break;
     1398    }
     1399       
     1400    case CheckMethod: {
     1401        MethodCheckData& methodCheckData = m_jit.graph().m_methodCheckData[node.methodCheckDataIndex()];
     1402       
     1403        SpeculateCellOperand base(this, node.child1());
     1404        GPRTemporary scratch(this); // this needs to be a separate register, unfortunately.
     1405        GPRReg baseGPR = base.gpr();
     1406        GPRReg scratchGPR = scratch.gpr();
     1407       
     1408        speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure)));
     1409        if (methodCheckData.prototype != m_jit.codeBlock()->globalObject()->methodCallDummy()) {
     1410            m_jit.move(JITCompiler::TrustedImmPtr(methodCheckData.prototype->structureAddress()), scratchGPR);
     1411            speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(scratchGPR), JITCompiler::TrustedImmPtr(methodCheckData.prototypeStructure)));
     1412        }
     1413       
     1414        useChildren(node);
     1415        initConstantInfo(m_compileIndex);
    13971416        break;
    13981417    }
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r95240 r95273  
    629629    for (unsigned i = 0; i < m_propertyAccessCompilationInfo.size(); ++i) {
    630630        StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
     631        ASSERT(m_propertyAccessCompilationInfo[i].bytecodeIndex != std::numeric_limits<unsigned>::max());
     632        info.bytecodeIndex = m_propertyAccessCompilationInfo[i].bytecodeIndex;
    631633        info.callReturnLocation = patchBuffer.locationOf(m_propertyAccessCompilationInfo[i].callReturnLocation);
    632634        info.hotPathBegin = patchBuffer.locationOf(m_propertyAccessCompilationInfo[i].hotPathBegin);
     
    644646    for (unsigned i = 0; i < methodCallCount; ++i) {
    645647        MethodCallLinkInfo& info = m_codeBlock->methodCallLinkInfo(i);
     648        info.bytecodeIndex = m_methodCallCompilationInfo[i].bytecodeIndex;
    646649        info.cachedStructure.setLocation(patchBuffer.locationOf(m_methodCallCompilationInfo[i].structureToCompare));
    647650        info.callReturnLocation = m_codeBlock->structureStubInfo(m_methodCallCompilationInfo[i].propertyAccessIndex).callReturnLocation;
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r95240 r95273  
    147147
    148148    struct PropertyStubCompilationInfo {
     149        unsigned bytecodeIndex;
    149150        MacroAssembler::Call callReturnLocation;
    150151        MacroAssembler::Label hotPathBegin;
     152       
     153#if !ASSERT_DISABLED
     154        PropertyStubCompilationInfo()
     155            : bytecodeIndex(std::numeric_limits<unsigned>::max())
     156        {
     157        }
     158#endif
    151159    };
    152160
     
    159167
    160168    struct MethodCallCompilationInfo {
    161         MethodCallCompilationInfo(unsigned propertyAccessIndex)
    162             : propertyAccessIndex(propertyAccessIndex)
    163         {
    164         }
    165 
     169        MethodCallCompilationInfo(unsigned bytecodeIndex, unsigned propertyAccessIndex)
     170            : bytecodeIndex(bytecodeIndex)
     171            , propertyAccessIndex(propertyAccessIndex)
     172        {
     173        }
     174
     175        unsigned bytecodeIndex;
    166176        MacroAssembler::DataLabelPtr structureToCompare;
    167177        unsigned propertyAccessIndex;
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r95219 r95273  
    290290
    291291    // Do the method check - check the object & its prototype's structure inline (this is the common case).
    292     m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_propertyAccessCompilationInfo.size()));
     292    m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_bytecodeOffset, m_propertyAccessCompilationInfo.size()));
    293293    MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last();
    294294
     
    367367    Label hotPathBegin(this);
    368368    m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo());
     369    m_propertyAccessCompilationInfo.last().bytecodeIndex = m_bytecodeOffset;
    369370    m_propertyAccessCompilationInfo.last().hotPathBegin = hotPathBegin;
    370371
     
    445446    Label hotPathBegin(this);
    446447    m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo());
     448    m_propertyAccessCompilationInfo.last().bytecodeIndex = m_bytecodeOffset;
    447449    m_propertyAccessCompilationInfo.last().hotPathBegin = hotPathBegin;
    448450
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r94920 r95273  
    109109   
    110110    // Do the method check - check the object & its prototype's structure inline (this is the common case).
    111     m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_propertyAccessCompilationInfo.size()));
     111    m_methodCallCompilationInfo.append(MethodCallCompilationInfo(m_bytecodeOffset, m_propertyAccessCompilationInfo.size()));
    112112    MethodCallCompilationInfo& info = m_methodCallCompilationInfo.last();
    113113   
     
    326326    Label hotPathBegin(this);
    327327    m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo());
     328    m_propertyAccessCompilationInfo.last().bytecodeIndex = m_bytecodeOffset;
    328329    m_propertyAccessCompilationInfo.last().hotPathBegin = hotPathBegin;
    329330   
     
    402403    Label hotPathBegin(this);
    403404    m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo());
     405    m_propertyAccessCompilationInfo.last().bytecodeIndex = m_bytecodeOffset;
    404406    m_propertyAccessCompilationInfo.last().hotPathBegin = hotPathBegin;
    405407   
  • trunk/Source/JavaScriptCore/runtime/JSCell.h

    r95229 r95273  
    139139            return OBJECT_OFFSETOF(JSCell, m_structure);
    140140        }
     141       
     142        void* structureAddress()
     143        {
     144            return &m_structure;
     145        }
    141146
    142147#if ENABLE(GC_VALIDATION)
Note: See TracChangeset for help on using the changeset viewer.