Changeset 95916 in webkit


Ignore:
Timestamp:
Sep 24, 2011 3:39:16 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

The DFG should not attempt to guess types in the absence of value
profiles
https://bugs.webkit.org/show_bug.cgi?id=68677

Reviewed by Oliver Hunt.

This adds the ForceOSRExit node, which is ignored by the propagator
and virtual register allocator (and hence ensuring that liveness analysis
works correctly), but forces terminateSpeculativeExecution() in the
back-end. This appears to be a slight speed-up on benchmark averages,
with ~5% swings on individual benchmarks, in both directions. But it's
never a regression on any average, and appears to be a ~1% progression
in the SunSpider average.

This also adds a bit better debugging support in the old JIT and in DFG,
as this was necessary to debug the much more frequent OSR transitions
that occur with this change.

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::addCall):
(JSC::DFG::ByteCodeParser::getStrongPrediction):
(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::exitSpeculativeWithOSR):

  • dfg/DFGNode.h:
  • dfg/DFGPropagator.cpp:

(JSC::DFG::Propagator::propagateNodePredictions):

  • dfg/DFGSpeculativeJIT.cpp:

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

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::privateCompile):

  • jit/JIT.h:
Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r95914 r95916  
     12011-09-24  Filip Pizlo  <fpizlo@apple.com>
     2
     3        The DFG should not attempt to guess types in the absence of value
     4        profiles
     5        https://bugs.webkit.org/show_bug.cgi?id=68677
     6
     7        Reviewed by Oliver Hunt.
     8       
     9        This adds the ForceOSRExit node, which is ignored by the propagator
     10        and virtual register allocator (and hence ensuring that liveness analysis
     11        works correctly), but forces terminateSpeculativeExecution() in the
     12        back-end. This appears to be a slight speed-up on benchmark averages,
     13        with ~5% swings on individual benchmarks, in both directions. But it's
     14        never a regression on any average, and appears to be a ~1% progression
     15        in the SunSpider average.
     16       
     17        This also adds a bit better debugging support in the old JIT and in DFG,
     18        as this was necessary to debug the much more frequent OSR transitions
     19        that occur with this change.
     20
     21        * dfg/DFGByteCodeParser.cpp:
     22        (JSC::DFG::ByteCodeParser::addCall):
     23        (JSC::DFG::ByteCodeParser::getStrongPrediction):
     24        (JSC::DFG::ByteCodeParser::parseBlock):
     25        * dfg/DFGJITCompiler.cpp:
     26        (JSC::DFG::JITCompiler::exitSpeculativeWithOSR):
     27        * dfg/DFGNode.h:
     28        * dfg/DFGPropagator.cpp:
     29        (JSC::DFG::Propagator::propagateNodePredictions):
     30        * dfg/DFGSpeculativeJIT.cpp:
     31        (JSC::DFG::SpeculativeJIT::compile):
     32        * jit/JIT.cpp:
     33        (JSC::JIT::privateCompileMainPass):
     34        (JSC::JIT::privateCompileSlowCases):
     35        (JSC::JIT::privateCompile):
     36        * jit/JIT.h:
     37
    1382011-09-24  Geoffrey Garen  <ggaren@apple.com>
    239
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r95902 r95916  
    433433    NodeIndex addCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op)
    434434    {
     435        Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
     436
     437        PredictedType prediction = PredictNone;
     438        if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
     439            prediction = getStrongPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call));
     440       
    435441        addVarArgChild(get(currentInstruction[1].u.operand));
    436442        int argCount = currentInstruction[2].u.operand;
     
    439445        for (int argIdx = firstArg; argIdx < firstArg + argCount; argIdx++)
    440446            addVarArgChild(get(argIdx));
    441         NodeIndex call = addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(PredictNone));
    442         Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
    443         if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
     447        NodeIndex call = addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction));
     448        if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
    444449            set(putInstruction[1].u.operand, call);
    445             stronglyPredict(call, m_currentIndex + OPCODE_LENGTH(op_call));
    446         }
    447450        if (RegisterFile::CallFrameHeaderSize + (unsigned)argCount > m_parameterSlots)
    448451            m_parameterSlots = RegisterFile::CallFrameHeaderSize + argCount;
     
    488491    {
    489492        UNUSED_PARAM(nodeIndex);
    490         UNUSED_PARAM(bytecodeIndex);
    491493       
    492494        ValueProfile* profile = m_profiledBlock->valueProfileForBytecodeOffset(bytecodeIndex);
     
    496498        printf("Dynamic [@%u, bc#%u] prediction: %s\n", nodeIndex, bytecodeIndex, predictionToString(prediction));
    497499#endif
     500       
     501        if (prediction == PredictNone) {
     502            // We have no information about what values this node generates. Give up
     503            // on executing this code, since we're likely to do more damage than good.
     504            addToGraph(ForceOSRExit);
     505        }
     506       
    498507        return prediction;
    499508    }
    500509   
    501     void stronglyPredict(NodeIndex nodeIndex, unsigned bytecodeIndex)
    502     {
    503         m_graph[nodeIndex].predict(getStrongPrediction(nodeIndex, bytecodeIndex) & ~PredictionTagMask, StrongPrediction);
    504     }
    505    
    506     void stronglyPredict(NodeIndex nodeIndex)
    507     {
    508         stronglyPredict(nodeIndex, m_currentIndex);
    509     }
    510    
     510    PredictedType getStrongPrediction()
     511    {
     512        return getStrongPrediction(m_graph.size(), m_currentIndex);
     513    }
     514
    511515    NodeIndex makeSafe(NodeIndex nodeIndex)
    512516    {
     
    10591063
    10601064        case op_get_by_val: {
     1065            PredictedType prediction = getStrongPrediction();
     1066           
    10611067            NodeIndex base = get(currentInstruction[2].u.operand);
    10621068            NodeIndex property = get(currentInstruction[3].u.operand);
     
    10641070            weaklyPredictInt32(property);
    10651071
    1066             NodeIndex getByVal = addToGraph(GetByVal, OpInfo(0), OpInfo(PredictNone), base, property);
     1072            NodeIndex getByVal = addToGraph(GetByVal, OpInfo(0), OpInfo(prediction), base, property);
    10671073            set(currentInstruction[1].u.operand, getByVal);
    1068             stronglyPredict(getByVal);
    10691074
    10701075            NEXT_OPCODE(op_get_by_val);
     
    10851090        case op_method_check: {
    10861091            Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check);
     1092           
     1093            PredictedType prediction = getStrongPrediction();
    10871094           
    10881095            ASSERT(interpreter->getOpcodeID(getInstruction->u.opcode) == op_get_by_id);
     
    11101117                m_graph.m_methodCheckData.append(methodCheckData);
    11111118            } else {
    1112                 NodeIndex getMethod = addToGraph(GetMethod, OpInfo(identifier), OpInfo(PredictNone), base);
     1119                NodeIndex getMethod = addToGraph(GetMethod, OpInfo(identifier), OpInfo(prediction), base);
    11131120                set(getInstruction[1].u.operand, getMethod);
    1114                 stronglyPredict(getMethod);
    11151121            }
    11161122           
     
    11191125        }
    11201126        case op_get_scoped_var: {
     1127            PredictedType prediction = getStrongPrediction();
    11211128            int dst = currentInstruction[1].u.operand;
    11221129            int slot = currentInstruction[2].u.operand;
    11231130            int depth = currentInstruction[3].u.operand;
    11241131            NodeIndex getScopeChain = addToGraph(GetScopeChain, OpInfo(depth));
    1125             NodeIndex getScopedVar = addToGraph(GetScopedVar, OpInfo(slot), OpInfo(PredictNone), getScopeChain);
     1132            NodeIndex getScopedVar = addToGraph(GetScopedVar, OpInfo(slot), OpInfo(prediction), getScopeChain);
    11261133            set(dst, getScopedVar);
    1127             stronglyPredict(getScopedVar);
    11281134            NEXT_OPCODE(op_get_scoped_var);
    11291135        }
     
    11371143        }
    11381144        case op_get_by_id: {
     1145            PredictedType prediction = getStrongPrediction();
     1146           
    11391147            NodeIndex base = get(currentInstruction[2].u.operand);
    11401148            unsigned identifierNumber = currentInstruction[3].u.operand;
     
    11491157               
    11501158                if (offset != notFound) {
    1151                     getById = addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(PredictNone), addToGraph(CheckStructure, OpInfo(structure), base));
     1159                    getById = addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(CheckStructure, OpInfo(structure), base));
    11521160                   
    11531161                    StorageAccessData storageAccessData;
     
    11591167           
    11601168            if (getById == NoNode)
    1161                 getById = addToGraph(GetById, OpInfo(identifierNumber), OpInfo(PredictNone), base);
     1169                getById = addToGraph(GetById, OpInfo(identifierNumber), OpInfo(prediction), base);
    11621170           
    11631171            set(currentInstruction[1].u.operand, getById);
    1164             stronglyPredict(getById);
    11651172
    11661173            NEXT_OPCODE(op_get_by_id);
     
    11821189
    11831190        case op_get_global_var: {
     1191            PredictedType prediction = getStrongPrediction();
     1192           
    11841193            NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand));
    11851194            set(currentInstruction[1].u.operand, getGlobalVar);
    1186             m_graph.predictGlobalVar(currentInstruction[2].u.operand, getStrongPrediction(getGlobalVar, m_currentIndex) & ~PredictionTagMask, StrongPrediction);
     1195            m_graph.predictGlobalVar(currentInstruction[2].u.operand, prediction & ~PredictionTagMask, StrongPrediction);
    11871196            NEXT_OPCODE(op_get_global_var);
    11881197        }
     
    14161425
    14171426        case op_resolve: {
     1427            PredictedType prediction = getStrongPrediction();
     1428           
    14181429            unsigned identifier = currentInstruction[2].u.operand;
    14191430
    1420             NodeIndex resolve = addToGraph(Resolve, OpInfo(identifier), OpInfo(PredictNone));
     1431            NodeIndex resolve = addToGraph(Resolve, OpInfo(identifier), OpInfo(prediction));
    14211432            set(currentInstruction[1].u.operand, resolve);
    1422             stronglyPredict(resolve);
    14231433
    14241434            NEXT_OPCODE(op_resolve);
     
    14261436
    14271437        case op_resolve_base: {
     1438            PredictedType prediction = getStrongPrediction();
     1439           
    14281440            unsigned identifier = currentInstruction[2].u.operand;
    14291441
    1430             NodeIndex resolve = addToGraph(currentInstruction[3].u.operand ? ResolveBaseStrictPut : ResolveBase, OpInfo(identifier), OpInfo(PredictNone));
     1442            NodeIndex resolve = addToGraph(currentInstruction[3].u.operand ? ResolveBaseStrictPut : ResolveBase, OpInfo(identifier), OpInfo(prediction));
    14311443            set(currentInstruction[1].u.operand, resolve);
    1432             stronglyPredict(resolve);
    14331444
    14341445            NEXT_OPCODE(op_resolve_base);
     
    14361447           
    14371448        case op_resolve_global: {
    1438             NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(PredictNone));
     1449            PredictedType prediction = getStrongPrediction();
     1450           
     1451            NodeIndex resolve = addToGraph(ResolveGlobal, OpInfo(m_graph.m_resolveGlobalData.size()), OpInfo(prediction));
    14391452            m_graph.m_resolveGlobalData.append(ResolveGlobalData());
    14401453            ResolveGlobalData& data = m_graph.m_resolveGlobalData.last();
     
    14421455            data.resolveInfoIndex = m_globalResolveNumber++;
    14431456            set(currentInstruction[1].u.operand, resolve);
    1444             stronglyPredict(resolve);
    14451457
    14461458            NEXT_OPCODE(op_resolve_global);
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

    r95910 r95916  
    110110    exit.dump(stderr);
    111111#endif
    112 #if ENABLE(DFG_JIT_BREAK_ON_SPECULATION_FAILURE)
    113     breakpoint();
    114 #endif
    115    
    116112#if ENABLE(DFG_VERBOSE_SPECULATION_FAILURE)
    117113    SpeculationFailureDebugInfo* debugInfo = new SpeculationFailureDebugInfo;
     
    120116   
    121117    debugCall(debugOperationPrintSpeculationFailure, debugInfo);
     118#endif
     119   
     120#if ENABLE(DFG_JIT_BREAK_ON_SPECULATION_FAILURE)
     121    breakpoint();
    122122#endif
    123123   
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r95902 r95916  
    306306    macro(Return, NodeMustGenerate | NodeIsTerminal) \
    307307    macro(Throw, NodeMustGenerate | NodeIsTerminal) \
    308     macro(ThrowReferenceError, NodeMustGenerate | NodeIsTerminal)
     308    macro(ThrowReferenceError, NodeMustGenerate | NodeIsTerminal) \
     309    \
     310    /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\
     311    /* this point, but execution does continue in the basic block - just in a */\
     312    /* different compiler. */\
     313    macro(ForceOSRExit, NodeMustGenerate)
    309314
    310315// This enum generates a monotonically increasing id for all Node types,
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r95901 r95916  
    607607        case Throw:
    608608        case ThrowReferenceError:
     609        case ForceOSRExit:
    609610            break;
    610611           
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r95910 r95916  
    20902090        break;
    20912091    }
     2092       
     2093    case ForceOSRExit: {
     2094        terminateSpeculativeExecution();
     2095        break;
     2096    }
    20922097
    20932098    case Phantom:
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r95901 r95916  
    211211        if (m_canBeOptimized)
    212212            m_jitCodeMapEncoder.append(m_bytecodeOffset, differenceBetween(m_startOfCode, label()));
     213#endif
     214       
     215#if ENABLE(JIT_VERBOSE)
     216        printf("Old JIT emitting code for bc#%u at offset 0x%lx.\n", m_bytecodeOffset, differenceBetween(m_startOfCode, label()));
    213217#endif
    214218
     
    421425#endif
    422426
     427#if ENABLE(JIT_VERBOSE)
     428        printf("Old JIT emitting slow code for bc#%u at offset 0x%lx.\n", m_bytecodeOffset, differenceBetween(m_startOfCode, label()));
     429#endif
     430
    423431        switch (m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
    424432        DEFINE_SLOWCASE_OP(op_add)
     
    672680        *functionEntryArityCheck = patchBuffer.locationOf(arityCheck);
    673681   
    674     return JITCode(patchBuffer.finalizeCode(), JITCode::BaselineJIT);
     682    CodeRef result = patchBuffer.finalizeCode();
     683   
     684#if ENABLE(JIT_VERBOSE)
     685    printf("JIT generated code for %p at [%p, %p).\n", m_codeBlock, result.executableMemory()->start(), result.executableMemory()->end());
     686#endif
     687   
     688    return JITCode(result, JITCode::BaselineJIT);
    675689}
    676690
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r95901 r95916  
    2929#if ENABLE(JIT)
    3030
     31// Verbose logging of code generation
     32#define ENABLE_JIT_VERBOSE 0
    3133// Verbose logging for OSR-related code.
    3234#define ENABLE_JIT_VERBOSE_OSR 0
Note: See TracChangeset for help on using the changeset viewer.