Ignore:
Timestamp:
Sep 6, 2011, 7:47:51 PM (14 years ago)
Author:
[email protected]
Message:

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

Reviewed by Gavin Barraclough.

This adds boolean value profiling, boolean prediction in the DFG,
boolean forward flow propagation in the DFGPropagator, boolean
data format in DFG generation info, and comprehensive optimizations
based on both boolean prediction and boolean generation info.
This is brings the speed-up on v8-richards to 12%, and gives slight
speed-ups elsewhere as well.

Making this work right required navigating some subtleties in
value profiling. Some functions get compiled with insufficient
information because some important path of the function never
executed. In these cases, we wish to fall back on static
speculation. But to do so, we need to ensure that predictions that
are inherent in the code (like that GetById almost certainly takes
a cell operand) are reflected in predictions that we make in
DFGPropagator. Thus, DFGPropagator now does both backward and
forward flow, using a both forward and backward fixpoint.

The backward flow in DFGPropagator is a separate static analysis,
and needs to keep a set of backward flow abstract values for
variables, arguments, and globals. To make this easy, this patch
factors out DFGGraph's prediction tracking capability into
DFGPredictionTracker, which now gets used by both DFGGraph (for
forward flow predictions) and DFGPropagator (for backward flow
predictions). Backward flow predictions eventually get merged
into forward flow ones, but the two are not equivalent: a forward
flow prediction is a superset of the backward flow prediction.

Debugging these prediction issues required a better understanding
of where we fail speculation, and what our value predictions look
like. This patch also adds optional verbose speculation failure
(so an informative printf fires whenever speculation failure occurs)
and slight improvements to the verbosity in other places.

  • bytecode/ValueProfile.h:

(JSC::ValueProfile::numberOfBooleans):
(JSC::ValueProfile::probabilityOfBoolean):
(JSC::ValueProfile::dump):
(JSC::ValueProfile::computeStatistics):

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGGenerationInfo.h:

(JSC::DFG::dataFormatToString):
(JSC::DFG::needDataFormatConversion):

  • dfg/DFGGraph.cpp:

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

  • dfg/DFGGraph.h:

(JSC::DFG::Graph::Graph):
(JSC::DFG::Graph::predictions):
(JSC::DFG::Graph::predict):
(JSC::DFG::Graph::predictGlobalVar):
(JSC::DFG::Graph::getPrediction):
(JSC::DFG::Graph::getGlobalVarPrediction):
(JSC::DFG::Graph::isBooleanConstant):
(JSC::DFG::Graph::valueOfBooleanConstant):

  • dfg/DFGJITCodeGenerator.cpp:

(JSC::DFG::JITCodeGenerator::fillInteger):
(JSC::DFG::JITCodeGenerator::fillDouble):
(JSC::DFG::JITCodeGenerator::fillJSValue):
(JSC::DFG::JITCodeGenerator::isKnownNotInteger):
(JSC::DFG::JITCodeGenerator::isKnownBoolean):
(JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeCompareNull):
(JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeCompare):
(JSC::DFG::JITCodeGenerator::nonSpeculativeNonPeepholeStrictEq):
(JSC::DFG::JITCodeGenerator::emitBranch):
(JSC::DFG::JITCodeGenerator::speculationCheck):
(JSC::DFG::GPRTemporary::GPRTemporary):

  • dfg/DFGJITCodeGenerator.h:

(JSC::DFG::JITCodeGenerator::isBooleanConstant):
(JSC::DFG::JITCodeGenerator::valueOfBooleanConstant):

  • dfg/DFGJITCompiler.cpp:

(JSC::DFG::JITCompiler::jumpFromSpeculativeToNonSpeculative):
(JSC::DFG::JITCompiler::link):

  • dfg/DFGJITCompiler.h:

(JSC::DFG::JITCompiler::debugCall):
(JSC::DFG::JITCompiler::isBooleanConstant):
(JSC::DFG::JITCompiler::valueOfBooleanConstant):

  • dfg/DFGNode.h:

(JSC::DFG::isBooleanPrediction):
(JSC::DFG::predictionToString):
(JSC::DFG::mergePredictions):
(JSC::DFG::makePrediction):
(JSC::DFG::Node::isBooleanConstant):
(JSC::DFG::Node::valueOfBooleanConstant):
(JSC::DFG::Node::hasBooleanResult):
(JSC::DFG::Node::hasNumericResult):
(JSC::DFG::Node::predict):

  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionTracker.h: Added.

(JSC::DFG::operandIsArgument):
(JSC::DFG::PredictionSlot::PredictionSlot):
(JSC::DFG::PredictionTracker::PredictionTracker):
(JSC::DFG::PredictionTracker::initializeSimilarTo):
(JSC::DFG::PredictionTracker::numberOfArguments):
(JSC::DFG::PredictionTracker::numberOfVariables):
(JSC::DFG::PredictionTracker::argumentIndexForOperand):
(JSC::DFG::PredictionTracker::predictArgument):
(JSC::DFG::PredictionTracker::predict):
(JSC::DFG::PredictionTracker::predictGlobalVar):
(JSC::DFG::PredictionTracker::getArgumentPrediction):
(JSC::DFG::PredictionTracker::getPrediction):
(JSC::DFG::PredictionTracker::getGlobalVarPrediction):

  • dfg/DFGPropagator.cpp:

(JSC::DFG::Propagator::Propagator):
(JSC::DFG::Propagator::fixpoint):
(JSC::DFG::Propagator::setPrediction):
(JSC::DFG::Propagator::mergeUse):
(JSC::DFG::Propagator::mergePrediction):
(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::compare):
(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculateBooleanOperand::SpeculateBooleanOperand):
(JSC::DFG::SpeculateBooleanOperand::~SpeculateBooleanOperand):
(JSC::DFG::SpeculateBooleanOperand::index):
(JSC::DFG::SpeculateBooleanOperand::gpr):
(JSC::DFG::SpeculateBooleanOperand::use):

  • runtime/JSGlobalData.h:
  • runtime/JSValue.cpp:

(JSC::JSValue::description):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h

    r94559 r94629  
    5555struct SpeculationCheck;
    5656
     57#ifndef NDEBUG
     58typedef void (*V_DFGDebugOperation_EP)(ExecState*, void*);
     59#endif
     60
     61#if DFG_VERBOSE_SPECULATION_FAILURE
     62struct SpeculationFailureDebugInfo {
     63    CodeBlock* codeBlock;
     64    unsigned debugOffset;
     65};
     66#endif
     67
    5768// === CallRecord ===
    5869//
     
    206217        return functionCall;
    207218    }
     219   
     220#ifndef NDEBUG
     221    // Add a debug call. This call has no effect on JIT code execution state.
     222    void debugCall(V_DFGDebugOperation_EP function, void* argument)
     223    {
     224        for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i)
     225            storePtr(GPRInfo::toRegister(i), m_globalData->debugDataBuffer + i);
     226        for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
     227            move(TrustedImmPtr(m_globalData->debugDataBuffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
     228            storeDouble(FPRInfo::toRegister(i), GPRInfo::regT0);
     229        }
     230        move(TrustedImmPtr(argument), GPRInfo::argumentGPR1);
     231        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     232        move(TrustedImmPtr(reinterpret_cast<void*>(function)), GPRInfo::regT0);
     233        call(GPRInfo::regT0);
     234        for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) {
     235            move(TrustedImmPtr(m_globalData->debugDataBuffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0);
     236            loadDouble(GPRInfo::regT0, FPRInfo::toRegister(i));
     237        }
     238        for (unsigned i = 0; i < GPRInfo::numberOfRegisters; ++i)
     239            loadPtr(m_globalData->debugDataBuffer + i, GPRInfo::toRegister(i));
     240    }
     241#endif
    208242
    209243    // Helper methods to check nodes for constants.
     
    212246    bool isInt32Constant(NodeIndex nodeIndex) { return graph().isInt32Constant(codeBlock(), nodeIndex); }
    213247    bool isDoubleConstant(NodeIndex nodeIndex) { return graph().isDoubleConstant(codeBlock(), nodeIndex); }
     248    bool isBooleanConstant(NodeIndex nodeIndex) { return graph().isBooleanConstant(codeBlock(), nodeIndex); }
    214249    // Helper methods get constant values from nodes.
    215250    JSValue valueOfJSConstant(NodeIndex nodeIndex) { return graph().valueOfJSConstant(codeBlock(), nodeIndex); }
    216251    int32_t valueOfInt32Constant(NodeIndex nodeIndex) { return graph().valueOfInt32Constant(codeBlock(), nodeIndex); }
    217252    double valueOfDoubleConstant(NodeIndex nodeIndex) { return graph().valueOfDoubleConstant(codeBlock(), nodeIndex); }
     253    bool valueOfBooleanConstant(NodeIndex nodeIndex) { return graph().valueOfBooleanConstant(codeBlock(), nodeIndex); }
    218254
    219255    // These methods JIT generate dynamic, debug-only checks - akin to ASSERTs.
Note: See TracChangeset for help on using the changeset viewer.