Ignore:
Timestamp:
Dec 4, 2014, 9:58:07 PM (11 years ago)
Author:
[email protected]
Message:

JavaScript Control Flow Profiler
https://bugs.webkit.org/show_bug.cgi?id=137785

Reviewed by Filip Pizlo.

This patch introduces a mechanism for JavaScriptCore to profile
which basic blocks have executed. This mechanism will then be
used by the Web Inspector to indicate which basic blocks
have and have not executed.

The profiling works by compiling in an op_profile_control_flow
at the start of every basic block. Then, whenever this op code
executes, we know that a particular basic block has executed.

When we tier up a CodeBlock that contains an op_profile_control_flow
that corresponds to an already executed basic block, we don't
have to emit code for that particular op_profile_control_flow
because the internal data structures used to keep track of
basic block locations has already recorded that the corresponding
op_profile_control_flow has executed.

  • CMakeLists.txt:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):

  • bytecode/Instruction.h:
  • bytecode/UnlinkedCodeBlock.cpp:

(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):

  • bytecode/UnlinkedCodeBlock.h:

(JSC::UnlinkedCodeBlock::addOpProfileControlFlowBytecodeOffset):
(JSC::UnlinkedCodeBlock::opProfileControlFlowBytecodeOffsets):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitProfileControlFlow):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::ConditionalNode::emitBytecode):
(JSC::IfElseNode::emitBytecode):
(JSC::WhileNode::emitBytecode):
(JSC::ForNode::emitBytecode):
(JSC::ContinueNode::emitBytecode):
(JSC::BreakNode::emitBytecode):
(JSC::ReturnNode::emitBytecode):
(JSC::CaseClauseNode::emitBytecode):
(JSC::SwitchNode::emitBytecode):
(JSC::ThrowNode::emitBytecode):
(JSC::TryNode::emitBytecode):
(JSC::ProgramNode::emitBytecode):
(JSC::FunctionNode::emitBytecode):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

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

  • dfg/DFGNode.h:

(JSC::DFG::Node::basicBlockLocation):

  • dfg/DFGNodeType.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • inspector/agents/InspectorRuntimeAgent.cpp:

(Inspector::InspectorRuntimeAgent::getRuntimeTypesForVariablesAtOffsets):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_profile_control_flow):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_profile_control_flow):

  • jsc.cpp:

(GlobalObject::finishCreation):
(functionFindTypeForExpression):
(functionReturnTypeFor):
(functionDumpBasicBlockExecutionRanges):

  • llint/LowLevelInterpreter.asm:
  • parser/ASTBuilder.h:

(JSC::ASTBuilder::createFunctionExpr):
(JSC::ASTBuilder::createGetterOrSetterProperty):
(JSC::ASTBuilder::createFuncDeclStatement):
(JSC::ASTBuilder::endOffset):
(JSC::ASTBuilder::setStartOffset):

  • parser/NodeConstructors.h:

(JSC::Node::Node):

  • parser/Nodes.h:

(JSC::CaseClauseNode::setStartOffset):

  • parser/Parser.cpp:

(JSC::Parser<LexerType>::parseSwitchClauses):
(JSC::Parser<LexerType>::parseSwitchDefaultClause):
(JSC::Parser<LexerType>::parseBlockStatement):
(JSC::Parser<LexerType>::parseStatement):
(JSC::Parser<LexerType>::parseFunctionDeclaration):
(JSC::Parser<LexerType>::parseIfStatement):
(JSC::Parser<LexerType>::parseExpression):
(JSC::Parser<LexerType>::parseConditionalExpression):
(JSC::Parser<LexerType>::parseProperty):
(JSC::Parser<LexerType>::parseMemberExpression):

  • parser/SyntaxChecker.h:

(JSC::SyntaxChecker::createFunctionExpr):
(JSC::SyntaxChecker::createFuncDeclStatement):
(JSC::SyntaxChecker::createGetterOrSetterProperty):
(JSC::SyntaxChecker::operatorStackPop):

  • runtime/BasicBlockLocation.cpp: Added.

(JSC::BasicBlockLocation::BasicBlockLocation):
(JSC::BasicBlockLocation::insertGap):
(JSC::BasicBlockLocation::getExecutedRanges):
(JSC::BasicBlockLocation::dumpData):
(JSC::BasicBlockLocation::emitExecuteCode):

  • runtime/BasicBlockLocation.h: Added.

(JSC::BasicBlockLocation::startOffset):
(JSC::BasicBlockLocation::endOffset):
(JSC::BasicBlockLocation::setStartOffset):
(JSC::BasicBlockLocation::setEndOffset):
(JSC::BasicBlockLocation::hasExecuted):

  • runtime/CodeCache.cpp:

(JSC::CodeCache::getGlobalCodeBlock):

  • runtime/ControlFlowProfiler.cpp: Added.

(JSC::ControlFlowProfiler::~ControlFlowProfiler):
(JSC::ControlFlowProfiler::getBasicBlockLocation):
(JSC::ControlFlowProfiler::dumpData):
(JSC::ControlFlowProfiler::getBasicBlocksForSourceID):

  • runtime/ControlFlowProfiler.h: Added. This class is in

charge of generating BasicBlockLocations and also
providing an interface that the Web Inspector can use to ping
which basic blocks have executed based on the source id of a script.

(JSC::BasicBlockKey::BasicBlockKey):
(JSC::BasicBlockKey::isHashTableDeletedValue):
(JSC::BasicBlockKey::operator==):
(JSC::BasicBlockKey::hash):
(JSC::BasicBlockKeyHash::hash):
(JSC::BasicBlockKeyHash::equal):

  • runtime/Executable.cpp:

(JSC::ProgramExecutable::ProgramExecutable):
(JSC::ProgramExecutable::initializeGlobalProperties):

  • runtime/FunctionHasExecutedCache.cpp:

(JSC::FunctionHasExecutedCache::getUnexecutedFunctionRanges):

  • runtime/FunctionHasExecutedCache.h:
  • runtime/Options.h:
  • runtime/TypeProfiler.cpp:

(JSC::TypeProfiler::logTypesForTypeLocation):
(JSC::TypeProfiler::typeInformationForExpressionAtOffset):
(JSC::TypeProfiler::findLocation):
(JSC::TypeProfiler::dumpTypeProfilerData):

  • runtime/TypeProfiler.h:

(JSC::TypeProfiler::functionHasExecutedCache): Deleted.

  • runtime/VM.cpp:

(JSC::VM::VM):
(JSC::enableProfilerWithRespectToCount):
(JSC::disableProfilerWithRespectToCount):
(JSC::VM::enableTypeProfiler):
(JSC::VM::disableTypeProfiler):
(JSC::VM::enableControlFlowProfiler):
(JSC::VM::disableControlFlowProfiler):
(JSC::VM::dumpTypeProfilerData):

  • runtime/VM.h:

(JSC::VM::functionHasExecutedCache):
(JSC::VM::controlFlowProfiler):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r176756 r176836  
    191191    , m_builtinExecutables(std::make_unique<BuiltinExecutables>(*this))
    192192    , m_typeProfilerEnabledCount(0)
     193    , m_controlFlowProfilerEnabledCount(0)
    193194{
    194195    interpreter = new Interpreter(*this);
     
    282283    if (Options::enableTypeProfiler())
    283284        enableTypeProfiler();
     285    if (Options::enableControlFlowProfiler())
     286        enableControlFlowProfiler();
    284287}
    285288
     
    894897}
    895898
     899static bool enableProfilerWithRespectToCount(unsigned& counter, std::function<void()> doEnableWork)
     900{
     901    bool needsToRecompile = false;
     902    if (!counter) {
     903        doEnableWork();
     904        needsToRecompile = true;
     905    }
     906    counter++;
     907
     908    return needsToRecompile;
     909}
     910
     911static bool disableProfilerWithRespectToCount(unsigned& counter, std::function<void()> doDisableWork)
     912{
     913    RELEASE_ASSERT(counter > 0);
     914    bool needsToRecompile = false;
     915    counter--;
     916    if (!counter) {
     917        doDisableWork();
     918        needsToRecompile = true;
     919    }
     920
     921    return needsToRecompile;
     922}
     923
    896924bool VM::enableTypeProfiler()
    897925{
    898     bool needsToRecompile = false;
    899     if (!m_typeProfilerEnabledCount) {
    900         m_typeProfiler = std::make_unique<TypeProfiler>();
    901         m_typeProfilerLog = std::make_unique<TypeProfilerLog>();
    902         needsToRecompile = true;
    903     }
    904     m_typeProfilerEnabledCount++;
    905 
    906     return needsToRecompile;
     926    auto enableTypeProfiler = [this] () {
     927        this->m_typeProfiler = std::make_unique<TypeProfiler>();
     928        this->m_typeProfilerLog = std::make_unique<TypeProfilerLog>();
     929    };
     930
     931    return enableProfilerWithRespectToCount(m_typeProfilerEnabledCount, enableTypeProfiler);
    907932}
    908933
    909934bool VM::disableTypeProfiler()
    910935{
    911     RELEASE_ASSERT(m_typeProfilerEnabledCount > 0);
    912 
    913     bool needsToRecompile = false;
    914     m_typeProfilerEnabledCount--;
    915     if (!m_typeProfilerEnabledCount) {
    916         m_typeProfiler.reset(nullptr);
    917         m_typeProfilerLog.reset(nullptr);
    918         needsToRecompile = true;
    919     }
    920 
    921     return needsToRecompile;
     936    auto disableTypeProfiler = [this] () {
     937        this->m_typeProfiler.reset(nullptr);
     938        this->m_typeProfilerLog.reset(nullptr);
     939    };
     940
     941    return disableProfilerWithRespectToCount(m_typeProfilerEnabledCount, disableTypeProfiler);
     942}
     943
     944bool VM::enableControlFlowProfiler()
     945{
     946    auto enableControlFlowProfiler = [this] () {
     947        this->m_controlFlowProfiler = std::make_unique<ControlFlowProfiler>();
     948    };
     949
     950    return enableProfilerWithRespectToCount(m_controlFlowProfilerEnabledCount, enableControlFlowProfiler);
     951}
     952
     953bool VM::disableControlFlowProfiler()
     954{
     955    auto disableControlFlowProfiler = [this] () {
     956        this->m_controlFlowProfiler.reset(nullptr);
     957    };
     958
     959    return disableProfilerWithRespectToCount(m_controlFlowProfilerEnabledCount, disableControlFlowProfiler);
    922960}
    923961
     
    928966
    929967    typeProfilerLog()->processLogEntries(ASCIILiteral("VM Dump Types"));
    930     typeProfiler()->dumpTypeProfilerData();
     968    typeProfiler()->dumpTypeProfilerData(*this);
    931969}
    932970
Note: See TracChangeset for help on using the changeset viewer.