Commit 90fce824 authored by oliver@apple.com's avatar oliver@apple.com

fourthTier: DFG should separate link phase into things that must be done...

fourthTier: DFG should separate link phase into things that must be done concurrently and things that must be done synchronously, and have a way of passing data from one to the other
https://bugs.webkit.org/show_bug.cgi?id=116060

Reviewed by Gavin Barraclough.

This introduces the concept of a DFG::Plan, which corresponds to:

- The data that the concurrent DFG or FTL need to start compiling a CodeBlock.
  This mostly includes basic things like CodeBlock*, but also a list of
  must-handle values for OSR entry.

- The data that the synchronous linker need to link in code compiled by a
  concurrent compilation thread. This is further encapsulated by DFG::Finalizer,
  since the data, and the actions that need to be taken, are different in DFG
  versus FTL. This patch also institutes the policy that the concurrent
  compilation thread shall not use LinkBuffer::performFinalization(), since that
  code assumes that it's running on the same thread that will actually run the
  code.

- The actions that need to be taken to compile code. In other words, most of the
  code that previously lived in DFGDriver.cpp now lives in
  DFG::Plan::compileInThread().

- The actions that need to be taken when synchronously linking the code. This
  includes "really" adding watchpoints and identifiers, checking watchpoint and
  chain validity, and running the DFG::Finalizer.

Currently, DFGDriver just creates a Plan and runs it synchronously. But in the
future, we will be able to malloc some Plans and enqueue them, and have the
concurrent thread dequeue them and call Plan::compileInThread().

For now, this has no behavior or performance change.

* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/LinkBuffer.cpp:
(JSC::LinkBuffer::performFinalization):
* assembler/LinkBuffer.h:
(LinkBuffer):
(JSC::LinkBuffer::LinkBuffer):
(JSC::LinkBuffer::~LinkBuffer):
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::initialize):
(JSC::DFG::AbstractState::executeEffects):
* dfg/DFGAbstractValue.cpp:
(JSC::DFG::AbstractValue::setFuturePossibleStructure):
(JSC::DFG::AbstractValue::filterFuturePossibleStructure):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::addStructureTransitionCheck):
(JSC::DFG::ByteCodeParser::handleGetById):
(JSC::DFG::ByteCodeParser::parseResolveOperations):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
(JSC::DFG::ByteCodeParser::parseCodeBlock):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
(JSC::DFG::ConstantFoldingPhase::addStructureTransitionCheck):
* dfg/DFGDriver.cpp:
(DFG):
(JSC::DFG::compile):
* dfg/DFGFailedFinalizer.cpp: Added.
(DFG):
(JSC::DFG::FailedFinalizer::FailedFinalizer):
(JSC::DFG::FailedFinalizer::~FailedFinalizer):
(JSC::DFG::FailedFinalizer::finalize):
(JSC::DFG::FailedFinalizer::finalizeFunction):
* dfg/DFGFailedFinalizer.h: Added.
(DFG):
(FailedFinalizer):
* dfg/DFGFinalizer.cpp: Added.
(DFG):
(JSC::DFG::Finalizer::Finalizer):
(JSC::DFG::Finalizer::~Finalizer):
* dfg/DFGFinalizer.h: Added.
(DFG):
(Finalizer):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::canOptimizeStringObjectAccess):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
(JSC::DFG::Graph::dump):
(DFG):
* dfg/DFGGraph.h:
(Graph):
(JSC::DFG::Graph::masqueradesAsUndefinedWatchpointIsStillValid):
(JSC::DFG::Graph::compilation):
(JSC::DFG::Graph::identifiers):
(JSC::DFG::Graph::watchpoints):
(JSC::DFG::Graph::chains):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::linkOSRExits):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):
(JSC::DFG::JITCompiler::linkFunction):
(DFG):
(JSC::DFG::JITCompiler::disassemble):
* dfg/DFGJITCompiler.h:
(JITCompiler):
(JSC::DFG::JITCompiler::addLazily):
* dfg/DFGJITFinalizer.cpp: Added.
(DFG):
(JSC::DFG::JITFinalizer::JITFinalizer):
(JSC::DFG::JITFinalizer::~JITFinalizer):
(JSC::DFG::JITFinalizer::finalize):
(JSC::DFG::JITFinalizer::finalizeFunction):
(JSC::DFG::JITFinalizer::finalizeCommon):
* dfg/DFGJITFinalizer.h: Added.
(DFG):
(JITFinalizer):
* dfg/DFGPlan.cpp: Added.
(DFG):
(JSC::DFG::dumpAndVerifyGraph):
(JSC::DFG::Plan::Plan):
(JSC::DFG::Plan::~Plan):
(JSC::DFG::Plan::compileInThread):
(JSC::DFG::Plan::isStillValid):
(JSC::DFG::Plan::reallyAdd):
(JSC::DFG::Plan::finalize):
* dfg/DFGPlan.h: Added.
(DFG):
(Plan):
(JSC::DFG::Plan::vm):
* dfg/DFGPredictionInjectionPhase.cpp:
(JSC::DFG::PredictionInjectionPhase::run):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::identifierUID):
(JSC::DFG::SpeculativeJIT::speculateStringObjectForStructure):
* dfg/DFGTypeCheckHoistingPhase.cpp:
(JSC::DFG::TypeCheckHoistingPhase::run):
* ftl/FTLGeneratedFunction.h: Added.
(FTL):
* ftl/FTLJITFinalizer.cpp: Added.
(FTL):
(JSC::FTL::JITFinalizer::JITFinalizer):
(JSC::FTL::JITFinalizer::~JITFinalizer):
(JSC::FTL::JITFinalizer::finalize):
(JSC::FTL::JITFinalizer::finalizeFunction):
* ftl/FTLJITFinalizer.h: Added.
(FTL):
(JITFinalizer):
(JSC::FTL::JITFinalizer::initializeExitThunksLinkBuffer):
(JSC::FTL::JITFinalizer::initializeEntrypointLinkBuffer):
(JSC::FTL::JITFinalizer::initializeCode):
(JSC::FTL::JITFinalizer::initializeFunction):
(JSC::FTL::JITFinalizer::initializeArityCheck):
(JSC::FTL::JITFinalizer::initializeJITCode):
* ftl/FTLLink.cpp:
(JSC::FTL::link):
* ftl/FTLLink.h:
(FTL):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::linkOSRExitsAndCompleteInitializationBlocks):
* ftl/FTLState.cpp:
(JSC::FTL::State::State):
* ftl/FTLState.h:
(FTL):
(State):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153161 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent cd1c2e74
2013-05-15 Mark Lam <mark.lam@apple.com>
Fix for broken 32-bit build in SpeculativeJIT::checkArray().
https://bugs.webkit.org/show_bug.cgi?id=116184.
Rubber stamped by Mark Hahnenberg.
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::checkArray):
2013-05-15 Filip Pizlo <fpizlo@apple.com>
fourthTier: DFG should separate link phase into things that must be done concurrently and things that must be done synchronously, and have a way of passing data from one to the other
https://bugs.webkit.org/show_bug.cgi?id=116060
Reviewed by Gavin Barraclough.
This introduces the concept of a DFG::Plan, which corresponds to:
- The data that the concurrent DFG or FTL need to start compiling a CodeBlock.
This mostly includes basic things like CodeBlock*, but also a list of
must-handle values for OSR entry.
- The data that the synchronous linker need to link in code compiled by a
concurrent compilation thread. This is further encapsulated by DFG::Finalizer,
since the data, and the actions that need to be taken, are different in DFG
versus FTL. This patch also institutes the policy that the concurrent
compilation thread shall not use LinkBuffer::performFinalization(), since that
code assumes that it's running on the same thread that will actually run the
code.
- The actions that need to be taken to compile code. In other words, most of the
code that previously lived in DFGDriver.cpp now lives in
DFG::Plan::compileInThread().
- The actions that need to be taken when synchronously linking the code. This
includes "really" adding watchpoints and identifiers, checking watchpoint and
chain validity, and running the DFG::Finalizer.
Currently, DFGDriver just creates a Plan and runs it synchronously. But in the
future, we will be able to malloc some Plans and enqueue them, and have the
concurrent thread dequeue them and call Plan::compileInThread().
For now, this has no behavior or performance change.
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/LinkBuffer.cpp:
(JSC::LinkBuffer::performFinalization):
* assembler/LinkBuffer.h:
(LinkBuffer):
(JSC::LinkBuffer::LinkBuffer):
(JSC::LinkBuffer::~LinkBuffer):
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::initialize):
(JSC::DFG::AbstractState::executeEffects):
* dfg/DFGAbstractValue.cpp:
(JSC::DFG::AbstractValue::setFuturePossibleStructure):
(JSC::DFG::AbstractValue::filterFuturePossibleStructure):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::addStructureTransitionCheck):
(JSC::DFG::ByteCodeParser::handleGetById):
(JSC::DFG::ByteCodeParser::parseResolveOperations):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
(JSC::DFG::ByteCodeParser::parseCodeBlock):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
(JSC::DFG::ConstantFoldingPhase::addStructureTransitionCheck):
* dfg/DFGDriver.cpp:
(DFG):
(JSC::DFG::compile):
* dfg/DFGFailedFinalizer.cpp: Added.
(DFG):
(JSC::DFG::FailedFinalizer::FailedFinalizer):
(JSC::DFG::FailedFinalizer::~FailedFinalizer):
(JSC::DFG::FailedFinalizer::finalize):
(JSC::DFG::FailedFinalizer::finalizeFunction):
* dfg/DFGFailedFinalizer.h: Added.
(DFG):
(FailedFinalizer):
* dfg/DFGFinalizer.cpp: Added.
(DFG):
(JSC::DFG::Finalizer::Finalizer):
(JSC::DFG::Finalizer::~Finalizer):
* dfg/DFGFinalizer.h: Added.
(DFG):
(Finalizer):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::canOptimizeStringObjectAccess):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::Graph):
(JSC::DFG::Graph::dump):
(DFG):
* dfg/DFGGraph.h:
(Graph):
(JSC::DFG::Graph::masqueradesAsUndefinedWatchpointIsStillValid):
(JSC::DFG::Graph::compilation):
(JSC::DFG::Graph::identifiers):
(JSC::DFG::Graph::watchpoints):
(JSC::DFG::Graph::chains):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::linkOSRExits):
(JSC::DFG::JITCompiler::link):
(JSC::DFG::JITCompiler::compile):
(JSC::DFG::JITCompiler::compileFunction):
(JSC::DFG::JITCompiler::linkFunction):
(DFG):
(JSC::DFG::JITCompiler::disassemble):
* dfg/DFGJITCompiler.h:
(JITCompiler):
(JSC::DFG::JITCompiler::addLazily):
* dfg/DFGJITFinalizer.cpp: Added.
(DFG):
(JSC::DFG::JITFinalizer::JITFinalizer):
(JSC::DFG::JITFinalizer::~JITFinalizer):
(JSC::DFG::JITFinalizer::finalize):
(JSC::DFG::JITFinalizer::finalizeFunction):
(JSC::DFG::JITFinalizer::finalizeCommon):
* dfg/DFGJITFinalizer.h: Added.
(DFG):
(JITFinalizer):
* dfg/DFGPlan.cpp: Added.
(DFG):
(JSC::DFG::dumpAndVerifyGraph):
(JSC::DFG::Plan::Plan):
(JSC::DFG::Plan::~Plan):
(JSC::DFG::Plan::compileInThread):
(JSC::DFG::Plan::isStillValid):
(JSC::DFG::Plan::reallyAdd):
(JSC::DFG::Plan::finalize):
* dfg/DFGPlan.h: Added.
(DFG):
(Plan):
(JSC::DFG::Plan::vm):
* dfg/DFGPredictionInjectionPhase.cpp:
(JSC::DFG::PredictionInjectionPhase::run):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::identifierUID):
(JSC::DFG::SpeculativeJIT::speculateStringObjectForStructure):
* dfg/DFGTypeCheckHoistingPhase.cpp:
(JSC::DFG::TypeCheckHoistingPhase::run):
* ftl/FTLGeneratedFunction.h: Added.
(FTL):
* ftl/FTLJITFinalizer.cpp: Added.
(FTL):
(JSC::FTL::JITFinalizer::JITFinalizer):
(JSC::FTL::JITFinalizer::~JITFinalizer):
(JSC::FTL::JITFinalizer::finalize):
(JSC::FTL::JITFinalizer::finalizeFunction):
* ftl/FTLJITFinalizer.h: Added.
(FTL):
(JITFinalizer):
(JSC::FTL::JITFinalizer::initializeExitThunksLinkBuffer):
(JSC::FTL::JITFinalizer::initializeEntrypointLinkBuffer):
(JSC::FTL::JITFinalizer::initializeCode):
(JSC::FTL::JITFinalizer::initializeFunction):
(JSC::FTL::JITFinalizer::initializeArityCheck):
(JSC::FTL::JITFinalizer::initializeJITCode):
* ftl/FTLLink.cpp:
(JSC::FTL::link):
* ftl/FTLLink.h:
(FTL):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::linkOSRExitsAndCompleteInitializationBlocks):
* ftl/FTLState.cpp:
(JSC::FTL::State::State):
* ftl/FTLState.h:
(FTL):
(State):
2013-05-14 Mark Lam <mark.lam@apple.com>
Refactor JITStubs.cpp to move CPU specific parts out into their own files.
......
......@@ -29,6 +29,7 @@
#if ENABLE(ASSEMBLER)
#include "Options.h"
#include <wtf/CompilationThread.h>
namespace JSC {
......@@ -146,6 +147,7 @@ void LinkBuffer::linkCode(void* ownerUID, JITCompilationEffort effort)
void LinkBuffer::performFinalization()
{
#ifndef NDEBUG
ASSERT(!isCompilationThread());
ASSERT(!m_completed);
ASSERT(isValid());
m_completed = true;
......
......@@ -37,6 +37,7 @@
#include "JITCompilationEffort.h"
#include "MacroAssembler.h"
#include <wtf/DataLog.h>
#include <wtf/FastAllocBase.h>
#include <wtf/Noncopyable.h>
namespace JSC {
......@@ -58,7 +59,8 @@ class VM;
// * The value referenced by a DataLabel may be set.
//
class LinkBuffer {
WTF_MAKE_NONCOPYABLE(LinkBuffer);
WTF_MAKE_NONCOPYABLE(LinkBuffer); WTF_MAKE_FAST_ALLOCATED;
typedef MacroAssemblerCodeRef CodeRef;
typedef MacroAssemblerCodePtr CodePtr;
typedef MacroAssembler::Label Label;
......@@ -86,7 +88,6 @@ public:
, m_vm(&vm)
#ifndef NDEBUG
, m_completed(false)
, m_effort(effort)
#endif
{
linkCode(ownerUID, effort);
......@@ -94,7 +95,6 @@ public:
~LinkBuffer()
{
ASSERT(m_completed || (!m_executableMemory && m_effort == JITCompilationCanFail));
}
bool didFailToAllocate() const
......@@ -264,7 +264,6 @@ private:
VM* m_vm;
#ifndef NDEBUG
bool m_completed;
JITCompilationEffort m_effort;
#endif
};
......
......@@ -135,12 +135,12 @@ void AbstractState::initialize(Graph& graph)
}
if (!block->isOSRTarget)
continue;
if (block->bytecodeBegin != graph.m_osrEntryBytecodeIndex)
if (block->bytecodeBegin != graph.m_plan.osrEntryBytecodeIndex)
continue;
for (size_t i = 0; i < graph.m_mustHandleValues.size(); ++i) {
for (size_t i = 0; i < graph.m_plan.mustHandleValues.size(); ++i) {
AbstractValue value;
value.setMostSpecific(graph, graph.m_mustHandleValues[i]);
int operand = graph.m_mustHandleValues.operandForIndex(i);
value.setMostSpecific(graph, graph.m_plan.mustHandleValues[i]);
int operand = graph.m_plan.mustHandleValues.operandForIndex(i);
block->valuesAtHead.operand(operand).merge(value);
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
dataLogF(" Initializing Block #%u, operand r%d, to ", blockIndex, operand);
......@@ -1296,7 +1296,7 @@ bool AbstractState::executeEffects(unsigned indexInBlock, Node* node)
if (Structure* structure = forNode(node->child1()).bestProvenStructure()) {
GetByIdStatus status = GetByIdStatus::computeFor(
m_graph.m_vm, structure,
m_graph.m_identifiers[node->identifierNumber()]);
m_graph.identifiers()[node->identifierNumber()]);
if (status.isSimple()) {
// Assert things that we can't handle and that the computeFor() method
// above won't be able to return.
......@@ -1363,7 +1363,7 @@ bool AbstractState::executeEffects(unsigned indexInBlock, Node* node)
// infinity of structures.
ASSERT(
value.m_futurePossibleStructure.isSubsetOf(StructureSet(node->structure()))
|| m_graph.m_watchpoints.shouldAssumeMixedState(node->structure()->transitionWatchpointSet()));
|| m_graph.watchpoints().shouldAssumeMixedState(node->structure()->transitionWatchpointSet()));
value.filter(m_graph, node->structure());
m_haveStructures = true;
......@@ -1497,7 +1497,7 @@ bool AbstractState::executeEffects(unsigned indexInBlock, Node* node)
m_graph.m_vm,
m_graph.globalObjectFor(node->codeOrigin),
structure,
m_graph.m_identifiers[node->identifierNumber()],
m_graph.identifiers()[node->identifierNumber()],
node->op() == PutByIdDirect);
if (status.isSimpleReplace()) {
forNode(node->child1()).filter(m_graph, structure);
......
......@@ -112,7 +112,7 @@ void AbstractValue::filter(Graph& graph, const StructureSet& other)
void AbstractValue::setFuturePossibleStructure(Graph& graph, Structure* structure)
{
if (graph.m_watchpoints.isStillValid(structure->transitionWatchpointSet()))
if (graph.watchpoints().isStillValid(structure->transitionWatchpointSet()))
m_futurePossibleStructure = structure;
else
m_futurePossibleStructure.makeTop();
......@@ -120,7 +120,7 @@ void AbstractValue::setFuturePossibleStructure(Graph& graph, Structure* structur
void AbstractValue::filterFuturePossibleStructure(Graph& graph, Structure* structure)
{
if (graph.m_watchpoints.isStillValid(structure->transitionWatchpointSet()))
if (graph.watchpoints().isStillValid(structure->transitionWatchpointSet()))
m_futurePossibleStructure.filter(StructureAbstractValue(structure));
}
......
......@@ -789,7 +789,7 @@ private:
Node* objectNode = cellConstant(object);
if (object->structure() == structure
&& m_graph.m_watchpoints.isStillValid(structure->transitionWatchpointSet())) {
&& m_graph.watchpoints().isStillValid(structure->transitionWatchpointSet())) {
addToGraph(StructureTransitionWatchpoint, OpInfo(structure), objectNode);
return objectNode;
}
......@@ -1212,13 +1212,13 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn
// the inputs must be kept alive whatever exits the intrinsic may do.
addToGraph(Phantom, callTarget);
emitArgumentPhantoms(registerOffset, argumentCountIncludingThis, kind);
if (m_graph.m_compilation)
m_graph.m_compilation->noticeInlinedCall();
if (m_graph.compilation())
m_graph.compilation()->noticeInlinedCall();
return;
}
} else if (handleInlining(usesResult, callTarget, resultOperand, callLinkStatus, registerOffset, argumentCountIncludingThis, nextOffset, kind)) {
if (m_graph.m_compilation)
m_graph.m_compilation->noticeInlinedCall();
if (m_graph.compilation())
m_graph.compilation()->noticeInlinedCall();
return;
}
......@@ -1728,15 +1728,15 @@ void ByteCodeParser::handleGetById(
// execution if it doesn't have a prediction, so we do it manually.
if (prediction == SpecNone)
addToGraph(ForceOSRExit);
else if (m_graph.m_compilation)
m_graph.m_compilation->noticeInlinedGetById();
else if (m_graph.compilation())
m_graph.compilation()->noticeInlinedGetById();
Node* originalBaseForBaselineJIT = base;
addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base);
if (getByIdStatus.chain()) {
m_graph.m_chains.addLazily(getByIdStatus.chain());
m_graph.chains().addLazily(getByIdStatus.chain());
Structure* currentStructure = getByIdStatus.structureSet().singletonStructure();
JSObject* currentObject = 0;
for (unsigned i = 0; i < getByIdStatus.chain()->size(); ++i) {
......@@ -1881,7 +1881,7 @@ bool ByteCodeParser::parseResolveOperations(SpeculatedType prediction, unsigned
ResolveOperation* resolveValueOperation = pc;
switch (resolveValueOperation->m_operation) {
case ResolveOperation::GetAndReturnGlobalProperty: {
ResolveGlobalStatus status = ResolveGlobalStatus::computeFor(m_inlineStackTop->m_profiledBlock, m_currentIndex, resolveValueOperation, m_graph.m_identifiers[identifier]);
ResolveGlobalStatus status = ResolveGlobalStatus::computeFor(m_inlineStackTop->m_profiledBlock, m_currentIndex, resolveValueOperation, m_graph.identifiers()[identifier]);
if (status.isSimple()) {
ASSERT(status.structure());
......@@ -1917,9 +1917,9 @@ bool ByteCodeParser::parseResolveOperations(SpeculatedType prediction, unsigned
JSGlobalObject* globalObject = m_inlineStackTop->m_codeBlock->globalObject();
StringImpl* uid = m_graph.m_identifiers[identifier];
StringImpl* uid = m_graph.identifiers()[identifier];
SymbolTableEntry entry = globalObject->symbolTable()->get(uid);
if (!m_graph.m_watchpoints.isStillValid(entry.watchpointSet())) {
if (!m_graph.watchpoints().isStillValid(entry.watchpointSet())) {
*value = addToGraph(GetGlobalVar, OpInfo(globalObject->assertRegisterIsInThisObject(pc->m_registerAddress)), OpInfo(prediction));
return true;
}
......@@ -2011,8 +2011,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
m_currentInstruction = currentInstruction; // Some methods want to use this, and we'd rather not thread it through calls.
OpcodeID opcodeID = interpreter->getOpcodeID(currentInstruction->u.opcode);
if (m_graph.m_compilation && opcodeID != op_call_put_result) {
addToGraph(CountExecution, OpInfo(m_graph.m_compilation->executionCounterFor(
if (m_graph.compilation() && opcodeID != op_call_put_result) {
addToGraph(CountExecution, OpInfo(m_graph.compilation()->executionCounterFor(
Profiler::OriginStack(*m_vm->m_perBytecodeProfiler, m_codeBlock, currentCodeOrigin()))));
}
......@@ -2571,7 +2571,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
Node* base = get(currentInstruction[2].u.operand);
unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
StringImpl* uid = m_graph.m_identifiers[identifierNumber];
StringImpl* uid = m_graph.identifiers()[identifierNumber];
GetByIdStatus getByIdStatus = GetByIdStatus::computeFor(
m_inlineStackTop->m_profiledBlock, m_currentIndex, uid);
......@@ -2594,7 +2594,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
PutByIdStatus putByIdStatus = PutByIdStatus::computeFor(
m_inlineStackTop->m_profiledBlock,
m_currentIndex,
m_graph.m_identifiers[identifierNumber]);
m_graph.identifiers()[identifierNumber]);
bool canCountAsInlined = true;
if (!putByIdStatus.isSet()) {
addToGraph(ForceOSRExit);
......@@ -2624,7 +2624,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
&& (!putByIdStatus.structureChain()
|| putByIdStatus.structureChain()->isStillValid())) {
m_graph.m_chains.addLazily(putByIdStatus.structureChain());
m_graph.chains().addLazily(putByIdStatus.structureChain());
addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
if (!direct) {
......@@ -2693,8 +2693,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
canCountAsInlined = false;
}
if (canCountAsInlined && m_graph.m_compilation)
m_graph.m_compilation->noticeInlinedPutById();
if (canCountAsInlined && m_graph.compilation())
m_graph.compilation()->noticeInlinedPutById();
NEXT_OPCODE(op_put_by_id);
}
......@@ -2717,7 +2717,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock;
JSGlobalObject* globalObject = codeBlock->globalObject();
unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[4].u.operand];
StringImpl* uid = m_graph.m_identifiers[identifierNumber];
StringImpl* uid = m_graph.identifiers()[identifierNumber];
SymbolTableEntry entry = globalObject->symbolTable()->get(uid);
if (!entry.couldBeWatched()) {
addToGraph(
......@@ -3193,7 +3193,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case PutToBaseOperation::GlobalVariablePutChecked: {
CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock;
JSGlobalObject* globalObject = codeBlock->globalObject();
SymbolTableEntry entry = globalObject->symbolTable()->get(m_graph.m_identifiers[identifier]);
SymbolTableEntry entry = globalObject->symbolTable()->get(m_graph.identifiers()[identifier]);
if (entry.couldBeWatched()) {
addToGraph(PutGlobalVarCheck,
OpInfo(codeBlock->globalObject()->assertRegisterIsInThisObject(putToBase->m_registerAddress)),
......@@ -3566,9 +3566,9 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
for (size_t i = 0; i < codeBlock->numberOfIdentifiers(); ++i) {
StringImpl* rep = codeBlock->identifier(i).impl();
BorrowedIdentifierMap::AddResult result = byteCodeParser->m_identifierMap.add(rep, byteCodeParser->m_graph.m_identifiers.numberOfIdentifiers());
BorrowedIdentifierMap::AddResult result = byteCodeParser->m_identifierMap.add(rep, byteCodeParser->m_graph.identifiers().numberOfIdentifiers());
if (result.isNewEntry)
byteCodeParser->m_graph.m_identifiers.addLazily(rep);
byteCodeParser->m_graph.identifiers().addLazily(rep);
m_identifierRemap[i] = result.iterator->value;
}
for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i) {
......@@ -3636,8 +3636,8 @@ void ByteCodeParser::parseCodeBlock()
{
CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock;
if (m_graph.m_compilation) {
m_graph.m_compilation->addProfiledBytecodes(
if (m_graph.compilation()) {
m_graph.compilation()->addProfiledBytecodes(
*m_vm->m_perBytecodeProfiler, m_inlineStackTop->m_profiledBlock);
}
......
......@@ -155,7 +155,7 @@ private:
bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
GetByIdStatus status = GetByIdStatus::computeFor(
vm(), structure, m_graph.m_identifiers[identifierNumber]);
vm(), structure, m_graph.identifiers()[identifierNumber]);
if (!status.isSimple()) {
// FIXME: We could handle prototype cases.
......@@ -223,7 +223,7 @@ private:
vm(),
m_graph.globalObjectFor(codeOrigin),
structure,
m_graph.m_identifiers[identifierNumber],
m_graph.identifiers()[identifierNumber],
node->op() == PutByIdDirect);
if (!status.isSimpleReplace() && !status.isSimpleTransition())
......@@ -261,7 +261,7 @@ private:
structure->storedPrototype().asCell());
}
m_graph.m_chains.addLazily(status.structureChain());
m_graph.chains().addLazily(status.structureChain());
for (unsigned i = 0; i < status.structureChain()->size(); ++i) {
JSValue prototype = status.structureChain()->at(i)->storedPrototype();
......@@ -399,7 +399,7 @@ private:
Node* weakConstant = m_insertionSet.insertNode(
indexInBlock, speculationFromValue(cell), WeakJSConstant, codeOrigin, OpInfo(cell));
if (m_graph.m_watchpoints.isStillValid(cell->structure()->transitionWatchpointSet())) {
if (m_graph.watchpoints().isStillValid(cell->structure()->transitionWatchpointSet())) {
m_insertionSet.insertNode(
indexInBlock, SpecNone, StructureTransitionWatchpoint, codeOrigin,
OpInfo(cell->structure()), Edge(weakConstant, CellUse));
......
......@@ -29,34 +29,15 @@
#include "JSObject.h"
#include "JSString.h"
#if ENABLE(DFG_JIT)
#include "DFGArgumentsSimplificationPhase.h"
#include "DFGBackwardsPropagationPhase.h"
#include "DFGByteCodeParser.h"
#include "DFGCFAPhase.h"
#include "DFGCFGSimplificationPhase.h"
#include "DFGCPSRethreadingPhase.h"
#include "DFGCSEPhase.h"
#include "DFGConstantFoldingPhase.h"
#include "DFGDCEPhase.h"
#include "DFGFixupPhase.h"
#include "DFGJITCompiler.h"
#include "DFGPredictionInjectionPhase.h"
#include "DFGPredictionPropagationPhase.h"
#include "DFGTypeCheckHoistingPhase.h"
#include "DFGUnificationPhase.h"
#include "DFGValidate.h"
#include "DFGVirtualRegisterAllocationPhase.h"
#include "FTLCapabilities.h"
#include "FTLCompile.h"
#include "FTLLink.h"
#include "FTLLowerDFGToLLVM.h"
#include "FTLState.h"
#include "DFGJITCode.h"
#include "DFGPlan.h"
#include "DFGThunks.h"
#include "FTLThunks.h"
#include "JITCode.h"
#include "Operations.h"
#include "Options.h"
#include <wtf/CompilationThread.h>
namespace JSC { namespace DFG {
......@@ -67,23 +48,9 @@ unsigned getNumCompilations()
return numCompilations;
}
static void dumpAndVerifyGraph(Graph& graph, const char* text)
{
GraphDumpMode modeForFinalValidate = DumpGraph;
if (verboseCompilationEnabled()) {
dataLog(text, "\n");
graph.dump();
modeForFinalValidate = DontDumpGraph;
}
if (validationEnabled())
validate(graph, modeForFinalValidate);
}
enum CompileMode { CompileFunction, CompileOther };
static bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlock, RefPtr<JSC::JITCode>& jitCode, MacroAssemblerCodePtr* jitCodeWithArityCheck, unsigned osrEntryBytecodeIndex)
{
SamplingRegion samplingRegion("DFG Compilation (Driver)");
CompilationScope compilationScope;
numCompilations++;
......@@ -102,6 +69,19 @@ static bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
if (logCompilationChanges())
dataLog("DFG compiling ", *codeBlock, ", number of instructions = ", codeBlock->instructionCount(), "\n");
// Make sure that any stubs that the DFG is going to use are initialized. We want to
// make sure that al JIT code generation does finalization on the main thread.
exec->vm().getCTIStub(osrExitGenerationThunkGenerator);
exec->vm().getCTIStub(throwExceptionFromCallSlowPathGenerator);
exec->vm().getCTIStub(linkCallThunkGenerator);
exec->vm().getCTIStub(linkConstructThunkGenerator);
exec->vm().getCTIStub(linkClosureCallThunkGenerator);
exec->vm().getCTIStub(virtualCallThunkGenerator);
exec->vm().getCTIStub(virtualConstructThunkGenerator);
#if ENABLE(FTL_JIT)
exec->vm().getCTIStub(FTL::osrExitGenerationThunkGenerator);
#endif
// Derive our set of must-handle values. The compilation must be at least conservative
// enough to allow for OSR entry with these values.
unsigned numVarsWithValues;
......@@ -109,9 +89,9 @@ static bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
numVarsWithValues = codeBlock->m_numVars;
else
numVarsWithValues = 0;
Operands<JSValue> mustHandleValues(codeBlock->numParameters(), numVarsWithValues);
for (size_t i = 0; i < mustHandleValues.size(); ++i) {
int operand = mustHandleValues.operandForIndex(i);
Plan plan(compileMode, codeBlock, osrEntryBytecodeIndex, numVarsWithValues);
for (size_t i = 0; i < plan.mustHandleValues.size(); ++i) {
int operand = plan.mustHandleValues.operandForIndex(i);
if (operandIsArgument(operand)
&& !operandToArgument(operand)
&& compileMode == CompileFunction
......@@ -120,92 +100,15 @@ static bool compile(CompileMode compileMode, ExecState* exec, CodeBlock* codeBlo
// also never be used. It doesn't matter what we put into the value for this,
// but it has to be an actual value that can be grokked by subsequent DFG passes,
// so we sanitize it here by turning it into Undefined.
mustHandleValues[i] = jsUndefined();
plan.mustHandleValues[i] = jsUndefined();
} else
mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
plan.mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
}
Graph dfg(exec->vm(), codeBlock, osrEntryBytecodeIndex, mustHandleValues);
if (!parse(dfg))
plan.compileInThread();
if (plan.finalize(jitCode, jitCodeWithArityCheck) != CompilationSuccessful)
return false;
// By this point the DFG bytecode parser will have potentially mutated various tables
// in the CodeBlock. This is a good time to perform an early shrink, which is more
// powerful than a late one. It's safe to do so because we haven't generated any code
// that references any of the tables directly, yet.
codeBlock->shrinkToFit(CodeBlock::EarlyShrink);
if (validationEnabled())
validate(dfg);
performCPSRethreading(dfg);
performUnification(dfg);
performPredictionInjection(dfg);
if (validationEnabled())
validate(dfg);
performBackwardsPropagation(dfg);
performPredictionPropagation(dfg);
performFixup(dfg);
performTypeCheckHoisting(dfg);
dfg.m_fixpointState = FixpointNotConverged;
performCSE(dfg);
performArgumentsSimplification(dfg);
performCPSRethreading(dfg); // This should usually be a no-op since CSE rarely dethreads, and arguments simplification rarely does anything.
performCFA(dfg);
performConstantFolding(dfg);
performCFGSimplification(dfg);
dfg.m_fixpointState = FixpointConverged;
performStoreElimination(dfg);
performCPSRethreading(dfg);
performDCE(dfg);
#if ENABLE(FTL_JIT)
if (Options::useExperimentalFTL()
&& compileMode == CompileFunction
&& FTL::canCompile(dfg)) {
dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:");
// FIXME: Support OSR entry.
// https://bugs.webkit.org/show_bug.cgi?id=113625
FTL::State state(dfg);
FTL::lowerDFGToLLVM(state);
FTL::compile(state);
compilationScope.leaveEarly();
return FTL::link(state, jitCode, *jitCodeWithArityCheck);
}
#endif // ENABLE(FTL_JIT)
performVirtualRegisterAllocation(dfg);
dumpAndVerifyGraph(dfg, "Graph after optimization:");
JITCompiler dataFlowJIT(dfg);
bool result;
if (compileMode == CompileFunction) {
ASSERT(jitCodeWithArityCheck);