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):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@224138 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 9cf3bcb..0427db7 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -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));