Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (224137 => 224138)
--- trunk/Source/_javascript_Core/ChangeLog 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-10-28 01:03:22 UTC (rev 224138)
@@ -1,3 +1,79 @@
+2017-10-27 Saam Barati <sbar...@apple.com>
+
+ Bytecode liveness should live on UnlinkedCodeBlock so it can be shared amongst CodeBlocks
+ https://bugs.webkit.org/show_bug.cgi?id=178949
+
+ Reviewed by Keith Miller.
+
+ This patch stores BytecodeLiveness on UnlinkedCodeBlock instead of CodeBlock
+ so that we don't need to recompute liveness for the same UnlinkedCodeBlock
+ more than once. To do this, this patch solidifies the invariant that CodeBlock
+ linking can't do anything that would change the result of liveness. For example,
+ it can't introduce new locals. This invariant was met my JSC before, because we
+ didn't do anything in bytecode linking that would change liveness. However, it is
+ now a correctness requirement that we don't do anything that would change the
+ result of running liveness. To support this change, I've refactored BytecodeGraph
+ to not be tied to a CodeBlockType*. Things that perform liveness will pass in
+ CodeBlockType* and the instruction stream as needed. This means that we may
+ compute liveness with one CodeBlock*'s instruction stream, and then perform
+ queries on that analysis with a different CodeBlock*'s instruction stream.
+
+ This seems to be a 2% JSBench progression.
+
+ * bytecode/BytecodeGeneratorification.cpp:
+ (JSC::BytecodeGeneratorification::BytecodeGeneratorification):
+ (JSC::BytecodeGeneratorification::graph):
+ (JSC::BytecodeGeneratorification::storageForGeneratorLocal):
+ (JSC::GeneratorLivenessAnalysis::run):
+ (JSC::BytecodeGeneratorification::run):
+ * bytecode/BytecodeGraph.h:
+ (JSC::BytecodeGraph::BytecodeGraph):
+ (JSC::BytecodeGraph::codeBlock const): Deleted.
+ (JSC::BytecodeGraph::instructions): Deleted.
+ (JSC::BytecodeGraph<Block>::BytecodeGraph): Deleted.
+ * bytecode/BytecodeLivenessAnalysis.cpp:
+ (JSC::BytecodeLivenessAnalysis::BytecodeLivenessAnalysis):
+ (JSC::BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset):
+ (JSC::BytecodeLivenessAnalysis::computeFullLiveness):
+ (JSC::BytecodeLivenessAnalysis::computeKills):
+ (JSC::BytecodeLivenessAnalysis::dumpResults):
+ (JSC::BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset): Deleted.
+ (JSC::BytecodeLivenessAnalysis::compute): Deleted.
+ * bytecode/BytecodeLivenessAnalysis.h:
+ * bytecode/BytecodeLivenessAnalysisInlines.h:
+ (JSC::BytecodeLivenessPropagation::stepOverInstruction):
+ (JSC::BytecodeLivenessPropagation::computeLocalLivenessForBytecodeOffset):
+ (JSC::BytecodeLivenessPropagation::computeLocalLivenessForBlock):
+ (JSC::BytecodeLivenessPropagation::getLivenessInfoAtBytecodeOffset):
+ (JSC::BytecodeLivenessPropagation::runLivenessFixpoint):
+ * bytecode/BytecodeRewriter.cpp:
+ (JSC::BytecodeRewriter::applyModification):
+ (JSC::BytecodeRewriter::execute):
+ (JSC::BytecodeRewriter::adjustJumpTargetsInFragment):
+ * bytecode/BytecodeRewriter.h:
+ (JSC::BytecodeRewriter::BytecodeRewriter):
+ (JSC::BytecodeRewriter::removeBytecode):
+ (JSC::BytecodeRewriter::graph):
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::finishCreation):
+ (JSC::CodeBlock::ensureCatchLivenessIsComputedForBytecodeOffsetSlow):
+ (JSC::CodeBlock::validate):
+ (JSC::CodeBlock::livenessAnalysisSlow): Deleted.
+ * bytecode/CodeBlock.h:
+ (JSC::CodeBlock::livenessAnalysis):
+ * bytecode/UnlinkedCodeBlock.cpp:
+ (JSC::UnlinkedCodeBlock::applyModification):
+ (JSC::UnlinkedCodeBlock::livenessAnalysisSlow):
+ * bytecode/UnlinkedCodeBlock.h:
+ (JSC::UnlinkedCodeBlock::livenessAnalysis):
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::livenessFor):
+ (JSC::DFG::Graph::killsFor):
+ * dfg/DFGPlan.cpp:
+ (JSC::DFG::Plan::cleanMustHandleValuesIfNecessary):
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+
2017-10-27 Keith Miller <keith_mil...@apple.com>
Add unified source list files and build scripts to Xcode project navigator
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeGeneratorification.cpp (224137 => 224138)
--- trunk/Source/_javascript_Core/bytecode/BytecodeGeneratorification.cpp 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeGeneratorification.cpp 2017-10-28 01:03:22 UTC (rev 224138)
@@ -53,13 +53,15 @@
typedef Vector<YieldData> Yields;
BytecodeGeneratorification(UnlinkedCodeBlock* codeBlock, UnlinkedCodeBlock::UnpackedInstructions& instructions, SymbolTable* generatorFrameSymbolTable, int generatorFrameSymbolTableIndex)
- : m_graph(codeBlock, instructions)
+ : m_codeBlock(codeBlock)
+ , m_instructions(instructions)
+ , m_graph(m_codeBlock, m_instructions)
, m_generatorFrameSymbolTable(*codeBlock->vm(), generatorFrameSymbolTable)
, m_generatorFrameSymbolTableIndex(generatorFrameSymbolTableIndex)
{
for (BytecodeBasicBlock* block : m_graph) {
for (unsigned bytecodeOffset : block->offsets()) {
- const UnlinkedInstruction* pc = &m_graph.instructions()[bytecodeOffset];
+ const UnlinkedInstruction* pc = &instructions[bytecodeOffset];
switch (pc->u.opcode) {
case op_enter: {
m_enterPoint = bytecodeOffset;
@@ -91,7 +93,7 @@
void run();
- BytecodeGraph<UnlinkedCodeBlock>& graph() { return m_graph; }
+ BytecodeGraph& graph() { return m_graph; }
const Yields& yields() const
{
@@ -121,10 +123,9 @@
if (std::optional<Storage> storage = m_storages[index])
return *storage;
- UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();
Identifier identifier = Identifier::fromUid(PrivateName());
- unsigned identifierIndex = codeBlock->numberOfIdentifiers();
- codeBlock->addIdentifier(identifier);
+ unsigned identifierIndex = m_codeBlock->numberOfIdentifiers();
+ m_codeBlock->addIdentifier(identifier);
ScopeOffset scopeOffset = m_generatorFrameSymbolTable->takeNextScopeOffset(NoLockingNecessary);
m_generatorFrameSymbolTable->set(NoLockingNecessary, identifier.impl(), SymbolTableEntry(VarOffset(scopeOffset)));
@@ -138,7 +139,9 @@
}
unsigned m_enterPoint { 0 };
- BytecodeGraph<UnlinkedCodeBlock> m_graph;
+ UnlinkedCodeBlock* m_codeBlock;
+ UnlinkedCodeBlock::UnpackedInstructions& m_instructions;
+ BytecodeGraph m_graph;
Vector<std::optional<Storage>> m_storages;
Yields m_yields;
Strong<SymbolTable> m_generatorFrameSymbolTable;
@@ -152,15 +155,15 @@
{
}
- void run()
+ void run(UnlinkedCodeBlock* codeBlock, UnlinkedCodeBlock::UnpackedInstructions& instructions)
{
// Perform modified liveness analysis to determine which locals are live at the merge points.
// This produces the conservative results for the question, "which variables should be saved and resumed?".
- runLivenessFixpoint(m_generatorification.graph());
+ runLivenessFixpoint(codeBlock, instructions, m_generatorification.graph());
for (YieldData& data : m_generatorification.yields())
- data.liveness = getLivenessInfoAtBytecodeOffset(m_generatorification.graph(), data.point + opcodeLength(op_yield));
+ data.liveness = getLivenessInfoAtBytecodeOffset(codeBlock, instructions, m_generatorification.graph(), data.point + opcodeLength(op_yield));
}
private:
@@ -173,18 +176,17 @@
{
GeneratorLivenessAnalysis pass(*this);
- pass.run();
+ pass.run(m_codeBlock, m_instructions);
}
- UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();
- BytecodeRewriter rewriter(m_graph);
+ BytecodeRewriter rewriter(m_graph, m_codeBlock, m_instructions);
// Setup the global switch for the generator.
{
unsigned nextToEnterPoint = enterPoint() + opcodeLength(op_enter);
- unsigned switchTableIndex = m_graph.codeBlock()->numberOfSwitchJumpTables();
+ unsigned switchTableIndex = m_codeBlock->numberOfSwitchJumpTables();
VirtualRegister state = virtualRegisterForArgument(static_cast<int32_t>(JSGeneratorFunction::GeneratorArgument::State));
- auto& jumpTable = m_graph.codeBlock()->addSwitchJumpTable();
+ auto& jumpTable = m_codeBlock->addSwitchJumpTable();
jumpTable.min = 0;
jumpTable.branchOffsets.resize(m_yields.size() + 1);
jumpTable.branchOffsets.fill(0);
@@ -227,7 +229,7 @@
VirtualRegister operand = virtualRegisterForLocal(index);
Storage storage = storageForGeneratorLocal(index);
- UnlinkedValueProfile profile = ""
+ UnlinkedValueProfile profile = ""
fragment.appendInstruction(
op_get_from_scope,
operand.offset(), // dst
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeGraph.h (224137 => 224138)
--- trunk/Source/_javascript_Core/bytecode/BytecodeGraph.h 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeGraph.h 2017-10-28 01:03:22 UTC (rev 224138)
@@ -35,23 +35,17 @@
class BytecodeBasicBlock;
-template<typename Block>
class BytecodeGraph {
WTF_MAKE_FAST_ALLOCATED;
WTF_MAKE_NONCOPYABLE(BytecodeGraph);
public:
- typedef Block CodeBlock;
- typedef typename Block::Instruction Instruction;
typedef Vector<std::unique_ptr<BytecodeBasicBlock>> BasicBlocksVector;
- typedef WTF::IndexedContainerIterator<BytecodeGraph<Block>> iterator;
+ typedef WTF::IndexedContainerIterator<BytecodeGraph> iterator;
- inline BytecodeGraph(Block*, typename Block::UnpackedInstructions&);
+ template <typename CodeBlockType>
+ inline BytecodeGraph(CodeBlockType*, typename CodeBlockType::UnpackedInstructions&);
- Block* codeBlock() const { return m_codeBlock; }
-
- typename Block::UnpackedInstructions& instructions() { return m_instructions; }
-
WTF::IteratorRange<BasicBlocksVector::reverse_iterator> basicBlocksInReverseOrder()
{
return WTF::makeIteratorRange(m_basicBlocks.rbegin(), m_basicBlocks.rend());
@@ -106,19 +100,14 @@
BytecodeBasicBlock* last() { return at(size() - 1); }
private:
- Block* m_codeBlock;
BasicBlocksVector m_basicBlocks;
- typename Block::UnpackedInstructions& m_instructions;
};
-template<typename Block>
-BytecodeGraph<Block>::BytecodeGraph(Block* codeBlock, typename Block::UnpackedInstructions& instructions)
- : m_codeBlock(codeBlock)
- , m_instructions(instructions)
+template<typename CodeBlockType>
+BytecodeGraph::BytecodeGraph(CodeBlockType* codeBlock, typename CodeBlockType::UnpackedInstructions& instructions)
{
- ASSERT(m_codeBlock);
- BytecodeBasicBlock::compute(m_codeBlock, instructions.begin(), instructions.size(), m_basicBlocks);
+ BytecodeBasicBlock::compute(codeBlock, instructions.begin(), instructions.size(), m_basicBlocks);
ASSERT(m_basicBlocks.size());
}
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.cpp (224137 => 224138)
--- trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.cpp 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.cpp 2017-10-28 01:03:22 UTC (rev 224138)
@@ -40,10 +40,13 @@
BytecodeLivenessAnalysis::BytecodeLivenessAnalysis(CodeBlock* codeBlock)
: m_graph(codeBlock, codeBlock->instructions())
{
- compute();
+ runLivenessFixpoint(codeBlock, codeBlock->instructions(), m_graph);
+
+ if (Options::dumpBytecodeLivenessResults())
+ dumpResults(codeBlock);
}
-void BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset, FastBitVector& result)
+void BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, FastBitVector& result)
{
BytecodeBasicBlock* block = m_graph.findBasicBlockForBytecodeOffset(bytecodeOffset);
ASSERT(block);
@@ -50,30 +53,20 @@
ASSERT(!block->isEntryBlock());
ASSERT(!block->isExitBlock());
result.resize(block->out().numBits());
- computeLocalLivenessForBytecodeOffset(m_graph, block, bytecodeOffset, result);
+ computeLocalLivenessForBytecodeOffset(codeBlock, codeBlock->instructions(), m_graph, block, bytecodeOffset, result);
}
-bool BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset)
+FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset)
{
- if (operandIsAlwaysLive(operand))
- return true;
- FastBitVector result;
- getLivenessInfoAtBytecodeOffset(bytecodeOffset, result);
- return operandThatIsNotAlwaysLiveIsLive(result, operand);
-}
-
-FastBitVector BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset)
-{
FastBitVector out;
- getLivenessInfoAtBytecodeOffset(bytecodeOffset, out);
+ getLivenessInfoAtBytecodeOffset(codeBlock, bytecodeOffset, out);
return out;
}
-void BytecodeLivenessAnalysis::computeFullLiveness(FullBytecodeLiveness& result)
+void BytecodeLivenessAnalysis::computeFullLiveness(CodeBlock* codeBlock, FullBytecodeLiveness& result)
{
FastBitVector out;
- CodeBlock* codeBlock = m_graph.codeBlock();
-
+
result.m_map.resize(codeBlock->instructions().size());
for (std::unique_ptr<BytecodeBasicBlock>& block : m_graph.basicBlocksInReverseOrder()) {
@@ -84,17 +77,17 @@
for (unsigned i = block->offsets().size(); i--;) {
unsigned bytecodeOffset = block->offsets()[i];
- stepOverInstruction(m_graph, bytecodeOffset, out);
+ stepOverInstruction(codeBlock, codeBlock->instructions(), m_graph, bytecodeOffset, out);
result.m_map[bytecodeOffset] = out;
}
}
}
-void BytecodeLivenessAnalysis::computeKills(BytecodeKills& result)
+void BytecodeLivenessAnalysis::computeKills(CodeBlock* codeBlock, BytecodeKills& result)
{
+ UNUSED_PARAM(result);
FastBitVector out;
-
- CodeBlock* codeBlock = m_graph.codeBlock();
+
result.m_codeBlock = codeBlock;
result.m_killSets = std::make_unique<BytecodeKills::KillSet[]>(codeBlock->instructions().size());
@@ -107,7 +100,7 @@
for (unsigned i = block->offsets().size(); i--;) {
unsigned bytecodeOffset = block->offsets()[i];
stepOverInstruction(
- m_graph, bytecodeOffset,
+ codeBlock, codeBlock->instructions(), m_graph, bytecodeOffset,
[&] (unsigned index) {
// This is for uses.
if (out[index])
@@ -123,9 +116,8 @@
}
}
-void BytecodeLivenessAnalysis::dumpResults()
+void BytecodeLivenessAnalysis::dumpResults(CodeBlock* codeBlock)
{
- CodeBlock* codeBlock = m_graph.codeBlock();
dataLog("\nDumping bytecode liveness for ", *codeBlock, ":\n");
Instruction* instructionsBegin = codeBlock->instructions().begin();
unsigned i = 0;
@@ -178,7 +170,7 @@
const Instruction* currentInstruction = &instructionsBegin[bytecodeOffset];
dataLogF("Live variables:");
- FastBitVector liveBefore = getLivenessInfoAtBytecodeOffset(bytecodeOffset);
+ FastBitVector liveBefore = getLivenessInfoAtBytecodeOffset(codeBlock, bytecodeOffset);
dumpBitVector(liveBefore);
dataLogF("\n");
codeBlock->dumpBytecode(WTF::dataFile(), instructionsBegin, currentInstruction);
@@ -195,12 +187,4 @@
}
}
-void BytecodeLivenessAnalysis::compute()
-{
- runLivenessFixpoint(m_graph);
-
- if (Options::dumpBytecodeLivenessResults())
- dumpResults();
-}
-
} // namespace JSC
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.h (224137 => 224138)
--- trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.h 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysis.h 2017-10-28 01:03:22 UTC (rev 224138)
@@ -37,17 +37,17 @@
class BytecodeLivenessPropagation {
protected:
- template<typename Graph, typename UseFunctor, typename DefFunctor> void stepOverInstruction(Graph&, unsigned bytecodeOffset, const UseFunctor&, const DefFunctor&);
+ template<typename CodeBlockType, typename Instructions, typename UseFunctor, typename DefFunctor> void stepOverInstruction(CodeBlockType*, const Instructions&, BytecodeGraph&, unsigned bytecodeOffset, const UseFunctor&, const DefFunctor&);
- template<typename Graph> void stepOverInstruction(Graph&, unsigned bytecodeOffset, FastBitVector& out);
+ template<typename CodeBlockType, typename Instructions> void stepOverInstruction(CodeBlockType*, const Instructions&, BytecodeGraph&, unsigned bytecodeOffset, FastBitVector& out);
- template<typename Graph> bool computeLocalLivenessForBytecodeOffset(Graph&, BytecodeBasicBlock*, unsigned targetOffset, FastBitVector& result);
+ template<typename CodeBlockType, typename Instructions> bool computeLocalLivenessForBytecodeOffset(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock*, unsigned targetOffset, FastBitVector& result);
- template<typename Graph> bool computeLocalLivenessForBlock(Graph&, BytecodeBasicBlock*);
+ template<typename CodeBlockType, typename Instructions> bool computeLocalLivenessForBlock(CodeBlockType*, const Instructions&, BytecodeGraph&, BytecodeBasicBlock*);
- template<typename Graph> FastBitVector getLivenessInfoAtBytecodeOffset(Graph&, unsigned bytecodeOffset);
+ template<typename CodeBlockType, typename Instructions> FastBitVector getLivenessInfoAtBytecodeOffset(CodeBlockType*, const Instructions&, BytecodeGraph&, unsigned bytecodeOffset);
- template<typename Graph> void runLivenessFixpoint(Graph&);
+ template<typename CodeBlockType, typename Instructions> void runLivenessFixpoint(CodeBlockType*, const Instructions&, BytecodeGraph&);
};
class BytecodeLivenessAnalysis : private BytecodeLivenessPropagation {
@@ -57,19 +57,17 @@
friend class BytecodeLivenessPropagation;
BytecodeLivenessAnalysis(CodeBlock*);
- bool operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset);
- FastBitVector getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset);
+ FastBitVector getLivenessInfoAtBytecodeOffset(CodeBlock*, unsigned bytecodeOffset);
- void computeFullLiveness(FullBytecodeLiveness& result);
- void computeKills(BytecodeKills& result);
+ void computeFullLiveness(CodeBlock*, FullBytecodeLiveness& result);
+ void computeKills(CodeBlock*, BytecodeKills& result);
private:
- void compute();
- void dumpResults();
+ void dumpResults(CodeBlock*);
- void getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset, FastBitVector&);
+ void getLivenessInfoAtBytecodeOffset(CodeBlock*, unsigned bytecodeOffset, FastBitVector&);
- BytecodeGraph<CodeBlock> m_graph;
+ BytecodeGraph m_graph;
};
inline bool operandIsAlwaysLive(int operand);
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysisInlines.h (224137 => 224138)
--- trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysisInlines.h 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeLivenessAnalysisInlines.h 2017-10-28 01:03:22 UTC (rev 224138)
@@ -61,8 +61,8 @@
// Simplified interface to bytecode use/def, which determines defs first and then uses, and includes
// exception handlers in the uses.
-template<typename Graph, typename UseFunctor, typename DefFunctor>
-inline void BytecodeLivenessPropagation::stepOverInstruction(Graph& graph, unsigned bytecodeOffset, const UseFunctor& use, const DefFunctor& def)
+template<typename CodeBlockType, typename Instructions, typename UseFunctor, typename DefFunctor>
+inline void BytecodeLivenessPropagation::stepOverInstruction(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, unsigned bytecodeOffset, const UseFunctor& use, const DefFunctor& def)
{
// This abstractly execute the instruction in reverse. Instructions logically first use operands and
// then define operands. This logical ordering is necessary for operations that use and def the same
@@ -79,14 +79,13 @@
// uses before defs, then the add operation above would appear to not have loc1 live, since we'd
// first add it to the out set (the use), and then we'd remove it (the def).
- auto* codeBlock = graph.codeBlock();
- auto* instructionsBegin = graph.instructions().begin();
+ auto* instructionsBegin = instructions.begin();
auto* instruction = &instructionsBegin[bytecodeOffset];
OpcodeID opcodeID = Interpreter::getOpcodeID(*instruction);
computeDefsForBytecodeOffset(
codeBlock, opcodeID, instruction,
- [&] (typename Graph::CodeBlock*, typename Graph::Instruction*, OpcodeID, int operand) {
+ [&] (CodeBlockType*, const typename CodeBlockType::Instruction*, OpcodeID, int operand) {
if (isValidRegisterForLiveness(operand))
def(VirtualRegister(operand).toLocal());
});
@@ -93,7 +92,7 @@
computeUsesForBytecodeOffset(
codeBlock, opcodeID, instruction,
- [&] (typename Graph::CodeBlock*, typename Graph::Instruction*, OpcodeID, int operand) {
+ [&] (CodeBlockType*, const typename CodeBlockType::Instruction*, OpcodeID, int operand) {
if (isValidRegisterForLiveness(operand))
use(VirtualRegister(operand).toLocal());
});
@@ -107,11 +106,11 @@
}
}
-template<typename Graph>
-inline void BytecodeLivenessPropagation::stepOverInstruction(Graph& graph, unsigned bytecodeOffset, FastBitVector& out)
+template<typename CodeBlockType, typename Instructions>
+inline void BytecodeLivenessPropagation::stepOverInstruction(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, unsigned bytecodeOffset, FastBitVector& out)
{
stepOverInstruction(
- graph, bytecodeOffset,
+ codeBlock, instructions, graph, bytecodeOffset,
[&] (unsigned bitIndex) {
// This is the use functor, so we set the bit.
out[bitIndex] = true;
@@ -122,8 +121,8 @@
});
}
-template<typename Graph>
-inline bool BytecodeLivenessPropagation::computeLocalLivenessForBytecodeOffset(Graph& graph, BytecodeBasicBlock* block, unsigned targetOffset, FastBitVector& result)
+template<typename CodeBlockType, typename Instructions>
+inline bool BytecodeLivenessPropagation::computeLocalLivenessForBytecodeOffset(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock* block, unsigned targetOffset, FastBitVector& result)
{
ASSERT(!block->isExitBlock());
ASSERT(!block->isEntryBlock());
@@ -134,22 +133,22 @@
unsigned bytecodeOffset = block->offsets()[i];
if (targetOffset > bytecodeOffset)
break;
- stepOverInstruction(graph, bytecodeOffset, out);
+ stepOverInstruction(codeBlock, instructions, graph, bytecodeOffset, out);
}
return result.setAndCheck(out);
}
-template<typename Graph>
-inline bool BytecodeLivenessPropagation::computeLocalLivenessForBlock(Graph& graph, BytecodeBasicBlock* block)
+template<typename CodeBlockType, typename Instructions>
+inline bool BytecodeLivenessPropagation::computeLocalLivenessForBlock(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, BytecodeBasicBlock* block)
{
if (block->isExitBlock() || block->isEntryBlock())
return false;
- return computeLocalLivenessForBytecodeOffset(graph, block, block->leaderOffset(), block->in());
+ return computeLocalLivenessForBytecodeOffset(codeBlock, instructions, graph, block, block->leaderOffset(), block->in());
}
-template<typename Graph>
-inline FastBitVector BytecodeLivenessPropagation::getLivenessInfoAtBytecodeOffset(Graph& graph, unsigned bytecodeOffset)
+template<typename CodeBlockType, typename Instructions>
+inline FastBitVector BytecodeLivenessPropagation::getLivenessInfoAtBytecodeOffset(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph, unsigned bytecodeOffset)
{
BytecodeBasicBlock* block = graph.findBasicBlockForBytecodeOffset(bytecodeOffset);
ASSERT(block);
@@ -157,14 +156,13 @@
ASSERT(!block->isExitBlock());
FastBitVector out;
out.resize(block->out().numBits());
- computeLocalLivenessForBytecodeOffset(graph, block, bytecodeOffset, out);
+ computeLocalLivenessForBytecodeOffset(codeBlock, instructions, graph, block, bytecodeOffset, out);
return out;
}
-template<typename Graph>
-inline void BytecodeLivenessPropagation::runLivenessFixpoint(Graph& graph)
+template<typename CodeBlockType, typename Instructions>
+inline void BytecodeLivenessPropagation::runLivenessFixpoint(CodeBlockType* codeBlock, const Instructions& instructions, BytecodeGraph& graph)
{
- auto* codeBlock = graph.codeBlock();
unsigned numberOfVariables = codeBlock->numCalleeLocals();
for (BytecodeBasicBlock* block : graph) {
block->in().resize(numberOfVariables);
@@ -186,7 +184,7 @@
for (BytecodeBasicBlock* successor : block->successors())
newOut |= successor->in();
block->out() = newOut;
- changed |= computeLocalLivenessForBlock(graph, block.get());
+ changed |= computeLocalLivenessForBlock(codeBlock, instructions, graph, block.get());
}
} while (changed);
}
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeRewriter.cpp (224137 => 224138)
--- trunk/Source/_javascript_Core/bytecode/BytecodeRewriter.cpp 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeRewriter.cpp 2017-10-28 01:03:22 UTC (rev 224138)
@@ -38,13 +38,13 @@
for (size_t insertionIndex = m_insertions.size(); insertionIndex--;) {
Insertion& insertion = m_insertions[insertionIndex];
if (insertion.type == Insertion::Type::Remove)
- m_graph.instructions().remove(insertion.index.bytecodeOffset, insertion.length());
+ m_instructions.remove(insertion.index.bytecodeOffset, insertion.length());
else {
if (insertion.includeBranch == IncludeBranch::Yes) {
int finalOffset = insertion.index.bytecodeOffset + calculateDifference(m_insertions.begin(), m_insertions.begin() + insertionIndex);
adjustJumpTargetsInFragment(finalOffset, insertion);
}
- m_graph.instructions().insertVector(insertion.index.bytecodeOffset, insertion.instructions);
+ m_instructions.insertVector(insertion.index.bytecodeOffset, insertion.instructions);
}
}
m_insertions.clear();
@@ -56,8 +56,7 @@
return lhs.index < rhs.index;
});
- UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();
- codeBlock->applyModification(*this);
+ m_codeBlock->applyModification(*this, m_instructions);
}
void BytecodeRewriter::adjustJumpTargetsInFragment(unsigned finalOffset, Insertion& insertion)
@@ -69,8 +68,7 @@
OpcodeID opcodeID = instruction.u.opcode;
if (isBranch(opcodeID)) {
unsigned bytecodeOffset = finalOffset + fragmentOffset;
- UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();
- extractStoredJumpTargetsForBytecodeOffset(codeBlock, instructionsBegin, fragmentOffset, [&](int32_t& label) {
+ extractStoredJumpTargetsForBytecodeOffset(m_codeBlock, instructionsBegin, fragmentOffset, [&](int32_t& label) {
int absoluteOffset = adjustAbsoluteOffset(label);
label = absoluteOffset - static_cast<int>(bytecodeOffset);
});
Modified: trunk/Source/_javascript_Core/bytecode/BytecodeRewriter.h (224137 => 224138)
--- trunk/Source/_javascript_Core/bytecode/BytecodeRewriter.h 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeRewriter.h 2017-10-28 01:03:22 UTC (rev 224138)
@@ -161,8 +161,10 @@
IncludeBranch& m_includeBranch;
};
- BytecodeRewriter(BytecodeGraph<UnlinkedCodeBlock>& graph)
+ BytecodeRewriter(BytecodeGraph& graph, UnlinkedCodeBlock* codeBlock, UnlinkedCodeBlock::UnpackedInstructions& instructions)
: m_graph(graph)
+ , m_codeBlock(codeBlock)
+ , m_instructions(instructions)
{
}
@@ -188,12 +190,12 @@
void removeBytecode(unsigned bytecodeOffset)
{
- m_insertions.append(Insertion { InsertionPoint(bytecodeOffset, Position::OriginalBytecodePoint), Insertion::Type::Remove, IncludeBranch::No, opcodeLength(m_graph.instructions()[bytecodeOffset].u.opcode), { } });
+ m_insertions.append(Insertion { InsertionPoint(bytecodeOffset, Position::OriginalBytecodePoint), Insertion::Type::Remove, IncludeBranch::No, opcodeLength(m_instructions[bytecodeOffset].u.opcode), { } });
}
void execute();
- BytecodeGraph<UnlinkedCodeBlock>& graph() { return m_graph; }
+ BytecodeGraph& graph() { return m_graph; }
int adjustAbsoluteOffset(int absoluteOffset)
{
@@ -215,7 +217,9 @@
int adjustJumpTarget(InsertionPoint startPoint, InsertionPoint jumpTargetPoint);
template<typename Iterator> int calculateDifference(Iterator begin, Iterator end);
- BytecodeGraph<UnlinkedCodeBlock>& m_graph;
+ BytecodeGraph& m_graph;
+ UnlinkedCodeBlock* m_codeBlock;
+ UnlinkedCodeBlock::UnpackedInstructions& m_instructions;
Vector<Insertion, 8> m_insertions;
};
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (224137 => 224138)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2017-10-28 01:03:22 UTC (rev 224138)
@@ -398,10 +398,19 @@
setNumParameters(unlinkedCodeBlock->numParameters());
}
+// The main purpose of this function is to generate linked bytecode from unlinked bytecode. The process
+// of linking is taking an abstract representation of bytecode and tying it to a GlobalObject and scope
+// chain. For example, this process allows us to cache the depth of lexical environment reads that reach
+// outside of this CodeBlock's compilation unit. It also allows us to generate particular constants that
+// we can't generate during unlinked bytecode generation. This process is not allowed to generate control
+// flow or introduce new locals. The reason for this is we rely on liveness analysis to be the same for
+// all the CodeBlocks of an UnlinkedCodeBlock. We rely on this fact by caching the liveness analysis
+// inside UnlinkedCodeBlock.
bool CodeBlock::finishCreation(VM& vm, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlinkedCodeBlock,
JSScope* scope)
{
Base::finishCreation(vm);
+
auto throwScope = DECLARE_THROW_SCOPE(vm);
if (vm.typeProfiler() || vm.controlFlowProfiler())
@@ -1719,7 +1728,7 @@
// is because the variables that the op_catch defines might be dead, and
// we can avoid profiling them and extracting them when doing OSR entry
// into the DFG.
- FastBitVector liveLocals = bytecodeLiveness.getLivenessInfoAtBytecodeOffset(bytecodeOffset + OPCODE_LENGTH(op_catch));
+ FastBitVector liveLocals = bytecodeLiveness.getLivenessInfoAtBytecodeOffset(this, bytecodeOffset + OPCODE_LENGTH(op_catch));
Vector<VirtualRegister> liveOperands;
liveOperands.reserveInitialCapacity(liveLocals.bitCount());
liveLocals.forEachSetBit([&] (unsigned liveLocal) {
@@ -2852,7 +2861,7 @@
{
BytecodeLivenessAnalysis liveness(this); // Compute directly from scratch so it doesn't effect CodeBlock footprint.
- FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset(0);
+ FastBitVector liveAtHead = liveness.getLivenessInfoAtBytecodeOffset(this, 0);
if (liveAtHead.numBits() != static_cast<size_t>(m_numCalleeLocals)) {
beginValidationDidFail();
@@ -3226,17 +3235,6 @@
#endif
}
-BytecodeLivenessAnalysis& CodeBlock::livenessAnalysisSlow()
-{
- std::unique_ptr<BytecodeLivenessAnalysis> analysis = std::make_unique<BytecodeLivenessAnalysis>(this);
- {
- ConcurrentJSLocker locker(m_lock);
- if (!m_livenessAnalysis)
- m_livenessAnalysis = WTFMove(analysis);
- return *m_livenessAnalysis;
- }
-}
-
void setPrinter(Printer::PrintRecord& record, CodeBlock* codeBlock)
{
Printer::setPrinter(record, toCString(codeBlock));
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.h (224137 => 224138)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.h 2017-10-28 01:03:22 UTC (rev 224138)
@@ -115,6 +115,7 @@
};
public:
+
enum CopyParsedBlockTag { CopyParsedBlock };
static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
@@ -600,12 +601,7 @@
BytecodeLivenessAnalysis& livenessAnalysis()
{
- {
- ConcurrentJSLocker locker(m_lock);
- if (!!m_livenessAnalysis)
- return *m_livenessAnalysis;
- }
- return livenessAnalysisSlow();
+ return m_unlinkedCode->livenessAnalysis(this);
}
void validate();
@@ -1059,8 +1055,6 @@
std::chrono::steady_clock::time_point m_creationTime;
- std::unique_ptr<BytecodeLivenessAnalysis> m_livenessAnalysis;
-
std::unique_ptr<RareData> m_rareData;
UnconditionalFinalizer m_unconditionalFinalizer;
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp (224137 => 224138)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp 2017-10-28 01:03:22 UTC (rev 224138)
@@ -28,6 +28,7 @@
#include "UnlinkedCodeBlock.h"
#include "BytecodeGenerator.h"
+#include "BytecodeLivenessAnalysis.h"
#include "BytecodeRewriter.h"
#include "ClassInfo.h"
#include "CodeCache.h"
@@ -339,15 +340,14 @@
return UnlinkedHandlerInfo::handlerForIndex(m_rareData->m_exceptionHandlers, index, requiredHandler);
}
-void UnlinkedCodeBlock::applyModification(BytecodeRewriter& rewriter)
+void UnlinkedCodeBlock::applyModification(BytecodeRewriter& rewriter, UnpackedInstructions& instructions)
{
// Before applying the changes, we adjust the jumps based on the original bytecode offset, the offset to the jump target, and
// the insertion information.
- BytecodeGraph<UnlinkedCodeBlock>& graph = rewriter.graph();
- UnlinkedInstruction* instructionsBegin = graph.instructions().begin();
+ UnlinkedInstruction* instructionsBegin = instructions.begin(); // OOPS: make this an accessor on rewriter.
- for (int bytecodeOffset = 0, instructionCount = graph.instructions().size(); bytecodeOffset < instructionCount;) {
+ for (int bytecodeOffset = 0, instructionCount = instructions.size(); bytecodeOffset < instructionCount;) {
UnlinkedInstruction* current = instructionsBegin + bytecodeOffset;
OpcodeID opcodeID = current[0].u.opcode;
extractStoredJumpTargetsForBytecodeOffset(this, instructionsBegin, bytecodeOffset, [&](int32_t& relativeOffset) {
@@ -386,7 +386,7 @@
// And recompute the jump target based on the modified unlinked instructions.
m_jumpTargets.clear();
- recomputePreciseJumpTargets(this, graph.instructions().begin(), graph.instructions().size(), m_jumpTargets);
+ recomputePreciseJumpTargets(this, instructions.begin(), instructions.size(), m_jumpTargets);
}
void UnlinkedCodeBlock::shrinkToFit()
@@ -418,4 +418,21 @@
{
}
+BytecodeLivenessAnalysis& UnlinkedCodeBlock::livenessAnalysisSlow(CodeBlock* codeBlock)
+{
+ RELEASE_ASSERT(codeBlock->unlinkedCodeBlock() == this);
+
+
+ {
+ auto locker = holdLock(m_lock);
+ if (!m_liveness) {
+ // There is a chance two compiler threads raced to the slow path.
+ // We defend against computing liveness twice.
+ m_liveness = std::make_unique<BytecodeLivenessAnalysis>(codeBlock);
+ }
+ }
+
+ return *m_liveness;
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h (224137 => 224138)
--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.h 2017-10-28 01:03:22 UTC (rev 224138)
@@ -46,7 +46,9 @@
namespace JSC {
+class BytecodeLivenessAnalysis;
class BytecodeRewriter;
+class CodeBlock;
class Debugger;
class FunctionExecutable;
class ParserError;
@@ -395,6 +397,13 @@
void dump(PrintStream&) const;
+ BytecodeLivenessAnalysis& livenessAnalysis(CodeBlock* codeBlock)
+ {
+ if (m_liveness)
+ return *m_liveness;
+ return livenessAnalysisSlow(codeBlock);
+ }
+
protected:
UnlinkedCodeBlock(VM*, Structure*, CodeType, const ExecutableInfo&, DebuggerMode);
~UnlinkedCodeBlock();
@@ -406,7 +415,7 @@
private:
friend class BytecodeRewriter;
- void applyModification(BytecodeRewriter&);
+ void applyModification(BytecodeRewriter&, UnpackedInstructions&);
void createRareDataIfNecessary()
{
@@ -417,10 +426,12 @@
}
void getLineAndColumn(const ExpressionRangeInfo&, unsigned& line, unsigned& column) const;
+ BytecodeLivenessAnalysis& livenessAnalysisSlow(CodeBlock*);
int m_numParameters;
std::unique_ptr<UnlinkedInstructionStream> m_unlinkedInstructions;
+ std::unique_ptr<BytecodeLivenessAnalysis> m_liveness;
VirtualRegister m_thisRegister;
VirtualRegister m_scopeRegister;
@@ -445,6 +456,7 @@
unsigned m_lineCount;
unsigned m_endColumn;
+ Lock m_lock;
TriState m_didOptimize;
SourceParseMode m_parseMode;
CodeFeatures m_features;
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.cpp (224137 => 224138)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.cpp 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.cpp 2017-10-28 01:03:22 UTC (rev 224138)
@@ -1086,7 +1086,7 @@
return *iter->value;
std::unique_ptr<FullBytecodeLiveness> liveness = std::make_unique<FullBytecodeLiveness>();
- codeBlock->livenessAnalysis().computeFullLiveness(*liveness);
+ codeBlock->livenessAnalysis().computeFullLiveness(codeBlock, *liveness);
FullBytecodeLiveness& result = *liveness;
m_bytecodeLiveness.add(codeBlock, WTFMove(liveness));
return result;
@@ -1104,7 +1104,7 @@
return *iter->value;
std::unique_ptr<BytecodeKills> kills = std::make_unique<BytecodeKills>();
- codeBlock->livenessAnalysis().computeKills(*kills);
+ codeBlock->livenessAnalysis().computeKills(codeBlock, *kills);
BytecodeKills& result = *kills;
m_bytecodeKills.add(codeBlock, WTFMove(kills));
return result;
Modified: trunk/Source/_javascript_Core/dfg/DFGPlan.cpp (224137 => 224138)
--- trunk/Source/_javascript_Core/dfg/DFGPlan.cpp 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/dfg/DFGPlan.cpp 2017-10-28 01:03:22 UTC (rev 224138)
@@ -697,7 +697,8 @@
if (!mustHandleValues.numberOfLocals())
return;
- FastBitVector liveness = codeBlock->alternative()->livenessAnalysis().getLivenessInfoAtBytecodeOffset(osrEntryBytecodeIndex);
+ CodeBlock* alternative = codeBlock->alternative();
+ FastBitVector liveness = alternative->livenessAnalysis().getLivenessInfoAtBytecodeOffset(alternative, osrEntryBytecodeIndex);
for (unsigned local = mustHandleValues.numberOfLocals(); local--;) {
if (!liveness[local])
Modified: trunk/Source/_javascript_Core/jit/JIT.cpp (224137 => 224138)
--- trunk/Source/_javascript_Core/jit/JIT.cpp 2017-10-28 00:09:47 UTC (rev 224137)
+++ trunk/Source/_javascript_Core/jit/JIT.cpp 2017-10-28 01:03:22 UTC (rev 224138)
@@ -195,7 +195,7 @@
// Instead, we just find the minimum bytecode offset that is reachable, and
// compile code from that bytecode offset onwards.
- BytecodeGraph<CodeBlock> graph(m_codeBlock, m_instructions);
+ BytecodeGraph graph(m_codeBlock, m_instructions);
BytecodeBasicBlock* block = graph.findBasicBlockForBytecodeOffset(m_loopOSREntryBytecodeOffset);
RELEASE_ASSERT(block);