diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp | 137 |
1 files changed, 118 insertions, 19 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp b/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp index d51a1f0d8..cf8828306 100644 --- a/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,9 +30,10 @@ #include "DFGGraph.h" #include "DFGInsertionSet.h" +#include "DFGNaturalLoops.h" #include "DFGPhase.h" #include "FTLCapabilities.h" -#include "Operations.h" +#include "JSCInlines.h" namespace JSC { namespace DFG { @@ -47,7 +48,13 @@ public: { RELEASE_ASSERT(m_graph.m_plan.mode == DFGMode); - if (!Options::useExperimentalFTL()) + if (!Options::useFTLJIT()) + return false; + + if (m_graph.m_profiledBlock->m_didFailFTLCompilation) + return false; + + if (!Options::bytecodeRangeToFTLCompile().isInRange(m_graph.m_profiledBlock->instructionCount())) return false; #if ENABLE(FTL_JIT) @@ -55,42 +62,134 @@ public: if (level == FTL::CannotCompile) return false; + if (!Options::useOSREntryToFTL()) + level = FTL::CanCompile; + + m_graph.ensureNaturalLoops(); + NaturalLoops& naturalLoops = *m_graph.m_naturalLoops; + HashMap<const NaturalLoop*, unsigned> naturalLoopToLoopHint = buildNaturalLoopToLoopHintMap(naturalLoops); + + HashMap<unsigned, LoopHintDescriptor> tierUpHierarchy; + InsertionSet insertionSet(m_graph); for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { BasicBlock* block = m_graph.block(blockIndex); if (!block) continue; - - if (block->at(0)->op() == LoopHint) { - CodeOrigin codeOrigin = block->at(0)->codeOrigin; - NodeType nodeType; - if (level == FTL::CanCompileAndOSREnter && !codeOrigin.inlineCallFrame) { - nodeType = CheckTierUpAndOSREnter; - RELEASE_ASSERT(block->bytecodeBegin == codeOrigin.bytecodeIndex); - } else - nodeType = CheckTierUpInLoop; - insertionSet.insertNode(1, SpecNone, nodeType, codeOrigin); + + for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { + Node* node = block->at(nodeIndex); + if (node->op() != LoopHint) + continue; + + NodeOrigin origin = node->origin; + bool canOSREnter = canOSREnterAtLoopHint(level, block, nodeIndex); + + NodeType tierUpType = CheckTierUpAndOSREnter; + if (!canOSREnter) + tierUpType = CheckTierUpInLoop; + insertionSet.insertNode(nodeIndex + 1, SpecNone, tierUpType, origin); + + unsigned bytecodeIndex = origin.semantic.bytecodeIndex; + if (canOSREnter) + m_graph.m_plan.tierUpAndOSREnterBytecodes.append(bytecodeIndex); + + if (const NaturalLoop* loop = naturalLoops.innerMostLoopOf(block)) { + LoopHintDescriptor descriptor; + descriptor.canOSREnter = canOSREnter; + + const NaturalLoop* outerLoop = loop; + while ((outerLoop = naturalLoops.innerMostOuterLoop(*outerLoop))) { + auto it = naturalLoopToLoopHint.find(outerLoop); + if (it != naturalLoopToLoopHint.end()) + descriptor.osrEntryCandidates.append(it->value); + } + if (!descriptor.osrEntryCandidates.isEmpty()) + tierUpHierarchy.add(bytecodeIndex, WTFMove(descriptor)); + } + break; } - - if (block->last()->op() == Return) { + + NodeAndIndex terminal = block->findTerminal(); + if (terminal.node->isFunctionTerminal()) { insertionSet.insertNode( - block->size() - 1, SpecNone, CheckTierUpAtReturn, block->last()->codeOrigin); + terminal.index, SpecNone, CheckTierUpAtReturn, terminal.node->origin); } - + insertionSet.execute(block); } - + + // Add all the candidates that can be OSR Entered. + for (auto entry : tierUpHierarchy) { + Vector<unsigned> tierUpCandidates; + for (unsigned bytecodeIndex : entry.value.osrEntryCandidates) { + auto descriptorIt = tierUpHierarchy.find(bytecodeIndex); + if (descriptorIt != tierUpHierarchy.end() + && descriptorIt->value.canOSREnter) + tierUpCandidates.append(bytecodeIndex); + } + + if (!tierUpCandidates.isEmpty()) + m_graph.m_plan.tierUpInLoopHierarchy.add(entry.key, WTFMove(tierUpCandidates)); + } + m_graph.m_plan.willTryToTierUp = true; return true; #else // ENABLE(FTL_JIT) RELEASE_ASSERT_NOT_REACHED(); return false; #endif // ENABLE(FTL_JIT) } + +private: +#if ENABLE(FTL_JIT) + struct LoopHintDescriptor { + Vector<unsigned> osrEntryCandidates; + bool canOSREnter; + }; + + bool canOSREnterAtLoopHint(FTL::CapabilityLevel level, const BasicBlock* block, unsigned nodeIndex) + { + Node* node = block->at(nodeIndex); + ASSERT(node->op() == LoopHint); + + NodeOrigin origin = node->origin; + if (level != FTL::CanCompileAndOSREnter || origin.semantic.inlineCallFrame) + return false; + + // We only put OSR checks for the first LoopHint in the block. Note that + // more than one LoopHint could happen in cases where we did a lot of CFG + // simplification in the bytecode parser, but it should be very rare. + for (unsigned subNodeIndex = nodeIndex; subNodeIndex--;) { + if (!block->at(subNodeIndex)->isSemanticallySkippable()) + return false; + } + return true; + } + + HashMap<const NaturalLoop*, unsigned> buildNaturalLoopToLoopHintMap(const NaturalLoops& naturalLoops) + { + HashMap<const NaturalLoop*, unsigned> naturalLoopsToLoopHint; + + for (BasicBlock* block : m_graph.blocksInNaturalOrder()) { + for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { + Node* node = block->at(nodeIndex); + if (node->op() != LoopHint) + continue; + + if (const NaturalLoop* loop = naturalLoops.innerMostLoopOf(block)) { + unsigned bytecodeIndex = node->origin.semantic.bytecodeIndex; + naturalLoopsToLoopHint.add(loop, bytecodeIndex); + } + break; + } + } + return naturalLoopsToLoopHint; + } +#endif }; bool performTierUpCheckInjection(Graph& graph) { - SamplingRegion samplingRegion("DFG Tier-up Check Injection"); return runPhase<TierUpCheckInjectionPhase>(graph); } |