<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[204994] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/204994">204994</a></dd>
<dt>Author</dt> <dd>utatane.tea@gmail.com</dd>
<dt>Date</dt> <dd>2016-08-25 15:55:10 -0700 (Thu, 25 Aug 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[DFG][FTL] Implement ES6 Generators in DFG / FTL
https://bugs.webkit.org/show_bug.cgi?id=152723

Reviewed by Filip Pizlo.

JSTests:

* stress/generator-fib-ftl-and-array.js: Added.
(fib):
* stress/generator-fib-ftl-and-object.js: Added.
(fib):
* stress/generator-fib-ftl-and-string.js: Added.
(fib):
* stress/generator-fib-ftl.js: Added.
(fib):
* stress/generator-frame-empty.js: Added.
(shouldThrow):
(shouldThrow.fib):
* stress/generator-reduced-save-point-put-to-scope.js: Added.
(shouldBe):
(gen):
* stress/generator-transfer-register-beyond-mutiple-yields.js: Added.
(shouldBe):
(gen):

Source/JavaScriptCore:

This patch introduces DFG and FTL support for ES6 generators.
ES6 generator is compiled by the BytecodeGenerator. But at the last phase, BytecodeGenerator performs &quot;generatorification&quot; onto the unlinked code.
In BytecodeGenerator phase, we just emit op_yield for each yield point. And we don't emit any generator related switch, save, and resume sequences
here. Those are emitted by the generatorification phase.

So the graph is super simple! Before the generatorification, the graph looks like this.

     op_enter -&gt; ...... -&gt; op_yield -&gt; ..... -&gt; op_yield -&gt; ...

Roughly speaking, in the generatorification phase, we turn out which variables should be saved and resumed at each op_yield.
This is done by liveness analysis. After that, we convert op_yield to the sequence of &quot;op_put_to_scope&quot;, &quot;op_ret&quot;, and &quot;op_get_from_scope&quot;.
op_put_to_scope and op_get_from_scope sequences are corresponding to the save and resume sequences. We set up the scope for the generator frame and
perform op_put_to_scope and op_get_from_scope onto it. The live registers are saved and resumed over the generator's next() calls by using this
special generator frame scope. And we also set up the global switch for the generator.

In the generatorification phase,

1. We construct the BytecodeGraph from the unlinked instructions. This constructs the basic blocks, and it is used in the subsequent analysis.
2. We perform the analysis onto the unlinked code. We extract the live variables at each op_yield.
3. We insert the get_from_scope and put_to_scope at each op_yield. Which registers should be saved and resumed is offered by (2).
   Then, clip the op_yield themselves. And we also insert the switch_imm. The jump targets of this switch are just after this op_switch_imm and each op_yield point.

One interesting point is the try-range. We split the try-range at the op_yield point in BytecodeGenerator phase.
This drops the hacky thing that is introduced in [1].
If the try-range covers the resume sequences, the exception handler's use-registers are incorrectly transferred to the entry block.
For example,

    handler uses <a href="http://trac.webkit.org/projects/webkit/changeset/2">r2</a>
                                                     try-range
    label:(entry block can jump here)                 ^
        <a href="http://trac.webkit.org/projects/webkit/changeset/1">r1</a> = get_from_scope # resume sequence starts  | use <a href="http://trac.webkit.org/projects/webkit/changeset/2">r2</a> is transferred to the entry block!
        <a href="http://trac.webkit.org/projects/webkit/changeset/2">r2</a> = get_from_scope                           |
        starts usual sequences                        |
        ...                                           |

Handler's <a href="http://trac.webkit.org/projects/webkit/changeset/2">r2</a> use should be considered at the `<a href="http://trac.webkit.org/projects/webkit/changeset/1">r1</a> = get_from_scope` point.
Previously, we handle this edge case by treating op_resume specially in the liveness analysis[1].
To drop this workaround, we split the try-range not to cover this resume sequence.

    handler uses <a href="http://trac.webkit.org/projects/webkit/changeset/2">r2</a>
                                                     try-range
    label:(entry block can jump here)
        <a href="http://trac.webkit.org/projects/webkit/changeset/1">r1</a> = get_from_scope # resume sequence starts
        <a href="http://trac.webkit.org/projects/webkit/changeset/2">r2</a> = get_from_scope
        starts usual sequences                        ^ try-range should start from here.
        ...                                           |

OK. Let's show the detailed example.

    1. First, there is the normal bytecode sequence. Here, | represents the offsets, and [] represents the bytecodes.

        bytecodes   | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
        try-range   &lt;-----------------------------------&gt;

    2. When we emit the op_yield in the bytecode generator, we carefully split the try-range.

        bytecodes   | [ ] | [ ] | [op_yield] | [ ] | [ ] | [ ] |
        try-range   &lt;-----------&gt;            &lt;-----------------&gt;

    3. And in the generatorification phase, we insert the switch's jump target and save &amp; resume sequences. And we also drop op_yield.

                Insert save seq  Insert resume seq
                before op_yield. after op_yield's point.
                               v v
        bytecodes   | [ ] | [ ] | [op_yield] | [ ] | [ ] | [ ] |
        try-range   &lt;-----------&gt;     ^      &lt;-----------------&gt;
                                ^     |
                     Jump to here.    Drop this op_yield.

    4. The final layout is the following.

        bytecodes   | [ ] | [ ][save seq][op_ret] | [resume seq] | [ ] | [ ] | [ ] |
        try-range   &lt;-----------------------------&gt;               &lt;----------------&gt;
                                                  ^
                                      Jump to here.

The rewriting done by the BytecodeRewriter is executed in a batch manner. Since these modification changes the basic blocks and size of unlinked instructions,
BytecodeRewriter also performs the offset adjustment for UnlinkedCodeBlock. So, this rewriting is performed onto the BytecodeGraph rather than BytecodeBasicBlock.
The reason why we take this design is simple: we don't want to newly create the basic blocks and opcodes for this early phase like DFG. Instead, we perform the
modification and adjustment to the unlinked instructions and UnlinkedCodeBlock in a in-place manner.

Bytecode rewriting functionality is offered by BytecodeRewriter. BytecodeRewriter allows us to insert any bytecodes to any places
in a in-place manner. BytecodeRewriter handles the original bytecode offsets as labels. And you can insert bytecodes before and after
these labels. You can also insert any jumps to any places. When you insert jumps, you need to specify jump target with this labels.
These labels (original bytecode offsets) are automatically converted to the appropriate offsets by BytecodeRewriter.

After that phase, the data flow of the generator-saved-and-resumed-registers are explicitly represented by the get_from_scope and put_to_scope.
And the switch is inserted to represent the actual control flow for the generator. And op_yield is removed. Since we use the existing bytecodes (op_switch_imm, op_put_to_scope
op_ret, and op_get_from_scope), DFG and FTL changes are not necessary. This patch also drops data structures and implementations for the old generator,
op_resume, op_save implementations and GeneratorFrame.

Note that this patch does not leverage the recent multi entrypoints support in B3. After this patch is introduced, we will submit a new patch that leverages the multi
entrypoints for generator's resume and sees the performance gain.

Microbenchmarks related to generators show up to 2.9x improvements.

                                                Baseline                  Patched

    generator-fib                          102.0116+-3.2880     ^     34.9670+-0.2221        ^ definitely 2.9174x faster
    generator-sunspider-access-nsieve        5.8596+-0.0371     ^      4.9051+-0.0720        ^ definitely 1.1946x faster
    generator-with-several-types           332.1478+-4.2425     ^    124.6642+-2.4826        ^ definitely 2.6643x faster

    &lt;geometric&gt;                             58.2998+-0.7758     ^     27.7425+-0.2577        ^ definitely 2.1015x faster

In ES6SampleBench's Basic, we can observe 41% improvement (Macbook Pro).

    Baseline:
        Geometric Mean Result: 133.55 ms +- 4.49 ms

        Benchmark    First Iteration        Worst 2%               Steady State
        Air          54.03 ms +- 7.51 ms    29.06 ms +- 3.13 ms    2276.59 ms +- 61.17 ms
        Basic        30.18 ms +- 1.86 ms    18.85 ms +- 0.45 ms    2851.16 ms +- 41.87 ms

    Patched:
        Geometric Mean Result: 121.78 ms +- 3.96 ms

        Benchmark    First Iteration        Worst 2%               Steady State
        Air          52.09 ms +- 6.89 ms    29.59 ms +- 3.16 ms    2239.90 ms +- 54.60 ms
        Basic        29.28 ms +- 1.46 ms    16.26 ms +- 0.66 ms    2025.15 ms +- 38.56 ms

[1]: https://bugs.webkit.org/show_bug.cgi?id=159281

* CMakeLists.txt:
* JavaScriptCore.xcodeproj/project.pbxproj:
* builtins/GeneratorPrototype.js:
(globalPrivate.generatorResume):
* bytecode/BytecodeBasicBlock.cpp:
(JSC::BytecodeBasicBlock::shrinkToFit):
(JSC::BytecodeBasicBlock::computeImpl):
(JSC::BytecodeBasicBlock::compute):
(JSC::isBranch): Deleted.
(JSC::isUnconditionalBranch): Deleted.
(JSC::isTerminal): Deleted.
(JSC::isThrow): Deleted.
(JSC::linkBlocks): Deleted.
(JSC::computeBytecodeBasicBlocks): Deleted.
* bytecode/BytecodeBasicBlock.h:
(JSC::BytecodeBasicBlock::isEntryBlock):
(JSC::BytecodeBasicBlock::isExitBlock):
(JSC::BytecodeBasicBlock::leaderOffset):
(JSC::BytecodeBasicBlock::totalLength):
(JSC::BytecodeBasicBlock::offsets):
(JSC::BytecodeBasicBlock::successors):
(JSC::BytecodeBasicBlock::index):
(JSC::BytecodeBasicBlock::addSuccessor):
(JSC::BytecodeBasicBlock::BytecodeBasicBlock):
(JSC::BytecodeBasicBlock::addLength):
(JSC::BytecodeBasicBlock::leaderBytecodeOffset): Deleted.
(JSC::BytecodeBasicBlock::totalBytecodeLength): Deleted.
(JSC::BytecodeBasicBlock::bytecodeOffsets): Deleted.
(JSC::BytecodeBasicBlock::addBytecodeLength): Deleted.
* bytecode/BytecodeGeneratorification.cpp: Added.
(JSC::BytecodeGeneratorification::BytecodeGeneratorification):
(JSC::BytecodeGeneratorification::graph):
(JSC::BytecodeGeneratorification::yields):
(JSC::BytecodeGeneratorification::enterPoint):
(JSC::BytecodeGeneratorification::storageForGeneratorLocal):
(JSC::GeneratorLivenessAnalysis::GeneratorLivenessAnalysis):
(JSC::GeneratorLivenessAnalysis::computeDefsForBytecodeOffset):
(JSC::GeneratorLivenessAnalysis::computeUsesForBytecodeOffset):
(JSC::GeneratorLivenessAnalysis::run):
(JSC::BytecodeGeneratorification::run):
(JSC::performGeneratorification):
* bytecode/BytecodeGeneratorification.h: Copied from Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h.
* bytecode/BytecodeGraph.h: Added.
(JSC::BytecodeGraph::codeBlock):
(JSC::BytecodeGraph::instructions):
(JSC::BytecodeGraph::basicBlocksInReverseOrder):
(JSC::BytecodeGraph::blockContainsBytecodeOffset):
(JSC::BytecodeGraph::findBasicBlockForBytecodeOffset):
(JSC::BytecodeGraph::findBasicBlockWithLeaderOffset):
(JSC::BytecodeGraph::size):
(JSC::BytecodeGraph::at):
(JSC::BytecodeGraph::operator[]):
(JSC::BytecodeGraph::begin):
(JSC::BytecodeGraph::end):
(JSC::BytecodeGraph::first):
(JSC::BytecodeGraph::last):
(JSC::BytecodeGraph&lt;Block&gt;::BytecodeGraph):
* bytecode/BytecodeList.json:
* bytecode/BytecodeLivenessAnalysis.cpp:
(JSC::BytecodeLivenessAnalysis::BytecodeLivenessAnalysis):
(JSC::BytecodeLivenessAnalysis::computeDefsForBytecodeOffset):
(JSC::BytecodeLivenessAnalysis::computeUsesForBytecodeOffset):
(JSC::BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset):
(JSC::BytecodeLivenessAnalysis::computeFullLiveness):
(JSC::BytecodeLivenessAnalysis::computeKills):
(JSC::BytecodeLivenessAnalysis::dumpResults):
(JSC::BytecodeLivenessAnalysis::compute):
(JSC::isValidRegisterForLiveness): Deleted.
(JSC::getLeaderOffsetForBasicBlock): Deleted.
(JSC::findBasicBlockWithLeaderOffset): Deleted.
(JSC::blockContainsBytecodeOffset): Deleted.
(JSC::findBasicBlockForBytecodeOffset): Deleted.
(JSC::stepOverInstruction): Deleted.
(JSC::computeLocalLivenessForBytecodeOffset): Deleted.
(JSC::computeLocalLivenessForBlock): Deleted.
(JSC::BytecodeLivenessAnalysis::runLivenessFixpoint): Deleted.
* bytecode/BytecodeLivenessAnalysis.h:
* bytecode/BytecodeLivenessAnalysisInlines.h:
(JSC::isValidRegisterForLiveness):
(JSC::BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::stepOverInstruction):
(JSC::BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::computeLocalLivenessForBytecodeOffset):
(JSC::BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::computeLocalLivenessForBlock):
(JSC::BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::getLivenessInfoAtBytecodeOffset):
(JSC::BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::runLivenessFixpoint):
* bytecode/BytecodeRewriter.cpp: Added.
(JSC::BytecodeRewriter::applyModification):
(JSC::BytecodeRewriter::execute):
(JSC::BytecodeRewriter::adjustJumpTargetsInFragment):
(JSC::BytecodeRewriter::insertImpl):
(JSC::BytecodeRewriter::adjustJumpTarget):
* bytecode/BytecodeRewriter.h: Added.
(JSC::BytecodeRewriter::InsertionPoint::InsertionPoint):
(JSC::BytecodeRewriter::InsertionPoint::operator&lt;):
(JSC::BytecodeRewriter::InsertionPoint::operator==):
(JSC::BytecodeRewriter::Insertion::length):
(JSC::BytecodeRewriter::Fragment::Fragment):
(JSC::BytecodeRewriter::Fragment::appendInstruction):
(JSC::BytecodeRewriter::BytecodeRewriter):
(JSC::BytecodeRewriter::insertFragmentBefore):
(JSC::BytecodeRewriter::insertFragmentAfter):
(JSC::BytecodeRewriter::removeBytecode):
(JSC::BytecodeRewriter::graph):
(JSC::BytecodeRewriter::adjustAbsoluteOffset):
(JSC::BytecodeRewriter::adjustJumpTarget):
(JSC::BytecodeRewriter::calculateDifference):
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::finishCreation):
(JSC::CodeBlock::handlerForIndex):
(JSC::CodeBlock::shrinkToFit):
(JSC::CodeBlock::valueProfileForBytecodeOffset):
(JSC::CodeBlock::livenessAnalysisSlow):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::isConstantRegisterIndex):
(JSC::CodeBlock::livenessAnalysis):
(JSC::CodeBlock::liveCalleeLocalsAtYield): Deleted.
* bytecode/HandlerInfo.h:
(JSC::HandlerInfoBase::handlerForIndex):
* bytecode/Opcode.h:
(JSC::isBranch):
(JSC::isUnconditionalBranch):
(JSC::isTerminal):
(JSC::isThrow):
* bytecode/PreciseJumpTargets.cpp:
(JSC::getJumpTargetsForBytecodeOffset):
(JSC::computePreciseJumpTargetsInternal):
(JSC::computePreciseJumpTargets):
(JSC::recomputePreciseJumpTargets):
(JSC::findJumpTargetsForBytecodeOffset):
* bytecode/PreciseJumpTargets.h:
* bytecode/PreciseJumpTargetsInlines.h: Added.
(JSC::extractStoredJumpTargetsForBytecodeOffset):
* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::handlerForBytecodeOffset):
(JSC::UnlinkedCodeBlock::handlerForIndex):
(JSC::UnlinkedCodeBlock::applyModification):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedStringJumpTable::offsetForValue):
(JSC::UnlinkedCodeBlock::numCalleeLocals):
* bytecode/VirtualRegister.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::emitComplexPopScopes):
(JSC::prepareJumpTableForStringSwitch):
(JSC::BytecodeGenerator::emitYieldPoint):
(JSC::BytecodeGenerator::emitSave): Deleted.
(JSC::BytecodeGenerator::emitResume): Deleted.
(JSC::BytecodeGenerator::emitGeneratorStateLabel): Deleted.
(JSC::BytecodeGenerator::beginGenerator): Deleted.
(JSC::BytecodeGenerator::endGenerator): Deleted.
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::generatorStateRegister):
(JSC::BytecodeGenerator::generatorValueRegister):
(JSC::BytecodeGenerator::generatorResumeModeRegister):
(JSC::BytecodeGenerator::generatorFrameRegister):
* bytecompiler/NodesCodegen.cpp:
(JSC::FunctionNode::emitBytecode):
* dfg/DFGOperations.cpp:
* interpreter/Interpreter.cpp:
(JSC::findExceptionHandler):
(JSC::GetCatchHandlerFunctor::operator()):
(JSC::UnwindFunctor::operator()):
* interpreter/Interpreter.h:
* interpreter/InterpreterInlines.h: Copied from Source/JavaScriptCore/bytecode/PreciseJumpTargets.h.
(JSC::Interpreter::getOpcodeID):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_save): Deleted.
(JSC::JIT::emit_op_resume): Deleted.
* llint/LowLevelInterpreter.asm:
* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::parseInner):
(JSC::Parser&lt;LexerType&gt;::parseGeneratorFunctionSourceElements):
(JSC::Parser&lt;LexerType&gt;::createGeneratorParameters):
* parser/Parser.h:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL): Deleted.
* runtime/CommonSlowPaths.h:
* runtime/GeneratorFrame.cpp: Removed.
(JSC::GeneratorFrame::GeneratorFrame): Deleted.
(JSC::GeneratorFrame::finishCreation): Deleted.
(JSC::GeneratorFrame::createStructure): Deleted.
(JSC::GeneratorFrame::create): Deleted.
(JSC::GeneratorFrame::save): Deleted.
(JSC::GeneratorFrame::resume): Deleted.
(JSC::GeneratorFrame::visitChildren): Deleted.
* runtime/GeneratorFrame.h: Removed.
(JSC::GeneratorFrame::locals): Deleted.
(JSC::GeneratorFrame::localAt): Deleted.
(JSC::GeneratorFrame::offsetOfLocals): Deleted.
(JSC::GeneratorFrame::allocationSizeForLocals): Deleted.
* runtime/JSGeneratorFunction.h:
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:

Source/WTF:

* wtf/FastBitVector.h:
(WTF::FastBitVector::FastBitVector):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorebuiltinsGeneratorPrototypejs">trunk/Source/JavaScriptCore/builtins/GeneratorPrototype.js</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeBasicBlockcpp">trunk/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeBasicBlockh">trunk/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeListjson">trunk/Source/JavaScriptCore/bytecode/BytecodeList.json</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeLivenessAnalysiscpp">trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeLivenessAnalysish">trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeLivenessAnalysisInlinesh">trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeUseDefh">trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeHandlerInfoh">trunk/Source/JavaScriptCore/bytecode/HandlerInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeOpcodeh">trunk/Source/JavaScriptCore/bytecode/Opcode.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePreciseJumpTargetscpp">trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePreciseJumpTargetsh">trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeVirtualRegisterh">trunk/Source/JavaScriptCore/bytecode/VirtualRegister.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpretercpp">trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpreterh">trunk/Source/JavaScriptCore/interpreter/Interpreter.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParsercpp">trunk/Source/JavaScriptCore/parser/Parser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParserh">trunk/Source/JavaScriptCore/parser/Parser.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathsh">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGeneratorFunctionh">trunk/Source/JavaScriptCore/runtime/JSGeneratorFunction.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfFastBitVectorh">trunk/Source/WTF/wtf/FastBitVector.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstressgeneratorfibftlandarrayjs">trunk/JSTests/stress/generator-fib-ftl-and-array.js</a></li>
<li><a href="#trunkJSTestsstressgeneratorfibftlandobjectjs">trunk/JSTests/stress/generator-fib-ftl-and-object.js</a></li>
<li><a href="#trunkJSTestsstressgeneratorfibftlandstringjs">trunk/JSTests/stress/generator-fib-ftl-and-string.js</a></li>
<li><a href="#trunkJSTestsstressgeneratorfibftljs">trunk/JSTests/stress/generator-fib-ftl.js</a></li>
<li><a href="#trunkJSTestsstressgeneratorframeemptyjs">trunk/JSTests/stress/generator-frame-empty.js</a></li>
<li><a href="#trunkJSTestsstressgeneratorreducedsavepointputtoscopejs">trunk/JSTests/stress/generator-reduced-save-point-put-to-scope.js</a></li>
<li><a href="#trunkJSTestsstressgeneratortransferregisterbeyondmutipleyieldsjs">trunk/JSTests/stress/generator-transfer-register-beyond-mutiple-yields.js</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeGeneratorificationcpp">trunk/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeGeneratorificationh">trunk/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeGraphh">trunk/Source/JavaScriptCore/bytecode/BytecodeGraph.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeRewritercpp">trunk/Source/JavaScriptCore/bytecode/BytecodeRewriter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeRewriterh">trunk/Source/JavaScriptCore/bytecode/BytecodeRewriter.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePreciseJumpTargetsInlinesh">trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargetsInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpreterInlinesh">trunk/Source/JavaScriptCore/interpreter/InterpreterInlines.h</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreruntimeGeneratorFramecpp">trunk/Source/JavaScriptCore/runtime/GeneratorFrame.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeGeneratorFrameh">trunk/Source/JavaScriptCore/runtime/GeneratorFrame.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/JSTests/ChangeLog        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2016-08-25  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        [DFG][FTL] Implement ES6 Generators in DFG / FTL
+        https://bugs.webkit.org/show_bug.cgi?id=152723
+
+        Reviewed by Filip Pizlo.
+
+        * stress/generator-fib-ftl-and-array.js: Added.
+        (fib):
+        * stress/generator-fib-ftl-and-object.js: Added.
+        (fib):
+        * stress/generator-fib-ftl-and-string.js: Added.
+        (fib):
+        * stress/generator-fib-ftl.js: Added.
+        (fib):
+        * stress/generator-frame-empty.js: Added.
+        (shouldThrow):
+        (shouldThrow.fib):
+        * stress/generator-reduced-save-point-put-to-scope.js: Added.
+        (shouldBe):
+        (gen):
+        * stress/generator-transfer-register-beyond-mutiple-yields.js: Added.
+        (shouldBe):
+        (gen):
+
</ins><span class="cx"> 2016-08-25  JF Bastien  &lt;jfbastien@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         TryGetById should have a ValueProfile so that it can predict its output type
</span></span></pre></div>
<a id="trunkJSTestsstressgeneratorfibftlandarrayjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/generator-fib-ftl-and-array.js (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/generator-fib-ftl-and-array.js                                (rev 0)
+++ trunk/JSTests/stress/generator-fib-ftl-and-array.js        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+(function () {
+    function *fib()
+    {
+        let a = 1;
+        let b = 1;
+        let c = [ 0 ];
+        while (true) {
+            c[0] = a;
+            yield c;
+            [a, b] = [b, a + b];
+        }
+    }
+
+    let value = 0;
+    for (let i = 0; i &lt; 1e4; ++i) {
+        let f = fib();
+        for (let i = 0; i &lt; 100; ++i) {
+            value = f.next().value;
+        }
+        if (value[0] !== 354224848179262000000)
+            throw new Error(`bad value:${result}`);
+    }
+}());
</ins></span></pre></div>
<a id="trunkJSTestsstressgeneratorfibftlandobjectjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/generator-fib-ftl-and-object.js (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/generator-fib-ftl-and-object.js                                (rev 0)
+++ trunk/JSTests/stress/generator-fib-ftl-and-object.js        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+(function () {
+    function *fib()
+    {
+        let a = 1;
+        let b = 1;
+        let c = { fib: 0 };
+        while (true) {
+            c.fib = a;
+            yield c;
+            [a, b] = [b, a + b];
+        }
+    }
+
+    let value = 0;
+    for (let i = 0; i &lt; 1e4; ++i) {
+        let f = fib();
+        for (let i = 0; i &lt; 100; ++i) {
+            value = f.next().value;
+        }
+        if (value.fib !== 354224848179262000000)
+            throw new Error(`bad value:${result}`);
+    }
+}());
</ins></span></pre></div>
<a id="trunkJSTestsstressgeneratorfibftlandstringjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/generator-fib-ftl-and-string.js (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/generator-fib-ftl-and-string.js                                (rev 0)
+++ trunk/JSTests/stress/generator-fib-ftl-and-string.js        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+(function () {
+    function *fib()
+    {
+        let a = 1;
+        let b = 1;
+        let c = &quot;Result! &quot;;
+        while (true) {
+            yield c + a;
+            [a, b] = [b, a + b];
+        }
+    }
+
+    let value = 0;
+    for (let i = 0; i &lt; 1e4; ++i) {
+        let f = fib();
+        for (let i = 0; i &lt; 100; ++i) {
+            value = f.next().value;
+        }
+        if (value !== `Result! 354224848179262000000`)
+            throw new Error(`bad value:${result}`);
+    }
+}());
</ins></span></pre></div>
<a id="trunkJSTestsstressgeneratorfibftljs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/generator-fib-ftl.js (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/generator-fib-ftl.js                                (rev 0)
+++ trunk/JSTests/stress/generator-fib-ftl.js        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+(function () {
+    function *fib()
+    {
+        let a = 1;
+        let b = 1;
+        while (true) {
+            yield a;
+            [a, b] = [b, a + b];
+        }
+    }
+
+    let value = 0;
+    for (let i = 0; i &lt; 1e4; ++i) {
+        let f = fib();
+        for (let i = 0; i &lt; 100; ++i) {
+            value = f.next().value;
+        }
+        if (value !== 354224848179262000000)
+            throw new Error(`bad value:${result}`);
+    }
+}());
</ins></span></pre></div>
<a id="trunkJSTestsstressgeneratorframeemptyjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/generator-frame-empty.js (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/generator-frame-empty.js                                (rev 0)
+++ trunk/JSTests/stress/generator-frame-empty.js        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,34 @@
</span><ins>+function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
+
+shouldThrow(function () {
+    function *fib(flag)
+    {
+        let a = 1;
+        let b = 1;
+        yield 42;
+        if (flag)
+            return c;
+        let c = 500;
+    }
+
+    let value = 0;
+    for (let i = 0; i &lt; 1e4; ++i) {
+        for (let v of fib(false)) {
+        }
+    }
+    for (let v of fib(true)) {
+    }
+}, `ReferenceError: Cannot access uninitialized variable.`);
</ins></span></pre></div>
<a id="trunkJSTestsstressgeneratorreducedsavepointputtoscopejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/generator-reduced-save-point-put-to-scope.js (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/generator-reduced-save-point-put-to-scope.js                                (rev 0)
+++ trunk/JSTests/stress/generator-reduced-save-point-put-to-scope.js        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error(`bad value: ${String(actual)}`);
+}
+
+function error()
+{
+    throw &quot;ok&quot;;
+}
+
+function* gen()
+{
+    var value = 42;
+    try {
+        yield 300;
+        value = 500;
+        error();
+    } catch (e) {
+        yield 42;
+        return value;
+    }
+    return 200;
+}
+
+var g = gen();
+shouldBe(g.next().value, 300);
+shouldBe(g.next().value, 42);
+shouldBe(g.next().value, 500);
</ins></span></pre></div>
<a id="trunkJSTestsstressgeneratortransferregisterbeyondmutipleyieldsjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/generator-transfer-register-beyond-mutiple-yields.js (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/generator-transfer-register-beyond-mutiple-yields.js                                (rev 0)
+++ trunk/JSTests/stress/generator-transfer-register-beyond-mutiple-yields.js        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+
+function *gen()
+{
+    var test = 42;
+    yield 32;
+    yield 33;
+    yield test;
+}
+
+var g = gen();
+shouldBe(g.next().value, 32);
+shouldBe(g.next().value, 33);
+shouldBe(g.next().value, 42);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -181,6 +181,8 @@
</span><span class="cx">     bytecode/ArrayAllocationProfile.cpp
</span><span class="cx">     bytecode/ArrayProfile.cpp
</span><span class="cx">     bytecode/BytecodeBasicBlock.cpp
</span><ins>+    bytecode/BytecodeGeneratorification.cpp
+    bytecode/BytecodeRewriter.cpp
</ins><span class="cx">     bytecode/BytecodeIntrinsicRegistry.cpp
</span><span class="cx">     bytecode/BytecodeLivenessAnalysis.cpp
</span><span class="cx">     bytecode/CallEdge.cpp
</span><span class="lines">@@ -661,7 +663,6 @@
</span><span class="cx">     runtime/FunctionHasExecutedCache.cpp
</span><span class="cx">     runtime/FunctionPrototype.cpp
</span><span class="cx">     runtime/FunctionRareData.cpp
</span><del>-    runtime/GeneratorFrame.cpp
</del><span class="cx">     runtime/GeneratorFunctionConstructor.cpp
</span><span class="cx">     runtime/GeneratorFunctionPrototype.cpp
</span><span class="cx">     runtime/GeneratorPrototype.cpp
</span><span class="lines">@@ -979,6 +980,10 @@
</span><span class="cx">     COMMAND ${PYTHON_EXECUTABLE} ${JAVASCRIPTCORE_DIR}/generate-bytecode-files --bytecodes_h ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/Bytecodes.h --init_bytecodes_asm ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/InitBytecodes.asm ${JAVASCRIPTCORE_DIR}/bytecode/BytecodeList.json
</span><span class="cx">     VERBATIM)
</span><span class="cx"> 
</span><ins>+list(APPEND JavaScriptCore_HEADERS
+    ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/Bytecodes.h
+)
+
</ins><span class="cx"> add_custom_command(
</span><span class="cx">     OUTPUT ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/LLIntDesiredOffsets.h
</span><span class="cx">     MAIN_DEPENDENCY ${JAVASCRIPTCORE_DIR}/offlineasm/generate_offset_extractor.rb
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -1,3 +1,334 @@
</span><ins>+2016-08-25  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        [DFG][FTL] Implement ES6 Generators in DFG / FTL
+        https://bugs.webkit.org/show_bug.cgi?id=152723
+
+        Reviewed by Filip Pizlo.
+
+        This patch introduces DFG and FTL support for ES6 generators.
+        ES6 generator is compiled by the BytecodeGenerator. But at the last phase, BytecodeGenerator performs &quot;generatorification&quot; onto the unlinked code.
+        In BytecodeGenerator phase, we just emit op_yield for each yield point. And we don't emit any generator related switch, save, and resume sequences
+        here. Those are emitted by the generatorification phase.
+
+        So the graph is super simple! Before the generatorification, the graph looks like this.
+
+             op_enter -&gt; ...... -&gt; op_yield -&gt; ..... -&gt; op_yield -&gt; ...
+
+        Roughly speaking, in the generatorification phase, we turn out which variables should be saved and resumed at each op_yield.
+        This is done by liveness analysis. After that, we convert op_yield to the sequence of &quot;op_put_to_scope&quot;, &quot;op_ret&quot;, and &quot;op_get_from_scope&quot;.
+        op_put_to_scope and op_get_from_scope sequences are corresponding to the save and resume sequences. We set up the scope for the generator frame and
+        perform op_put_to_scope and op_get_from_scope onto it. The live registers are saved and resumed over the generator's next() calls by using this
+        special generator frame scope. And we also set up the global switch for the generator.
+
+        In the generatorification phase,
+
+        1. We construct the BytecodeGraph from the unlinked instructions. This constructs the basic blocks, and it is used in the subsequent analysis.
+        2. We perform the analysis onto the unlinked code. We extract the live variables at each op_yield.
+        3. We insert the get_from_scope and put_to_scope at each op_yield. Which registers should be saved and resumed is offered by (2).
+           Then, clip the op_yield themselves. And we also insert the switch_imm. The jump targets of this switch are just after this op_switch_imm and each op_yield point.
+
+        One interesting point is the try-range. We split the try-range at the op_yield point in BytecodeGenerator phase.
+        This drops the hacky thing that is introduced in [1].
+        If the try-range covers the resume sequences, the exception handler's use-registers are incorrectly transferred to the entry block.
+        For example,
+
+            handler uses r2
+                                                             try-range
+            label:(entry block can jump here)                 ^
+                r1 = get_from_scope # resume sequence starts  | use r2 is transferred to the entry block!
+                r2 = get_from_scope                           |
+                starts usual sequences                        |
+                ...                                           |
+
+        Handler's r2 use should be considered at the `r1 = get_from_scope` point.
+        Previously, we handle this edge case by treating op_resume specially in the liveness analysis[1].
+        To drop this workaround, we split the try-range not to cover this resume sequence.
+
+            handler uses r2
+                                                             try-range
+            label:(entry block can jump here)
+                r1 = get_from_scope # resume sequence starts
+                r2 = get_from_scope
+                starts usual sequences                        ^ try-range should start from here.
+                ...                                           |
+
+        OK. Let's show the detailed example.
+
+            1. First, there is the normal bytecode sequence. Here, | represents the offsets, and [] represents the bytecodes.
+
+                bytecodes   | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] |
+                try-range   &lt;-----------------------------------&gt;
+
+            2. When we emit the op_yield in the bytecode generator, we carefully split the try-range.
+
+                bytecodes   | [ ] | [ ] | [op_yield] | [ ] | [ ] | [ ] |
+                try-range   &lt;-----------&gt;            &lt;-----------------&gt;
+
+            3. And in the generatorification phase, we insert the switch's jump target and save &amp; resume sequences. And we also drop op_yield.
+
+                        Insert save seq  Insert resume seq
+                        before op_yield. after op_yield's point.
+                                       v v
+                bytecodes   | [ ] | [ ] | [op_yield] | [ ] | [ ] | [ ] |
+                try-range   &lt;-----------&gt;     ^      &lt;-----------------&gt;
+                                        ^     |
+                             Jump to here.    Drop this op_yield.
+
+            4. The final layout is the following.
+
+                bytecodes   | [ ] | [ ][save seq][op_ret] | [resume seq] | [ ] | [ ] | [ ] |
+                try-range   &lt;-----------------------------&gt;               &lt;----------------&gt;
+                                                          ^
+                                              Jump to here.
+
+        The rewriting done by the BytecodeRewriter is executed in a batch manner. Since these modification changes the basic blocks and size of unlinked instructions,
+        BytecodeRewriter also performs the offset adjustment for UnlinkedCodeBlock. So, this rewriting is performed onto the BytecodeGraph rather than BytecodeBasicBlock.
+        The reason why we take this design is simple: we don't want to newly create the basic blocks and opcodes for this early phase like DFG. Instead, we perform the
+        modification and adjustment to the unlinked instructions and UnlinkedCodeBlock in a in-place manner.
+
+        Bytecode rewriting functionality is offered by BytecodeRewriter. BytecodeRewriter allows us to insert any bytecodes to any places
+        in a in-place manner. BytecodeRewriter handles the original bytecode offsets as labels. And you can insert bytecodes before and after
+        these labels. You can also insert any jumps to any places. When you insert jumps, you need to specify jump target with this labels.
+        These labels (original bytecode offsets) are automatically converted to the appropriate offsets by BytecodeRewriter.
+
+        After that phase, the data flow of the generator-saved-and-resumed-registers are explicitly represented by the get_from_scope and put_to_scope.
+        And the switch is inserted to represent the actual control flow for the generator. And op_yield is removed. Since we use the existing bytecodes (op_switch_imm, op_put_to_scope
+        op_ret, and op_get_from_scope), DFG and FTL changes are not necessary. This patch also drops data structures and implementations for the old generator,
+        op_resume, op_save implementations and GeneratorFrame.
+
+        Note that this patch does not leverage the recent multi entrypoints support in B3. After this patch is introduced, we will submit a new patch that leverages the multi
+        entrypoints for generator's resume and sees the performance gain.
+
+        Microbenchmarks related to generators show up to 2.9x improvements.
+
+                                                        Baseline                  Patched
+
+            generator-fib                          102.0116+-3.2880     ^     34.9670+-0.2221        ^ definitely 2.9174x faster
+            generator-sunspider-access-nsieve        5.8596+-0.0371     ^      4.9051+-0.0720        ^ definitely 1.1946x faster
+            generator-with-several-types           332.1478+-4.2425     ^    124.6642+-2.4826        ^ definitely 2.6643x faster
+
+            &lt;geometric&gt;                             58.2998+-0.7758     ^     27.7425+-0.2577        ^ definitely 2.1015x faster
+
+        In ES6SampleBench's Basic, we can observe 41% improvement (Macbook Pro).
+
+            Baseline:
+                Geometric Mean Result: 133.55 ms +- 4.49 ms
+
+                Benchmark    First Iteration        Worst 2%               Steady State
+                Air          54.03 ms +- 7.51 ms    29.06 ms +- 3.13 ms    2276.59 ms +- 61.17 ms
+                Basic        30.18 ms +- 1.86 ms    18.85 ms +- 0.45 ms    2851.16 ms +- 41.87 ms
+
+            Patched:
+                Geometric Mean Result: 121.78 ms +- 3.96 ms
+
+                Benchmark    First Iteration        Worst 2%               Steady State
+                Air          52.09 ms +- 6.89 ms    29.59 ms +- 3.16 ms    2239.90 ms +- 54.60 ms
+                Basic        29.28 ms +- 1.46 ms    16.26 ms +- 0.66 ms    2025.15 ms +- 38.56 ms
+
+        [1]: https://bugs.webkit.org/show_bug.cgi?id=159281
+
+        * CMakeLists.txt:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * builtins/GeneratorPrototype.js:
+        (globalPrivate.generatorResume):
+        * bytecode/BytecodeBasicBlock.cpp:
+        (JSC::BytecodeBasicBlock::shrinkToFit):
+        (JSC::BytecodeBasicBlock::computeImpl):
+        (JSC::BytecodeBasicBlock::compute):
+        (JSC::isBranch): Deleted.
+        (JSC::isUnconditionalBranch): Deleted.
+        (JSC::isTerminal): Deleted.
+        (JSC::isThrow): Deleted.
+        (JSC::linkBlocks): Deleted.
+        (JSC::computeBytecodeBasicBlocks): Deleted.
+        * bytecode/BytecodeBasicBlock.h:
+        (JSC::BytecodeBasicBlock::isEntryBlock):
+        (JSC::BytecodeBasicBlock::isExitBlock):
+        (JSC::BytecodeBasicBlock::leaderOffset):
+        (JSC::BytecodeBasicBlock::totalLength):
+        (JSC::BytecodeBasicBlock::offsets):
+        (JSC::BytecodeBasicBlock::successors):
+        (JSC::BytecodeBasicBlock::index):
+        (JSC::BytecodeBasicBlock::addSuccessor):
+        (JSC::BytecodeBasicBlock::BytecodeBasicBlock):
+        (JSC::BytecodeBasicBlock::addLength):
+        (JSC::BytecodeBasicBlock::leaderBytecodeOffset): Deleted.
+        (JSC::BytecodeBasicBlock::totalBytecodeLength): Deleted.
+        (JSC::BytecodeBasicBlock::bytecodeOffsets): Deleted.
+        (JSC::BytecodeBasicBlock::addBytecodeLength): Deleted.
+        * bytecode/BytecodeGeneratorification.cpp: Added.
+        (JSC::BytecodeGeneratorification::BytecodeGeneratorification):
+        (JSC::BytecodeGeneratorification::graph):
+        (JSC::BytecodeGeneratorification::yields):
+        (JSC::BytecodeGeneratorification::enterPoint):
+        (JSC::BytecodeGeneratorification::storageForGeneratorLocal):
+        (JSC::GeneratorLivenessAnalysis::GeneratorLivenessAnalysis):
+        (JSC::GeneratorLivenessAnalysis::computeDefsForBytecodeOffset):
+        (JSC::GeneratorLivenessAnalysis::computeUsesForBytecodeOffset):
+        (JSC::GeneratorLivenessAnalysis::run):
+        (JSC::BytecodeGeneratorification::run):
+        (JSC::performGeneratorification):
+        * bytecode/BytecodeGeneratorification.h: Copied from Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h.
+        * bytecode/BytecodeGraph.h: Added.
+        (JSC::BytecodeGraph::codeBlock):
+        (JSC::BytecodeGraph::instructions):
+        (JSC::BytecodeGraph::basicBlocksInReverseOrder):
+        (JSC::BytecodeGraph::blockContainsBytecodeOffset):
+        (JSC::BytecodeGraph::findBasicBlockForBytecodeOffset):
+        (JSC::BytecodeGraph::findBasicBlockWithLeaderOffset):
+        (JSC::BytecodeGraph::size):
+        (JSC::BytecodeGraph::at):
+        (JSC::BytecodeGraph::operator[]):
+        (JSC::BytecodeGraph::begin):
+        (JSC::BytecodeGraph::end):
+        (JSC::BytecodeGraph::first):
+        (JSC::BytecodeGraph::last):
+        (JSC::BytecodeGraph&lt;Block&gt;::BytecodeGraph):
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeLivenessAnalysis.cpp:
+        (JSC::BytecodeLivenessAnalysis::BytecodeLivenessAnalysis):
+        (JSC::BytecodeLivenessAnalysis::computeDefsForBytecodeOffset):
+        (JSC::BytecodeLivenessAnalysis::computeUsesForBytecodeOffset):
+        (JSC::BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset):
+        (JSC::BytecodeLivenessAnalysis::computeFullLiveness):
+        (JSC::BytecodeLivenessAnalysis::computeKills):
+        (JSC::BytecodeLivenessAnalysis::dumpResults):
+        (JSC::BytecodeLivenessAnalysis::compute):
+        (JSC::isValidRegisterForLiveness): Deleted.
+        (JSC::getLeaderOffsetForBasicBlock): Deleted.
+        (JSC::findBasicBlockWithLeaderOffset): Deleted.
+        (JSC::blockContainsBytecodeOffset): Deleted.
+        (JSC::findBasicBlockForBytecodeOffset): Deleted.
+        (JSC::stepOverInstruction): Deleted.
+        (JSC::computeLocalLivenessForBytecodeOffset): Deleted.
+        (JSC::computeLocalLivenessForBlock): Deleted.
+        (JSC::BytecodeLivenessAnalysis::runLivenessFixpoint): Deleted.
+        * bytecode/BytecodeLivenessAnalysis.h:
+        * bytecode/BytecodeLivenessAnalysisInlines.h:
+        (JSC::isValidRegisterForLiveness):
+        (JSC::BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::stepOverInstruction):
+        (JSC::BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::computeLocalLivenessForBytecodeOffset):
+        (JSC::BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::computeLocalLivenessForBlock):
+        (JSC::BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::getLivenessInfoAtBytecodeOffset):
+        (JSC::BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::runLivenessFixpoint):
+        * bytecode/BytecodeRewriter.cpp: Added.
+        (JSC::BytecodeRewriter::applyModification):
+        (JSC::BytecodeRewriter::execute):
+        (JSC::BytecodeRewriter::adjustJumpTargetsInFragment):
+        (JSC::BytecodeRewriter::insertImpl):
+        (JSC::BytecodeRewriter::adjustJumpTarget):
+        * bytecode/BytecodeRewriter.h: Added.
+        (JSC::BytecodeRewriter::InsertionPoint::InsertionPoint):
+        (JSC::BytecodeRewriter::InsertionPoint::operator&lt;):
+        (JSC::BytecodeRewriter::InsertionPoint::operator==):
+        (JSC::BytecodeRewriter::Insertion::length):
+        (JSC::BytecodeRewriter::Fragment::Fragment):
+        (JSC::BytecodeRewriter::Fragment::appendInstruction):
+        (JSC::BytecodeRewriter::BytecodeRewriter):
+        (JSC::BytecodeRewriter::insertFragmentBefore):
+        (JSC::BytecodeRewriter::insertFragmentAfter):
+        (JSC::BytecodeRewriter::removeBytecode):
+        (JSC::BytecodeRewriter::graph):
+        (JSC::BytecodeRewriter::adjustAbsoluteOffset):
+        (JSC::BytecodeRewriter::adjustJumpTarget):
+        (JSC::BytecodeRewriter::calculateDifference):
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        (JSC::CodeBlock::finishCreation):
+        (JSC::CodeBlock::handlerForIndex):
+        (JSC::CodeBlock::shrinkToFit):
+        (JSC::CodeBlock::valueProfileForBytecodeOffset):
+        (JSC::CodeBlock::livenessAnalysisSlow):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::isConstantRegisterIndex):
+        (JSC::CodeBlock::livenessAnalysis):
+        (JSC::CodeBlock::liveCalleeLocalsAtYield): Deleted.
+        * bytecode/HandlerInfo.h:
+        (JSC::HandlerInfoBase::handlerForIndex):
+        * bytecode/Opcode.h:
+        (JSC::isBranch):
+        (JSC::isUnconditionalBranch):
+        (JSC::isTerminal):
+        (JSC::isThrow):
+        * bytecode/PreciseJumpTargets.cpp:
+        (JSC::getJumpTargetsForBytecodeOffset):
+        (JSC::computePreciseJumpTargetsInternal):
+        (JSC::computePreciseJumpTargets):
+        (JSC::recomputePreciseJumpTargets):
+        (JSC::findJumpTargetsForBytecodeOffset):
+        * bytecode/PreciseJumpTargets.h:
+        * bytecode/PreciseJumpTargetsInlines.h: Added.
+        (JSC::extractStoredJumpTargetsForBytecodeOffset):
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::UnlinkedCodeBlock::handlerForBytecodeOffset):
+        (JSC::UnlinkedCodeBlock::handlerForIndex):
+        (JSC::UnlinkedCodeBlock::applyModification):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedStringJumpTable::offsetForValue):
+        (JSC::UnlinkedCodeBlock::numCalleeLocals):
+        * bytecode/VirtualRegister.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::generate):
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::emitComplexPopScopes):
+        (JSC::prepareJumpTableForStringSwitch):
+        (JSC::BytecodeGenerator::emitYieldPoint):
+        (JSC::BytecodeGenerator::emitSave): Deleted.
+        (JSC::BytecodeGenerator::emitResume): Deleted.
+        (JSC::BytecodeGenerator::emitGeneratorStateLabel): Deleted.
+        (JSC::BytecodeGenerator::beginGenerator): Deleted.
+        (JSC::BytecodeGenerator::endGenerator): Deleted.
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::generatorStateRegister):
+        (JSC::BytecodeGenerator::generatorValueRegister):
+        (JSC::BytecodeGenerator::generatorResumeModeRegister):
+        (JSC::BytecodeGenerator::generatorFrameRegister):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::FunctionNode::emitBytecode):
+        * dfg/DFGOperations.cpp:
+        * interpreter/Interpreter.cpp:
+        (JSC::findExceptionHandler):
+        (JSC::GetCatchHandlerFunctor::operator()):
+        (JSC::UnwindFunctor::operator()):
+        * interpreter/Interpreter.h:
+        * interpreter/InterpreterInlines.h: Copied from Source/JavaScriptCore/bytecode/PreciseJumpTargets.h.
+        (JSC::Interpreter::getOpcodeID):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * jit/JIT.h:
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_save): Deleted.
+        (JSC::JIT::emit_op_resume): Deleted.
+        * llint/LowLevelInterpreter.asm:
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::parseInner):
+        (JSC::Parser&lt;LexerType&gt;::parseGeneratorFunctionSourceElements):
+        (JSC::Parser&lt;LexerType&gt;::createGeneratorParameters):
+        * parser/Parser.h:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL): Deleted.
+        * runtime/CommonSlowPaths.h:
+        * runtime/GeneratorFrame.cpp: Removed.
+        (JSC::GeneratorFrame::GeneratorFrame): Deleted.
+        (JSC::GeneratorFrame::finishCreation): Deleted.
+        (JSC::GeneratorFrame::createStructure): Deleted.
+        (JSC::GeneratorFrame::create): Deleted.
+        (JSC::GeneratorFrame::save): Deleted.
+        (JSC::GeneratorFrame::resume): Deleted.
+        (JSC::GeneratorFrame::visitChildren): Deleted.
+        * runtime/GeneratorFrame.h: Removed.
+        (JSC::GeneratorFrame::locals): Deleted.
+        (JSC::GeneratorFrame::localAt): Deleted.
+        (JSC::GeneratorFrame::offsetOfLocals): Deleted.
+        (JSC::GeneratorFrame::allocationSizeForLocals): Deleted.
+        * runtime/JSGeneratorFunction.h:
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+
</ins><span class="cx"> 2016-08-25  JF Bastien  &lt;jfbastien@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         TryGetById should have a ValueProfile so that it can predict its output type
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -1198,7 +1198,7 @@
</span><span class="cx">                 53F40E8D1D5901F20099A1B6 /* WASMParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E8C1D5901F20099A1B6 /* WASMParser.h */; };
</span><span class="cx">                 53F40E8F1D5902820099A1B6 /* WASMB3IRGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53F40E8E1D5902820099A1B6 /* WASMB3IRGenerator.cpp */; };
</span><span class="cx">                 53F40E911D5903020099A1B6 /* WASMOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E901D5903020099A1B6 /* WASMOps.h */; };
</span><del>-                53F40E931D5A4AB30099A1B6 /* WASMB3IRGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E921D5A4AB30099A1B6 /* WASMB3IRGenerator.h */; };
</del><ins>+                53F40E931D5A4AB30099A1B6 /* WASMB3IRGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E921D5A4AB30099A1B6 /* WASMB3IRGenerator.h */; };
</ins><span class="cx">                 53F40E951D5A7AEF0099A1B6 /* WASMModuleParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E941D5A7AEF0099A1B6 /* WASMModuleParser.h */; };
</span><span class="cx">                 53F40E971D5A7BEC0099A1B6 /* WASMModuleParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53F40E961D5A7BEC0099A1B6 /* WASMModuleParser.cpp */; };
</span><span class="cx">                 53F6BF6D1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -1270,8 +1270,6 @@
</span><span class="cx">                 709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 709FB8661AE335C60039D069 /* WeakSetPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 70B0A9D11A9B66460001306A /* RuntimeFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = 70B0A9D01A9B66200001306A /* RuntimeFlags.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 70B791911C024A13002481E2 /* SourceCodeKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 70B7918E1C0244C9002481E2 /* SourceCodeKey.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                70B791921C024A23002481E2 /* GeneratorFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70B791831C024432002481E2 /* GeneratorFrame.cpp */; };
-                70B791931C024A28002481E2 /* GeneratorFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 70B791841C024432002481E2 /* GeneratorFrame.h */; settings = {ATTRIBUTES = (Private, ); }; };
</del><span class="cx">                 70B791941C024A28002481E2 /* GeneratorFunctionConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70B791851C024432002481E2 /* GeneratorFunctionConstructor.cpp */; };
</span><span class="cx">                 70B791951C024A28002481E2 /* GeneratorFunctionConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 70B791861C024432002481E2 /* GeneratorFunctionConstructor.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 70B791961C024A28002481E2 /* GeneratorFunctionPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70B791871C024432002481E2 /* GeneratorFunctionPrototype.cpp */; };
</span><span class="lines">@@ -2045,6 +2043,11 @@
</span><span class="cx">                 E18E3A590DF9278C00D90B34 /* VM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E18E3A570DF9278C00D90B34 /* VM.cpp */; };
</span><span class="cx">                 E318CBC01B8AEF5100A2929D /* JSModuleNamespaceObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E318CBBE1B8AEF5100A2929D /* JSModuleNamespaceObject.cpp */; };
</span><span class="cx">                 E318CBC11B8AEF5100A2929D /* JSModuleNamespaceObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E318CBBF1B8AEF5100A2929D /* JSModuleNamespaceObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                E328DAE71D38D004001A2529 /* BytecodeGeneratorification.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3D264261D38C042000BE174 /* BytecodeGeneratorification.cpp */; };
+                E328DAE81D38D005001A2529 /* BytecodeGeneratorification.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D264271D38C042000BE174 /* BytecodeGeneratorification.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                E328DAE91D38D005001A2529 /* BytecodeGraph.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D264281D38C042000BE174 /* BytecodeGraph.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                E328DAEA1D38D005001A2529 /* BytecodeRewriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3D264291D38C042000BE174 /* BytecodeRewriter.cpp */; };
+                E328DAEB1D38D005001A2529 /* BytecodeRewriter.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D2642A1D38C042000BE174 /* BytecodeRewriter.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 E33637A51B63220200EE0840 /* ReflectObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E33637A31B63220200EE0840 /* ReflectObject.cpp */; };
</span><span class="cx">                 E33637A61B63220200EE0840 /* ReflectObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E33637A41B63220200EE0840 /* ReflectObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 E33B3E261B7ABD750048DB2E /* InspectorInstrumentationObject.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E33B3E251B7ABD750048DB2E /* InspectorInstrumentationObject.lut.h */; };
</span><span class="lines">@@ -2069,8 +2072,10 @@
</span><span class="cx">                 E3794E751B77EB97005543AE /* ModuleAnalyzer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3794E731B77EB97005543AE /* ModuleAnalyzer.cpp */; };
</span><span class="cx">                 E3794E761B77EB97005543AE /* ModuleAnalyzer.h in Headers */ = {isa = PBXBuildFile; fileRef = E3794E741B77EB97005543AE /* ModuleAnalyzer.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 E3963CEE1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */; };
</span><ins>+                E39D45F51D39005600B3B377 /* InterpreterInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D9D841D39000600667282 /* InterpreterInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 E39DA4A61B7E8B7C0084F33A /* JSModuleRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */; };
</span><span class="cx">                 E39DA4A71B7E8B7C0084F33A /* JSModuleRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                E3A421431D6F58930007C617 /* PreciseJumpTargetsInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E3A421421D6F588F0007C617 /* PreciseJumpTargetsInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 E3D239C81B829C1C00BBEF67 /* JSModuleEnvironment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3D239C61B829C1C00BBEF67 /* JSModuleEnvironment.cpp */; };
</span><span class="cx">                 E3D239C91B829C1C00BBEF67 /* JSModuleEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D239C71B829C1C00BBEF67 /* JSModuleEnvironment.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 E3EF88741B66DF23003F26CB /* JSPropertyNameIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3EF88721B66DF23003F26CB /* JSPropertyNameIterator.cpp */; };
</span><span class="lines">@@ -3386,7 +3391,7 @@
</span><span class="cx">                 53F40E8C1D5901F20099A1B6 /* WASMParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMParser.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53F40E8E1D5902820099A1B6 /* WASMB3IRGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WASMB3IRGenerator.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53F40E901D5903020099A1B6 /* WASMOps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMOps.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                53F40E921D5A4AB30099A1B6 /* WASMB3IRGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMB3IRGenerator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><ins>+                53F40E921D5A4AB30099A1B6 /* WASMB3IRGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMB3IRGenerator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 53F40E941D5A7AEF0099A1B6 /* WASMModuleParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WASMModuleParser.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53F40E961D5A7BEC0099A1B6 /* WASMModuleParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WASMModuleParser.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InternalFunctionAllocationProfile.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3492,8 +3497,6 @@
</span><span class="cx">                 709FB8651AE335C60039D069 /* WeakSetPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WeakSetPrototype.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 709FB8661AE335C60039D069 /* WeakSetPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakSetPrototype.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 70B0A9D01A9B66200001306A /* RuntimeFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeFlags.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                70B791831C024432002481E2 /* GeneratorFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GeneratorFrame.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
-                70B791841C024432002481E2 /* GeneratorFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratorFrame.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 70B791851C024432002481E2 /* GeneratorFunctionConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GeneratorFunctionConstructor.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 70B791861C024432002481E2 /* GeneratorFunctionConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeneratorFunctionConstructor.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 70B791871C024432002481E2 /* GeneratorFunctionPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GeneratorFunctionPrototype.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4333,10 +4336,17 @@
</span><span class="cx">                 E3794E731B77EB97005543AE /* ModuleAnalyzer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleAnalyzer.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E3794E741B77EB97005543AE /* ModuleAnalyzer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleAnalyzer.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodesAnalyzeModule.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                E39D9D841D39000600667282 /* InterpreterInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InterpreterInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleRecord.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSModuleRecord.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                E3A421421D6F588F0007C617 /* PreciseJumpTargetsInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreciseJumpTargetsInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 E3D239C61B829C1C00BBEF67 /* JSModuleEnvironment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleEnvironment.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E3D239C71B829C1C00BBEF67 /* JSModuleEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSModuleEnvironment.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                E3D264261D38C042000BE174 /* BytecodeGeneratorification.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BytecodeGeneratorification.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                E3D264271D38C042000BE174 /* BytecodeGeneratorification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeGeneratorification.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                E3D264281D38C042000BE174 /* BytecodeGraph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeGraph.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                E3D264291D38C042000BE174 /* BytecodeRewriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BytecodeRewriter.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                E3D2642A1D38C042000BE174 /* BytecodeRewriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeRewriter.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 E3EF88721B66DF23003F26CB /* JSPropertyNameIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameIterator.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E3EF88731B66DF23003F26CB /* JSPropertyNameIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameIterator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 E49DC14912EF261A00184A1F /* SourceProviderCacheItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceProviderCacheItem.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5063,6 +5073,7 @@
</span><span class="cx">                 1429D77A0ED20D7300B89619 /* interpreter */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                E39D9D841D39000600667282 /* InterpreterInlines.h */,
</ins><span class="cx">                                 0F55F0F114D1063600AC7649 /* AbstractPC.cpp */,
</span><span class="cx">                                 0F55F0F214D1063600AC7649 /* AbstractPC.h */,
</span><span class="cx">                                 1429D85B0ED218E900B89619 /* CLoopStack.cpp */,
</span><span class="lines">@@ -5558,7 +5569,7 @@
</span><span class="cx">                                 53F40E901D5903020099A1B6 /* WASMOps.h */,
</span><span class="cx">                                 7BC547D21B69599B00959B58 /* WASMFormat.h */,
</span><span class="cx">                                 53F40E8E1D5902820099A1B6 /* WASMB3IRGenerator.cpp */,
</span><del>-                                53F40E921D5A4AB30099A1B6 /* WASMB3IRGenerator.h */,
</del><ins>+                                53F40E921D5A4AB30099A1B6 /* WASMB3IRGenerator.h */,
</ins><span class="cx">                                 53F40E8A1D5901BB0099A1B6 /* WASMFunctionParser.h */,
</span><span class="cx">                                 53F40E961D5A7BEC0099A1B6 /* WASMModuleParser.cpp */,
</span><span class="cx">                                 53F40E941D5A7AEF0099A1B6 /* WASMModuleParser.h */,
</span><span class="lines">@@ -5743,8 +5754,6 @@
</span><span class="cx">                                 F692A85D0255597D01FF60F7 /* FunctionPrototype.h */,
</span><span class="cx">                                 62D2D38D1ADF103F000206C1 /* FunctionRareData.cpp */,
</span><span class="cx">                                 62D2D38E1ADF103F000206C1 /* FunctionRareData.h */,
</span><del>-                                70B791831C024432002481E2 /* GeneratorFrame.cpp */,
-                                70B791841C024432002481E2 /* GeneratorFrame.h */,
</del><span class="cx">                                 70B791851C024432002481E2 /* GeneratorFunctionConstructor.cpp */,
</span><span class="cx">                                 70B791861C024432002481E2 /* GeneratorFunctionConstructor.h */,
</span><span class="cx">                                 70B791871C024432002481E2 /* GeneratorFunctionPrototype.cpp */,
</span><span class="lines">@@ -6630,6 +6639,12 @@
</span><span class="cx">                 969A078F0ED1D3AE00F1F681 /* bytecode */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                E3A421421D6F588F0007C617 /* PreciseJumpTargetsInlines.h */,
+                                E3D264261D38C042000BE174 /* BytecodeGeneratorification.cpp */,
+                                E3D264271D38C042000BE174 /* BytecodeGeneratorification.h */,
+                                E3D264281D38C042000BE174 /* BytecodeGraph.h */,
+                                E3D264291D38C042000BE174 /* BytecodeRewriter.cpp */,
+                                E3D2642A1D38C042000BE174 /* BytecodeRewriter.h */,
</ins><span class="cx">                                 5370B4F31BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.cpp */,
</span><span class="cx">                                 5370B4F41BF25EA2005C40FC /* AdaptiveInferredPropertyValueWatchpointBase.h */,
</span><span class="cx">                                 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */,
</span><span class="lines">@@ -7184,6 +7199,7 @@
</span><span class="cx">                                 0FEC852D1BDACDAC0080FF74 /* B3ProcedureInlines.h in Headers */,
</span><span class="cx">                                 0FEC85BD1BE1462F0080FF74 /* B3ReduceStrength.h in Headers */,
</span><span class="cx">                                 0FEC85311BDACDAC0080FF74 /* B3StackmapSpecial.h in Headers */,
</span><ins>+                                E328DAE81D38D005001A2529 /* BytecodeGeneratorification.h in Headers */,
</ins><span class="cx">                                 0FEC85351BDACDAC0080FF74 /* B3SlotBaseValue.h in Headers */,
</span><span class="cx">                                 0FEC85361BDACDAC0080FF74 /* B3SuccessorCollection.h in Headers */,
</span><span class="cx">                                 0FEC85381BDACDAC0080FF74 /* B3SwitchCase.h in Headers */,
</span><span class="lines">@@ -7214,6 +7230,7 @@
</span><span class="cx">                                 99DA00A91BD5993100F4575C /* builtins_generate_separate_header.py in Headers */,
</span><span class="cx">                                 0F338E111BF0276C0013C88F /* B3OpaqueByproduct.h in Headers */,
</span><span class="cx">                                 FEA0C4031CDD7D1D00481991 /* FunctionWhitelist.h in Headers */,
</span><ins>+                                E3A421431D6F58930007C617 /* PreciseJumpTargetsInlines.h in Headers */,
</ins><span class="cx">                                 99DA00AA1BD5993100F4575C /* builtins_generate_separate_implementation.py in Headers */,
</span><span class="cx">                                 99DA00A31BD5993100F4575C /* builtins_generator.py in Headers */,
</span><span class="cx">                                 412952781D2CF6BC00E78B89 /* builtins_generate_internals_wrapper_implementation.py in Headers */,
</span><span class="lines">@@ -7449,7 +7466,6 @@
</span><span class="cx">                                 A737810E1799EA2E00817533 /* DFGNaturalLoops.h in Headers */,
</span><span class="cx">                                 86ECA3EA132DEF1C002B2AD7 /* DFGNode.h in Headers */,
</span><span class="cx">                                 0FFB921B16D02F010055A5DB /* DFGNodeAllocator.h in Headers */,
</span><del>-                                70B791931C024A28002481E2 /* GeneratorFrame.h in Headers */,
</del><span class="cx">                                 0FA581BB150E953000B9A2D9 /* DFGNodeFlags.h in Headers */,
</span><span class="cx">                                 0F300B7818AB051100A6D72E /* DFGNodeOrigin.h in Headers */,
</span><span class="cx">                                 0FA581BC150E953000B9A2D9 /* DFGNodeType.h in Headers */,
</span><span class="lines">@@ -7464,6 +7480,7 @@
</span><span class="cx">                                 0FD8A32617D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.h in Headers */,
</span><span class="cx">                                 0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */,
</span><span class="cx">                                 0F235BEC17178E7300690C7F /* DFGOSRExitBase.h in Headers */,
</span><ins>+                                E39D45F51D39005600B3B377 /* InterpreterInlines.h in Headers */,
</ins><span class="cx">                                 0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */,
</span><span class="cx">                                 0FC0977114693AF500CF2442 /* DFGOSRExitCompiler.h in Headers */,
</span><span class="cx">                                 0F7025AA1714B0FC00382C0E /* DFGOSRExitCompilerCommon.h in Headers */,
</span><span class="lines">@@ -7726,6 +7743,7 @@
</span><span class="cx">                                 E33B3E261B7ABD750048DB2E /* InspectorInstrumentationObject.lut.h in Headers */,
</span><span class="cx">                                 A532438C18568335002ED692 /* InspectorProtocolObjects.h in Headers */,
</span><span class="cx">                                 A55D93AC18514F7900400DED /* InspectorProtocolTypes.h in Headers */,
</span><ins>+                                E328DAEB1D38D005001A2529 /* BytecodeRewriter.h in Headers */,
</ins><span class="cx">                                 A50E4B6218809DD50068A46D /* InspectorRuntimeAgent.h in Headers */,
</span><span class="cx">                                 A593CF831840377100BFCE27 /* InspectorValues.h in Headers */,
</span><span class="cx">                                 969A07990ED1D3AE00F1F681 /* Instruction.h in Headers */,
</span><span class="lines">@@ -7857,6 +7875,7 @@
</span><span class="cx">                                 E33F50811B8429A400413856 /* JSInternalPromise.h in Headers */,
</span><span class="cx">                                 0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */,
</span><span class="cx">                                 E33F50791B84225700413856 /* JSInternalPromiseConstructor.h in Headers */,
</span><ins>+                                E328DAE91D38D005001A2529 /* BytecodeGraph.h in Headers */,
</ins><span class="cx">                                 E33F50871B8449EF00413856 /* JSInternalPromiseConstructor.lut.h in Headers */,
</span><span class="cx">                                 E33F50851B8437A000413856 /* JSInternalPromiseDeferred.h in Headers */,
</span><span class="cx">                                 E33F50751B8421C000413856 /* JSInternalPromisePrototype.h in Headers */,
</span><span class="lines">@@ -7945,7 +7964,7 @@
</span><span class="cx">                                 0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */,
</span><span class="cx">                                 99DA00B01BD5994E00F4575C /* lazywriter.py in Headers */,
</span><span class="cx">                                 BC18C4310E16F5CD00B34460 /* Lexer.h in Headers */,
</span><del>-                                53F40E931D5A4AB30099A1B6 /* WASMB3IRGenerator.h in Headers */,
</del><ins>+                                53F40E931D5A4AB30099A1B6 /* WASMB3IRGenerator.h in Headers */,
</ins><span class="cx">                                 BC18C52E0E16FCE100B34460 /* Lexer.lut.h in Headers */,
</span><span class="cx">                                 DCF3D56B1CD29472003D5C65 /* LazyClassStructureInlines.h in Headers */,
</span><span class="cx">                                 FE187A021BFBE5610038BBCA /* JITMulGenerator.h in Headers */,
</span><span class="lines">@@ -8823,6 +8842,7 @@
</span><span class="cx">                                 147F39BD107EC37600427A48 /* ArgList.cpp in Sources */,
</span><span class="cx">                                 0F743BAA16B88249009F9277 /* ARM64Disassembler.cpp in Sources */,
</span><span class="cx">                                 86D3B2C310156BDE002865E7 /* ARMAssembler.cpp in Sources */,
</span><ins>+                                E328DAE71D38D004001A2529 /* BytecodeGeneratorification.cpp in Sources */,
</ins><span class="cx">                                 65C02850171795E200351E35 /* ARMv7Disassembler.cpp in Sources */,
</span><span class="cx">                                 65C0285C1717966800351E35 /* ARMv7DOpcode.cpp in Sources */,
</span><span class="cx">                                 0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */,
</span><span class="lines">@@ -9158,6 +9178,7 @@
</span><span class="cx">                                 0F25F1B1181635F300522F39 /* FTLSlowPathCall.cpp in Sources */,
</span><span class="cx">                                 0F338DF11BE93AD10013C88F /* B3StackmapValue.cpp in Sources */,
</span><span class="cx">                                 0F25F1B3181635F300522F39 /* FTLSlowPathCallKey.cpp in Sources */,
</span><ins>+                                E328DAEA1D38D005001A2529 /* BytecodeRewriter.cpp in Sources */,
</ins><span class="cx">                                 4319DA031C1BE40A001D260B /* B3LowerMacrosAfterOptimizations.cpp in Sources */,
</span><span class="cx">                                 0FEA0A161706BB9000BB722C /* FTLState.cpp in Sources */,
</span><span class="cx">                                 0F235BE117178E1C00690C7F /* FTLThunks.cpp in Sources */,
</span><span class="lines">@@ -9565,7 +9586,6 @@
</span><span class="cx">                                 79EE0BFF1B4AFB85000385C9 /* VariableEnvironment.cpp in Sources */,
</span><span class="cx">                                 0F6C73501AC9F99F00BE1682 /* VariableWriteFireDetail.cpp in Sources */,
</span><span class="cx">                                 0FE0502C1AA9095600D33B33 /* VarOffset.cpp in Sources */,
</span><del>-                                70B791921C024A23002481E2 /* GeneratorFrame.cpp in Sources */,
</del><span class="cx">                                 0F20C2591A8013AB00DA3229 /* VirtualRegister.cpp in Sources */,
</span><span class="cx">                                 E18E3A590DF9278C00D90B34 /* VM.cpp in Sources */,
</span><span class="cx">                                 FE5932A7183C5A2600A1ECCC /* VMEntryScope.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebuiltinsGeneratorPrototypejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/builtins/GeneratorPrototype.js (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/builtins/GeneratorPrototype.js        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/builtins/GeneratorPrototype.js        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -51,7 +51,7 @@
</span><span class="cx">     } else {
</span><span class="cx">         try {
</span><span class="cx">             generator.@generatorState = @GeneratorStateExecuting;
</span><del>-            value = generator.@generatorNext.@call(generator.@generatorThis, generator, state, sentValue, resumeMode);
</del><ins>+            value = generator.@generatorNext.@call(generator.@generatorThis, generator, state, sentValue, resumeMode, generator.@generatorFrame);
</ins><span class="cx">             if (generator.@generatorState === @GeneratorStateExecuting) {
</span><span class="cx">                 generator.@generatorState = @GeneratorStateCompleted;
</span><span class="cx">                 done = true;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeBasicBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #include &quot;BytecodeBasicBlock.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><ins>+#include &quot;InterpreterInlines.h&quot;
</ins><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;PreciseJumpTargets.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -34,69 +35,10 @@
</span><span class="cx"> 
</span><span class="cx"> void BytecodeBasicBlock::shrinkToFit()
</span><span class="cx"> {
</span><del>-    m_bytecodeOffsets.shrinkToFit();
</del><ins>+    m_offsets.shrinkToFit();
</ins><span class="cx">     m_successors.shrinkToFit();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool isBranch(OpcodeID opcodeID)
-{
-    switch (opcodeID) {
-    case op_jmp:
-    case op_jtrue:
-    case op_jfalse:
-    case op_jeq_null:
-    case op_jneq_null:
-    case op_jneq_ptr:
-    case op_jless:
-    case op_jlesseq:
-    case op_jgreater:
-    case op_jgreatereq:
-    case op_jnless:
-    case op_jnlesseq:
-    case op_jngreater:
-    case op_jngreatereq:
-    case op_switch_imm:
-    case op_switch_char:
-    case op_switch_string:
-    case op_save:
-        return true;
-    default:
-        return false;
-    }
-}
-
-static bool isUnconditionalBranch(OpcodeID opcodeID)
-{
-    switch (opcodeID) {
-    case op_jmp:
-        return true;
-    default:
-        return false;
-    }
-}
-
-static bool isTerminal(OpcodeID opcodeID)
-{
-    switch (opcodeID) {
-    case op_ret:
-    case op_end:
-        return true;
-    default:
-        return false;
-    }
-}
-
-static bool isThrow(OpcodeID opcodeID)
-{
-    switch (opcodeID) {
-    case op_throw:
-    case op_throw_static_error:
-        return true;
-    default:
-        return false;
-    }
-}
-
</del><span class="cx"> static bool isJumpTarget(OpcodeID opcodeID, const Vector&lt;unsigned, 32&gt;&amp; jumpTargets, unsigned bytecodeOffset)
</span><span class="cx"> {
</span><span class="cx">     if (opcodeID == op_catch)
</span><span class="lines">@@ -105,16 +47,21 @@
</span><span class="cx">     return std::binary_search(jumpTargets.begin(), jumpTargets.end(), bytecodeOffset);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void linkBlocks(BytecodeBasicBlock* predecessor, BytecodeBasicBlock* successor)
</del><ins>+template&lt;typename Block, typename Instruction&gt;
+void BytecodeBasicBlock::computeImpl(Block* codeBlock, Instruction* instructionsBegin, unsigned instructionCount, Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks)
</ins><span class="cx"> {
</span><del>-    predecessor-&gt;addSuccessor(successor);
-}
-
-void computeBytecodeBasicBlocks(CodeBlock* codeBlock, Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks)
-{
</del><span class="cx">     Vector&lt;unsigned, 32&gt; jumpTargets;
</span><del>-    computePreciseJumpTargets(codeBlock, jumpTargets);
</del><ins>+    computePreciseJumpTargets(codeBlock, instructionsBegin, instructionCount, jumpTargets);
</ins><span class="cx"> 
</span><ins>+    auto appendBlock = [&amp;] (std::unique_ptr&lt;BytecodeBasicBlock&gt;&amp;&amp; block) {
+        block-&gt;m_index = basicBlocks.size();
+        basicBlocks.append(WTFMove(block));
+    };
+
+    auto linkBlocks = [&amp;] (BytecodeBasicBlock* from, BytecodeBasicBlock* to) {
+        from-&gt;addSuccessor(to);
+    };
+
</ins><span class="cx">     // Create the entry and exit basic blocks.
</span><span class="cx">     basicBlocks.reserveCapacity(jumpTargets.size() + 2);
</span><span class="cx"> 
</span><span class="lines">@@ -122,9 +69,9 @@
</span><span class="cx">     auto firstBlock = std::make_unique&lt;BytecodeBasicBlock&gt;(0, 0);
</span><span class="cx">     linkBlocks(entry.get(), firstBlock.get());
</span><span class="cx"> 
</span><del>-    basicBlocks.append(WTFMove(entry));
</del><ins>+    appendBlock(WTFMove(entry));
</ins><span class="cx">     BytecodeBasicBlock* current = firstBlock.get();
</span><del>-    basicBlocks.append(WTFMove(firstBlock));
</del><ins>+    appendBlock(WTFMove(firstBlock));
</ins><span class="cx"> 
</span><span class="cx">     auto exit = std::make_unique&lt;BytecodeBasicBlock&gt;(BytecodeBasicBlock::ExitBlock);
</span><span class="cx"> 
</span><span class="lines">@@ -131,10 +78,8 @@
</span><span class="cx">     bool nextInstructionIsLeader = false;
</span><span class="cx"> 
</span><span class="cx">     Interpreter* interpreter = codeBlock-&gt;vm()-&gt;interpreter;
</span><del>-    Instruction* instructionsBegin = codeBlock-&gt;instructions().begin();
-    unsigned instructionCount = codeBlock-&gt;instructions().size();
</del><span class="cx">     for (unsigned bytecodeOffset = 0; bytecodeOffset &lt; instructionCount;) {
</span><del>-        OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode);
</del><ins>+        OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instructionsBegin[bytecodeOffset]);
</ins><span class="cx">         unsigned opcodeLength = opcodeLengths[opcodeID];
</span><span class="cx"> 
</span><span class="cx">         bool createdBlock = false;
</span><span class="lines">@@ -142,7 +87,7 @@
</span><span class="cx">         if (isJumpTarget(opcodeID, jumpTargets, bytecodeOffset) || nextInstructionIsLeader) {
</span><span class="cx">             auto newBlock = std::make_unique&lt;BytecodeBasicBlock&gt;(bytecodeOffset, opcodeLength);
</span><span class="cx">             current = newBlock.get();
</span><del>-            basicBlocks.append(WTFMove(newBlock));
</del><ins>+            appendBlock(WTFMove(newBlock));
</ins><span class="cx">             createdBlock = true;
</span><span class="cx">             nextInstructionIsLeader = false;
</span><span class="cx">             bytecodeOffset += opcodeLength;
</span><span class="lines">@@ -156,7 +101,7 @@
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><span class="cx">         // Otherwise, just add to the length of the current block.
</span><del>-        current-&gt;addBytecodeLength(opcodeLength);
</del><ins>+        current-&gt;addLength(opcodeLength);
</ins><span class="cx">         bytecodeOffset += opcodeLength;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -168,13 +113,12 @@
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><span class="cx">         bool fallsThrough = true; 
</span><del>-        for (unsigned bytecodeOffset = block-&gt;leaderBytecodeOffset(); bytecodeOffset &lt; block-&gt;leaderBytecodeOffset() + block-&gt;totalBytecodeLength();) {
-            const Instruction&amp; currentInstruction = instructionsBegin[bytecodeOffset];
-            OpcodeID opcodeID = interpreter-&gt;getOpcodeID(currentInstruction.u.opcode);
</del><ins>+        for (unsigned bytecodeOffset = block-&gt;leaderOffset(); bytecodeOffset &lt; block-&gt;leaderOffset() + block-&gt;totalLength();) {
+            OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instructionsBegin[bytecodeOffset]);
</ins><span class="cx">             unsigned opcodeLength = opcodeLengths[opcodeID];
</span><span class="cx">             // If we found a terminal bytecode, link to the exit block.
</span><span class="cx">             if (isTerminal(opcodeID)) {
</span><del>-                ASSERT(bytecodeOffset + opcodeLength == block-&gt;leaderBytecodeOffset() + block-&gt;totalBytecodeLength());
</del><ins>+                ASSERT(bytecodeOffset + opcodeLength == block-&gt;leaderOffset() + block-&gt;totalLength());
</ins><span class="cx">                 linkBlocks(block, exit.get());
</span><span class="cx">                 fallsThrough = false;
</span><span class="cx">                 break;
</span><span class="lines">@@ -184,8 +128,8 @@
</span><span class="cx">             // If there isn't one, treat this throw as a terminal. This is true even if we have a finally
</span><span class="cx">             // block because the finally block will create its own catch, which will generate a HandlerInfo.
</span><span class="cx">             if (isThrow(opcodeID)) {
</span><del>-                ASSERT(bytecodeOffset + opcodeLength == block-&gt;leaderBytecodeOffset() + block-&gt;totalBytecodeLength());
-                HandlerInfo* handler = codeBlock-&gt;handlerForBytecodeOffset(bytecodeOffset);
</del><ins>+                ASSERT(bytecodeOffset + opcodeLength == block-&gt;leaderOffset() + block-&gt;totalLength());
+                auto* handler = codeBlock-&gt;handlerForBytecodeOffset(bytecodeOffset);
</ins><span class="cx">                 fallsThrough = false;
</span><span class="cx">                 if (!handler) {
</span><span class="cx">                     linkBlocks(block, exit.get());
</span><span class="lines">@@ -193,7 +137,7 @@
</span><span class="cx">                 }
</span><span class="cx">                 for (unsigned i = 0; i &lt; basicBlocks.size(); i++) {
</span><span class="cx">                     BytecodeBasicBlock* otherBlock = basicBlocks[i].get();
</span><del>-                    if (handler-&gt;target == otherBlock-&gt;leaderBytecodeOffset()) {
</del><ins>+                    if (handler-&gt;target == otherBlock-&gt;leaderOffset()) {
</ins><span class="cx">                         linkBlocks(block, otherBlock);
</span><span class="cx">                         break;
</span><span class="cx">                     }
</span><span class="lines">@@ -203,13 +147,13 @@
</span><span class="cx"> 
</span><span class="cx">             // If we found a branch, link to the block(s) that we jump to.
</span><span class="cx">             if (isBranch(opcodeID)) {
</span><del>-                ASSERT(bytecodeOffset + opcodeLength == block-&gt;leaderBytecodeOffset() + block-&gt;totalBytecodeLength());
</del><ins>+                ASSERT(bytecodeOffset + opcodeLength == block-&gt;leaderOffset() + block-&gt;totalLength());
</ins><span class="cx">                 Vector&lt;unsigned, 1&gt; bytecodeOffsetsJumpedTo;
</span><del>-                findJumpTargetsForBytecodeOffset(codeBlock, bytecodeOffset, bytecodeOffsetsJumpedTo);
</del><ins>+                findJumpTargetsForBytecodeOffset(codeBlock, instructionsBegin, bytecodeOffset, bytecodeOffsetsJumpedTo);
</ins><span class="cx"> 
</span><span class="cx">                 for (unsigned i = 0; i &lt; basicBlocks.size(); i++) {
</span><span class="cx">                     BytecodeBasicBlock* otherBlock = basicBlocks[i].get();
</span><del>-                    if (bytecodeOffsetsJumpedTo.contains(otherBlock-&gt;leaderBytecodeOffset()))
</del><ins>+                    if (bytecodeOffsetsJumpedTo.contains(otherBlock-&gt;leaderOffset()))
</ins><span class="cx">                         linkBlocks(block, otherBlock);
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="lines">@@ -229,10 +173,20 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    basicBlocks.append(WTFMove(exit));
</del><ins>+    appendBlock(WTFMove(exit));
</ins><span class="cx">     
</span><span class="cx">     for (auto&amp; basicBlock : basicBlocks)
</span><span class="cx">         basicBlock-&gt;shrinkToFit();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void BytecodeBasicBlock::compute(CodeBlock* codeBlock, Instruction* instructionsBegin, unsigned instructionCount, Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks)
+{
+    computeImpl(codeBlock, instructionsBegin, instructionCount, basicBlocks);
+}
+
+void BytecodeBasicBlock::compute(UnlinkedCodeBlock* codeBlock, UnlinkedInstruction* instructionsBegin, unsigned instructionCount, Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks)
+{
+    BytecodeBasicBlock::computeImpl(codeBlock, instructionsBegin, instructionCount, basicBlocks);
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeBasicBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeBasicBlock.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -33,6 +33,9 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class CodeBlock;
</span><ins>+class UnlinkedCodeBlock;
+struct Instruction;
+struct UnlinkedInstruction;
</ins><span class="cx"> 
</span><span class="cx"> class BytecodeBasicBlock {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="lines">@@ -42,26 +45,36 @@
</span><span class="cx">     BytecodeBasicBlock(SpecialBlockType);
</span><span class="cx">     void shrinkToFit();
</span><span class="cx"> 
</span><del>-    bool isEntryBlock() { return !m_leaderBytecodeOffset &amp;&amp; !m_totalBytecodeLength; }
-    bool isExitBlock() { return m_leaderBytecodeOffset == UINT_MAX &amp;&amp; m_totalBytecodeLength == UINT_MAX; }
</del><ins>+    bool isEntryBlock() { return !m_leaderOffset &amp;&amp; !m_totalLength; }
+    bool isExitBlock() { return m_leaderOffset == UINT_MAX &amp;&amp; m_totalLength == UINT_MAX; }
</ins><span class="cx"> 
</span><del>-    unsigned leaderBytecodeOffset() { return m_leaderBytecodeOffset; }
-    unsigned totalBytecodeLength() { return m_totalBytecodeLength; }
</del><ins>+    unsigned leaderOffset() { return m_leaderOffset; }
+    unsigned totalLength() { return m_totalLength; }
</ins><span class="cx"> 
</span><del>-    Vector&lt;unsigned&gt;&amp; bytecodeOffsets() { return m_bytecodeOffsets; }
-    void addBytecodeLength(unsigned);
</del><ins>+    const Vector&lt;unsigned&gt;&amp; offsets() const { return m_offsets; }
</ins><span class="cx"> 
</span><del>-    Vector&lt;BytecodeBasicBlock*&gt;&amp; successors() { return m_successors; }
-    void addSuccessor(BytecodeBasicBlock* block) { m_successors.append(block); }
</del><ins>+    const Vector&lt;BytecodeBasicBlock*&gt;&amp; successors() const { return m_successors; }
</ins><span class="cx"> 
</span><span class="cx">     FastBitVector&amp; in() { return m_in; }
</span><span class="cx">     FastBitVector&amp; out() { return m_out; }
</span><span class="cx"> 
</span><ins>+    unsigned index() const { return m_index; }
+
+    static void compute(CodeBlock*, Instruction* instructionsBegin, unsigned instructionCount, Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp;);
+    static void compute(UnlinkedCodeBlock*, UnlinkedInstruction* instructionsBegin, unsigned instructionCount, Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp;);
+
</ins><span class="cx"> private:
</span><del>-    unsigned m_leaderBytecodeOffset;
-    unsigned m_totalBytecodeLength;
</del><ins>+    template&lt;typename Block, typename Instruction&gt; static void computeImpl(Block* codeBlock, Instruction* instructionsBegin, unsigned instructionCount, Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks);
</ins><span class="cx"> 
</span><del>-    Vector&lt;unsigned&gt; m_bytecodeOffsets;
</del><ins>+    void addSuccessor(BytecodeBasicBlock* block) { m_successors.append(block); }
+
+    void addLength(unsigned);
+
+    unsigned m_leaderOffset;
+    unsigned m_totalLength;
+    unsigned m_index;
+
+    Vector&lt;unsigned&gt; m_offsets;
</ins><span class="cx">     Vector&lt;BytecodeBasicBlock*&gt; m_successors;
</span><span class="cx"> 
</span><span class="cx">     FastBitVector m_in;
</span><span class="lines">@@ -68,25 +81,23 @@
</span><span class="cx">     FastBitVector m_out;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-void computeBytecodeBasicBlocks(CodeBlock*, Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp;);
-
</del><span class="cx"> inline BytecodeBasicBlock::BytecodeBasicBlock(unsigned start, unsigned length)
</span><del>-    : m_leaderBytecodeOffset(start)
-    , m_totalBytecodeLength(length)
</del><ins>+    : m_leaderOffset(start)
+    , m_totalLength(length)
</ins><span class="cx"> {
</span><del>-    m_bytecodeOffsets.append(m_leaderBytecodeOffset);
</del><ins>+    m_offsets.append(m_leaderOffset);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline BytecodeBasicBlock::BytecodeBasicBlock(BytecodeBasicBlock::SpecialBlockType blockType)
</span><del>-    : m_leaderBytecodeOffset(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX)
-    , m_totalBytecodeLength(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX)
</del><ins>+    : m_leaderOffset(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX)
+    , m_totalLength(blockType == BytecodeBasicBlock::EntryBlock ? 0 : UINT_MAX)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void BytecodeBasicBlock::addBytecodeLength(unsigned bytecodeLength)
</del><ins>+inline void BytecodeBasicBlock::addLength(unsigned bytecodeLength)
</ins><span class="cx"> {
</span><del>-    m_bytecodeOffsets.append(m_leaderBytecodeOffset + m_totalBytecodeLength);
-    m_totalBytecodeLength += bytecodeLength;
</del><ins>+    m_offsets.append(m_leaderOffset + m_totalLength);
+    m_totalLength += bytecodeLength;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeGeneratorificationcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.cpp (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,268 @@
</span><ins>+/*
+ * Copyright (C) 2016 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;BytecodeGeneratorification.h&quot;
+
+#include &quot;BytecodeLivenessAnalysisInlines.h&quot;
+#include &quot;BytecodeRewriter.h&quot;
+#include &quot;BytecodeUseDef.h&quot;
+#include &quot;IdentifierInlines.h&quot;
+#include &quot;InterpreterInlines.h&quot;
+#include &quot;JSCInlines.h&quot;
+#include &quot;JSCJSValueInlines.h&quot;
+#include &quot;JSGeneratorFunction.h&quot;
+#include &quot;StrongInlines.h&quot;
+#include &quot;UnlinkedCodeBlock.h&quot;
+#include &lt;wtf/Optional.h&gt;
+
+namespace JSC {
+
+struct YieldData {
+    size_t point { 0 };
+    int argument { 0 };
+    FastBitVector liveness;
+};
+
+class BytecodeGeneratorification {
+public:
+    typedef Vector&lt;YieldData&gt; Yields;
+
+    BytecodeGeneratorification(UnlinkedCodeBlock* codeBlock, UnlinkedCodeBlock::UnpackedInstructions&amp; instructions, SymbolTable* generatorFrameSymbolTable, int generatorFrameSymbolTableIndex)
+        : m_graph(codeBlock, instructions)
+        , m_generatorFrameSymbolTable(*codeBlock-&gt;vm(), generatorFrameSymbolTable)
+        , m_generatorFrameSymbolTableIndex(generatorFrameSymbolTableIndex)
+    {
+        for (BytecodeBasicBlock* block : m_graph) {
+            for (unsigned bytecodeOffset : block-&gt;offsets()) {
+                const UnlinkedInstruction* pc = &amp;m_graph.instructions()[bytecodeOffset];
+                switch (pc-&gt;u.opcode) {
+                case op_enter: {
+                    m_enterPoint = bytecodeOffset;
+                    break;
+                }
+
+                case op_yield: {
+                    unsigned liveCalleeLocalsIndex = pc[2].u.index;
+                    if (liveCalleeLocalsIndex &gt;= m_yields.size())
+                        m_yields.resize(liveCalleeLocalsIndex + 1);
+                    YieldData&amp; data = m_yields[liveCalleeLocalsIndex];
+                    data.point = bytecodeOffset;
+                    data.argument = pc[3].u.operand;
+                    break;
+                }
+
+                default:
+                    break;
+                }
+            }
+        }
+    }
+
+    struct Storage {
+        Identifier identifier;
+        unsigned identifierIndex;
+        ScopeOffset scopeOffset;
+    };
+
+    void run();
+
+    BytecodeGraph&lt;UnlinkedCodeBlock&gt;&amp; graph() { return m_graph; }
+
+    const Yields&amp; yields() const
+    {
+        return m_yields;
+    }
+
+    Yields&amp; yields()
+    {
+        return m_yields;
+    }
+
+    unsigned enterPoint() const
+    {
+        return m_enterPoint;
+    }
+
+private:
+    Storage storageForGeneratorLocal(unsigned index)
+    {
+        // We assign a symbol to a register. There is one-on-one corresponding between a register and a symbol.
+        // By doing so, we allocate the specific storage to save the given register.
+        // This allow us not to save all the live registers even if the registers are not overwritten from the previous resuming time.
+        // It means that, the register can be retrieved even if the immediate previous op_save does not save it.
+
+        if (m_storages.size() &lt;= index)
+            m_storages.resize(index + 1);
+        if (Optional&lt;Storage&gt; storage = m_storages[index])
+            return *storage;
+
+        UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();
+        Identifier identifier = Identifier::fromUid(PrivateName());
+        unsigned identifierIndex = codeBlock-&gt;numberOfIdentifiers();
+        codeBlock-&gt;addIdentifier(identifier);
+        ScopeOffset scopeOffset = m_generatorFrameSymbolTable-&gt;takeNextScopeOffset(NoLockingNecessary);
+        m_generatorFrameSymbolTable-&gt;set(NoLockingNecessary, identifier.impl(), SymbolTableEntry(VarOffset(scopeOffset)));
+
+        Storage storage = {
+            identifier,
+            identifierIndex,
+            scopeOffset
+        };
+        m_storages[index] = storage;
+        return storage;
+    }
+
+    unsigned m_enterPoint { 0 };
+    BytecodeGraph&lt;UnlinkedCodeBlock&gt; m_graph;
+    Vector&lt;Optional&lt;Storage&gt;&gt; m_storages;
+    Yields m_yields;
+    Strong&lt;SymbolTable&gt; m_generatorFrameSymbolTable;
+    int m_generatorFrameSymbolTableIndex;
+};
+
+class GeneratorLivenessAnalysis : public BytecodeLivenessPropagation&lt;GeneratorLivenessAnalysis&gt; {
+public:
+    GeneratorLivenessAnalysis(BytecodeGeneratorification&amp; generatorification)
+        : m_generatorification(generatorification)
+    {
+    }
+
+    template&lt;typename Functor&gt;
+    void computeDefsForBytecodeOffset(UnlinkedCodeBlock* codeBlock, OpcodeID opcodeID, UnlinkedInstruction* instruction, FastBitVector&amp;, const Functor&amp; functor)
+    {
+        JSC::computeDefsForBytecodeOffset(codeBlock, opcodeID, instruction, functor);
+    }
+
+    template&lt;typename Functor&gt;
+    void computeUsesForBytecodeOffset(UnlinkedCodeBlock* codeBlock, OpcodeID opcodeID, UnlinkedInstruction* instruction, FastBitVector&amp;, const Functor&amp; functor)
+    {
+        JSC::computeUsesForBytecodeOffset(codeBlock, opcodeID, instruction, functor);
+    }
+
+    void run()
+    {
+        // Perform modified liveness analysis to determine which locals are live at the merge points.
+        // This produces the conservative results for the question, &quot;which variables should be saved and resumed?&quot;.
+
+        runLivenessFixpoint(m_generatorification.graph());
+
+        for (YieldData&amp; data : m_generatorification.yields())
+            data.liveness = getLivenessInfoAtBytecodeOffset(m_generatorification.graph(), data.point + opcodeLength(op_yield));
+    }
+
+private:
+    BytecodeGeneratorification&amp; m_generatorification;
+};
+
+void BytecodeGeneratorification::run()
+{
+    // We calculate the liveness at each merge point. This gives us the information which registers should be saved and resumed conservatively.
+
+    {
+        GeneratorLivenessAnalysis pass(*this);
+        pass.run();
+    }
+
+    UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();
+    BytecodeRewriter rewriter(m_graph);
+
+    // Setup the global switch for the generator.
+    {
+        unsigned nextToEnterPoint = enterPoint() + opcodeLength(op_enter);
+        unsigned switchTableIndex = m_graph.codeBlock()-&gt;numberOfSwitchJumpTables();
+        VirtualRegister state = virtualRegisterForArgument(static_cast&lt;int32_t&gt;(JSGeneratorFunction::GeneratorArgument::State));
+        auto&amp; jumpTable = m_graph.codeBlock()-&gt;addSwitchJumpTable();
+        jumpTable.min = 0;
+        jumpTable.branchOffsets.resize(m_yields.size() + 1);
+        jumpTable.branchOffsets.fill(0);
+        jumpTable.add(0, nextToEnterPoint);
+        for (unsigned i = 0; i &lt; m_yields.size(); ++i)
+            jumpTable.add(i + 1, m_yields[i].point);
+
+        rewriter.insertFragmentBefore(nextToEnterPoint, [&amp;](BytecodeRewriter::Fragment&amp; fragment) {
+            fragment.appendInstruction(op_switch_imm, switchTableIndex, nextToEnterPoint, state.offset());
+        });
+    }
+
+    for (const YieldData&amp; data : m_yields) {
+        VirtualRegister scope = virtualRegisterForArgument(static_cast&lt;int32_t&gt;(JSGeneratorFunction::GeneratorArgument::Frame));
+
+        // Emit save sequence.
+        rewriter.insertFragmentBefore(data.point, [&amp;](BytecodeRewriter::Fragment&amp; fragment) {
+            data.liveness.forEachSetBit([&amp;](size_t index) {
+                VirtualRegister operand = virtualRegisterForLocal(index);
+                Storage storage = storageForGeneratorLocal(index);
+
+                fragment.appendInstruction(
+                    op_put_to_scope,
+                    scope.offset(), // scope
+                    storage.identifierIndex, // identifier
+                    operand.offset(), // value
+                    GetPutInfo(DoNotThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization).operand(), // info
+                    m_generatorFrameSymbolTableIndex, // symbol table constant index
+                    storage.scopeOffset.offset() // scope offset
+                );
+            });
+
+            // Insert op_ret just after save sequence.
+            fragment.appendInstruction(op_ret, data.argument);
+        });
+
+        // Emit resume sequence.
+        rewriter.insertFragmentAfter(data.point, [&amp;](BytecodeRewriter::Fragment&amp; fragment) {
+            data.liveness.forEachSetBit([&amp;](size_t index) {
+                VirtualRegister operand = virtualRegisterForLocal(index);
+                Storage storage = storageForGeneratorLocal(index);
+
+                UnlinkedValueProfile profile = codeBlock-&gt;addValueProfile();
+                fragment.appendInstruction(
+                    op_get_from_scope,
+                    operand.offset(), // dst
+                    scope.offset(), // scope
+                    storage.identifierIndex, // identifier
+                    GetPutInfo(DoNotThrowIfNotFound, LocalClosureVar, InitializationMode::NotInitialization).operand(), // info
+                    0, // local scope depth
+                    storage.scopeOffset.offset(), // scope offset
+                    profile // profile
+                );
+            });
+        });
+
+        // Clip the unnecessary bytecodes.
+        rewriter.removeBytecode(data.point);
+    }
+
+    rewriter.execute();
+}
+
+void performGeneratorification(UnlinkedCodeBlock* codeBlock, UnlinkedCodeBlock::UnpackedInstructions&amp; instructions, SymbolTable* generatorFrameSymbolTable, int generatorFrameSymbolTableIndex)
+{
+    BytecodeGeneratorification pass(codeBlock, instructions, generatorFrameSymbolTable, generatorFrameSymbolTableIndex);
+    pass.run();
+}
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeGeneratorificationhfromrev204993trunkSourceJavaScriptCorebytecodeBytecodeLivenessAnalysisInlinesh"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.h (from rev 204993, trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h) (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeGeneratorification.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+/*
+ * Copyright (C) 2016 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &quot;UnlinkedCodeBlock.h&quot;
+
+namespace JSC {
+
+class SymbolTable;
+
+void performGeneratorification(UnlinkedCodeBlock*, UnlinkedCodeBlock::UnpackedInstructions&amp;, SymbolTable* generatorFrameSymbolTable, int generatorFrameSymbolTableIndex);
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeGraphh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/BytecodeGraph.h (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeGraph.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeGraph.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,125 @@
</span><ins>+/*
+ * Copyright (C) 2016 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &quot;BytecodeBasicBlock.h&quot;
+#include &lt;wtf/IndexedContainerIterator.h&gt;
+#include &lt;wtf/IteratorRange.h&gt;
+#include &lt;wtf/Vector.h&gt;
+
+namespace JSC {
+
+class BytecodeBasicBlock;
+
+template&lt;typename Block&gt;
+class BytecodeGraph {
+    WTF_MAKE_FAST_ALLOCATED;
+    WTF_MAKE_NONCOPYABLE(BytecodeGraph);
+public:
+    typedef Block CodeBlock;
+    typedef typename Block::Instruction Instruction;
+    typedef Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt; BasicBlocksVector;
+
+    typedef WTF::IndexedContainerIterator&lt;BytecodeGraph&lt;Block&gt;&gt; iterator;
+
+    inline BytecodeGraph(Block*, typename Block::UnpackedInstructions&amp;);
+
+    Block* codeBlock() const { return m_codeBlock; }
+
+    typename Block::UnpackedInstructions&amp; instructions() { return m_instructions; }
+
+    WTF::IteratorRange&lt;BasicBlocksVector::reverse_iterator&gt; basicBlocksInReverseOrder()
+    {
+        return WTF::makeIteratorRange(m_basicBlocks.rbegin(), m_basicBlocks.rend());
+    }
+
+    static bool blockContainsBytecodeOffset(BytecodeBasicBlock* block, unsigned bytecodeOffset)
+    {
+        unsigned leaderOffset = block-&gt;leaderOffset();
+        return bytecodeOffset &gt;= leaderOffset &amp;&amp; bytecodeOffset &lt; leaderOffset + block-&gt;totalLength();
+    }
+
+    BytecodeBasicBlock* findBasicBlockForBytecodeOffset(unsigned bytecodeOffset)
+    {
+        /*
+            for (unsigned i = 0; i &lt; m_basicBlocks.size(); i++) {
+                if (blockContainsBytecodeOffset(m_basicBlocks[i].get(), bytecodeOffset))
+                    return m_basicBlocks[i].get();
+            }
+            return 0;
+        */
+
+        std::unique_ptr&lt;BytecodeBasicBlock&gt;* basicBlock = approximateBinarySearch&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;, unsigned&gt;(m_basicBlocks, m_basicBlocks.size(), bytecodeOffset, [] (std::unique_ptr&lt;BytecodeBasicBlock&gt;* basicBlock) { return (*basicBlock)-&gt;leaderOffset(); });
+        // We found the block we were looking for.
+        if (blockContainsBytecodeOffset((*basicBlock).get(), bytecodeOffset))
+            return (*basicBlock).get();
+
+        // Basic block is to the left of the returned block.
+        if (bytecodeOffset &lt; (*basicBlock)-&gt;leaderOffset()) {
+            ASSERT(basicBlock - 1 &gt;= m_basicBlocks.data());
+            ASSERT(blockContainsBytecodeOffset(basicBlock[-1].get(), bytecodeOffset));
+            return basicBlock[-1].get();
+        }
+
+        // Basic block is to the right of the returned block.
+        ASSERT(&amp;basicBlock[1] &lt;= &amp;m_basicBlocks.last());
+        ASSERT(blockContainsBytecodeOffset(basicBlock[1].get(), bytecodeOffset));
+        return basicBlock[1].get();
+    }
+
+    BytecodeBasicBlock* findBasicBlockWithLeaderOffset(unsigned leaderOffset)
+    {
+        return (*tryBinarySearch&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;, unsigned&gt;(m_basicBlocks, m_basicBlocks.size(), leaderOffset, [] (std::unique_ptr&lt;BytecodeBasicBlock&gt;* basicBlock) { return (*basicBlock)-&gt;leaderOffset(); })).get();
+    }
+
+    unsigned size() const { return m_basicBlocks.size(); }
+    BytecodeBasicBlock* at(unsigned index) const { return m_basicBlocks[index].get(); }
+    BytecodeBasicBlock* operator[](unsigned index) const { return at(index); }
+
+    iterator begin() const { return iterator(*this, 0); }
+    iterator end() const { return iterator(*this, size()); }
+    BytecodeBasicBlock* first() { return at(0); }
+    BytecodeBasicBlock* last() { return at(size() - 1); }
+
+private:
+    Block* m_codeBlock;
+    BasicBlocksVector m_basicBlocks;
+    typename Block::UnpackedInstructions&amp; m_instructions;
+};
+
+
+template&lt;typename Block&gt;
+BytecodeGraph&lt;Block&gt;::BytecodeGraph(Block* codeBlock, typename Block::UnpackedInstructions&amp; instructions)
+    : m_codeBlock(codeBlock)
+    , m_instructions(instructions)
+{
+    ASSERT(m_codeBlock);
+    BytecodeBasicBlock::compute(m_codeBlock, instructions.begin(), instructions.size(), m_basicBlocks);
+    ASSERT(m_basicBlocks.size());
+}
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeListjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeList.json (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -143,8 +143,7 @@
</span><span class="cx">             { &quot;name&quot; : &quot;op_assert&quot;, &quot;length&quot; : 3 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_create_rest&quot;, &quot;length&quot;: 4 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_get_rest_length&quot;, &quot;length&quot;: 3 },
</span><del>-            { &quot;name&quot; : &quot;op_save&quot;, &quot;length&quot; : 4 },
-            { &quot;name&quot; : &quot;op_resume&quot;, &quot;length&quot; : 3 },
</del><ins>+            { &quot;name&quot; : &quot;op_yield&quot;, &quot;length&quot; : 4 },
</ins><span class="cx">             { &quot;name&quot; : &quot;op_watchdog&quot;, &quot;length&quot; : 1 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_log_shadow_chicken_prologue&quot;, &quot;length&quot; : 2},
</span><span class="cx">             { &quot;name&quot; : &quot;op_log_shadow_chicken_tail&quot;, &quot;length&quot; : 3}
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeLivenessAnalysiscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -31,198 +31,36 @@
</span><span class="cx"> #include &quot;BytecodeUseDef.h&quot;
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;FullBytecodeLiveness.h&quot;
</span><del>-#include &quot;PreciseJumpTargets.h&quot;
</del><ins>+#include &quot;InterpreterInlines.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> BytecodeLivenessAnalysis::BytecodeLivenessAnalysis(CodeBlock* codeBlock)
</span><del>-    : m_codeBlock(codeBlock)
</del><ins>+    : m_graph(codeBlock, codeBlock-&gt;instructions())
</ins><span class="cx"> {
</span><del>-    ASSERT(m_codeBlock);
</del><span class="cx">     compute();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static bool isValidRegisterForLiveness(CodeBlock* codeBlock, int operand)
</del><ins>+template&lt;typename Functor&gt;
+void BytecodeLivenessAnalysis::computeDefsForBytecodeOffset(CodeBlock* codeBlock, OpcodeID opcodeID, Instruction* instruction, FastBitVector&amp;, const Functor&amp; functor)
</ins><span class="cx"> {
</span><del>-    if (codeBlock-&gt;isConstantRegisterIndex(operand))
-        return false;
-    
-    VirtualRegister virtualReg(operand);
-    return virtualReg.isLocal();
</del><ins>+    JSC::computeDefsForBytecodeOffset(codeBlock, opcodeID, instruction, functor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static unsigned getLeaderOffsetForBasicBlock(std::unique_ptr&lt;BytecodeBasicBlock&gt;* basicBlock)
</del><ins>+template&lt;typename Functor&gt;
+void BytecodeLivenessAnalysis::computeUsesForBytecodeOffset(CodeBlock* codeBlock, OpcodeID opcodeID, Instruction* instruction, FastBitVector&amp;, const Functor&amp; functor)
</ins><span class="cx"> {
</span><del>-    return (*basicBlock)-&gt;leaderBytecodeOffset();
</del><ins>+    JSC::computeUsesForBytecodeOffset(codeBlock, opcodeID, instruction, functor);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static BytecodeBasicBlock* findBasicBlockWithLeaderOffset(Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks, unsigned leaderOffset)
-{
-    return (*tryBinarySearch&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;, unsigned&gt;(basicBlocks, basicBlocks.size(), leaderOffset, getLeaderOffsetForBasicBlock)).get();
-}
-
-static bool blockContainsBytecodeOffset(BytecodeBasicBlock* block, unsigned bytecodeOffset)
-{
-    unsigned leaderOffset = block-&gt;leaderBytecodeOffset();
-    return bytecodeOffset &gt;= leaderOffset &amp;&amp; bytecodeOffset &lt; leaderOffset + block-&gt;totalBytecodeLength();
-}
-
-static BytecodeBasicBlock* findBasicBlockForBytecodeOffset(Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks, unsigned bytecodeOffset)
-{
-/*
-    for (unsigned i = 0; i &lt; basicBlocks.size(); i++) {
-        if (blockContainsBytecodeOffset(basicBlocks[i].get(), bytecodeOffset))
-            return basicBlocks[i].get();
-    }
-    return 0;
-*/
-    std::unique_ptr&lt;BytecodeBasicBlock&gt;* basicBlock = approximateBinarySearch&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;, unsigned&gt;(
-        basicBlocks, basicBlocks.size(), bytecodeOffset, getLeaderOffsetForBasicBlock);
-    // We found the block we were looking for.
-    if (blockContainsBytecodeOffset((*basicBlock).get(), bytecodeOffset))
-        return (*basicBlock).get();
-
-    // Basic block is to the left of the returned block.
-    if (bytecodeOffset &lt; (*basicBlock)-&gt;leaderBytecodeOffset()) {
-        ASSERT(basicBlock - 1 &gt;= basicBlocks.data());
-        ASSERT(blockContainsBytecodeOffset(basicBlock[-1].get(), bytecodeOffset));
-        return basicBlock[-1].get();
-    }
-
-    // Basic block is to the right of the returned block.
-    ASSERT(&amp;basicBlock[1] &lt;= &amp;basicBlocks.last());
-    ASSERT(blockContainsBytecodeOffset(basicBlock[1].get(), bytecodeOffset));
-    return basicBlock[1].get();
-}
-
-// Simplified interface to bytecode use/def, which determines defs first and then uses, and includes
-// exception handlers in the uses.
-template&lt;typename UseFunctor, typename DefFunctor&gt;
-static void stepOverInstruction(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks, unsigned bytecodeOffset, const UseFunctor&amp; use, const DefFunctor&amp; 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
-    // operand, like:
-    //
-    //     op_add loc1, loc1, loc2
-    //
-    // The use of loc1 happens before the def of loc1. That's a semantic requirement since the add
-    // operation cannot travel forward in time to read the value that it will produce after reading that
-    // value. Since we are executing in reverse, this means that we must do defs before uses (reverse of
-    // uses before defs).
-    //
-    // Since this is a liveness analysis, this ordering ends up being particularly important: if we did
-    // 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).
-    
-    computeDefsForBytecodeOffset(
-        codeBlock, block, bytecodeOffset,
-        [&amp;] (CodeBlock* codeBlock, Instruction*, OpcodeID, int operand) {
-            if (isValidRegisterForLiveness(codeBlock, operand))
-                def(VirtualRegister(operand).toLocal());
-        });
-
-    computeUsesForBytecodeOffset(
-        codeBlock, block, bytecodeOffset,
-        [&amp;] (CodeBlock* codeBlock, Instruction*, OpcodeID, int operand) {
-            if (isValidRegisterForLiveness(codeBlock, operand))
-                use(VirtualRegister(operand).toLocal());
-        });
-
-    // If we have an exception handler, we want the live-in variables of the 
-    // exception handler block to be included in the live-in of this particular bytecode.
-    if (HandlerInfo* handler = codeBlock-&gt;handlerForBytecodeOffset(bytecodeOffset)) {
-        // FIXME: This resume check should not be needed.
-        // https://bugs.webkit.org/show_bug.cgi?id=159281
-        Interpreter* interpreter = codeBlock-&gt;vm()-&gt;interpreter;
-        Instruction* instructionsBegin = codeBlock-&gt;instructions().begin();
-        Instruction* instruction = &amp;instructionsBegin[bytecodeOffset];
-        OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instruction-&gt;u.opcode);
-        if (opcodeID != op_resume) {
-            BytecodeBasicBlock* handlerBlock = findBasicBlockWithLeaderOffset(basicBlocks, handler-&gt;target);
-            ASSERT(handlerBlock);
-            handlerBlock-&gt;in().forEachSetBit(use);
-        }
-    }
-}
-
-static void stepOverInstruction(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks, unsigned bytecodeOffset, FastBitVector&amp; out)
-{
-    stepOverInstruction(
-        codeBlock, block, basicBlocks, bytecodeOffset,
-        [&amp;] (unsigned bitIndex) {
-            // This is the use functor, so we set the bit.
-            out.set(bitIndex);
-        },
-        [&amp;] (unsigned bitIndex) {
-            // This is the def functor, so we clear the bit.
-            out.clear(bitIndex);
-        });
-}
-
-static void computeLocalLivenessForBytecodeOffset(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks, unsigned targetOffset, FastBitVector&amp; result)
-{
-    ASSERT(!block-&gt;isExitBlock());
-    ASSERT(!block-&gt;isEntryBlock());
-
-    FastBitVector out = block-&gt;out();
-
-    for (int i = block-&gt;bytecodeOffsets().size() - 1; i &gt;= 0; i--) {
-        unsigned bytecodeOffset = block-&gt;bytecodeOffsets()[i];
-        if (targetOffset &gt; bytecodeOffset)
-            break;
-        
-        stepOverInstruction(codeBlock, block, basicBlocks, bytecodeOffset, out);
-    }
-
-    result.set(out);
-}
-
-static void computeLocalLivenessForBlock(CodeBlock* codeBlock, BytecodeBasicBlock* block, Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt;&amp; basicBlocks)
-{
-    if (block-&gt;isExitBlock() || block-&gt;isEntryBlock())
-        return;
-    computeLocalLivenessForBytecodeOffset(codeBlock, block, basicBlocks, block-&gt;leaderBytecodeOffset(), block-&gt;in());
-}
-
-void BytecodeLivenessAnalysis::runLivenessFixpoint()
-{
-    UnlinkedCodeBlock* unlinkedCodeBlock = m_codeBlock-&gt;unlinkedCodeBlock();
-    unsigned numberOfVariables = unlinkedCodeBlock-&gt;m_numCalleeLocals;
-
-    for (unsigned i = 0; i &lt; m_basicBlocks.size(); i++) {
-        BytecodeBasicBlock* block = m_basicBlocks[i].get();
-        block-&gt;in().resize(numberOfVariables);
-        block-&gt;out().resize(numberOfVariables);
-    }
-
-    bool changed;
-    m_basicBlocks.last()-&gt;in().clearAll();
-    m_basicBlocks.last()-&gt;out().clearAll();
-    FastBitVector newOut;
-    newOut.resize(m_basicBlocks.last()-&gt;out().numBits());
-    do {
-        changed = false;
-        for (unsigned i = m_basicBlocks.size() - 1; i--;) {
-            BytecodeBasicBlock* block = m_basicBlocks[i].get();
-            newOut.clearAll();
-            for (unsigned j = 0; j &lt; block-&gt;successors().size(); j++)
-                newOut.merge(block-&gt;successors()[j]-&gt;in());
-            bool outDidChange = block-&gt;out().setAndCheck(newOut);
-            computeLocalLivenessForBlock(m_codeBlock, block, m_basicBlocks);
-            changed |= outDidChange;
-        }
-    } while (changed);
-}
-
</del><span class="cx"> void BytecodeLivenessAnalysis::getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset, FastBitVector&amp; result)
</span><span class="cx"> {
</span><del>-    BytecodeBasicBlock* block = findBasicBlockForBytecodeOffset(m_basicBlocks, bytecodeOffset);
</del><ins>+    BytecodeBasicBlock* block = m_graph.findBasicBlockForBytecodeOffset(bytecodeOffset);
</ins><span class="cx">     ASSERT(block);
</span><span class="cx">     ASSERT(!block-&gt;isEntryBlock());
</span><span class="cx">     ASSERT(!block-&gt;isExitBlock());
</span><span class="cx">     result.resize(block-&gt;out().numBits());
</span><del>-    computeLocalLivenessForBytecodeOffset(m_codeBlock, block, m_basicBlocks, bytecodeOffset, result);
</del><ins>+    computeLocalLivenessForBytecodeOffset(m_graph, block, bytecodeOffset, result);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool BytecodeLivenessAnalysis::operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset)
</span><span class="lines">@@ -244,19 +82,19 @@
</span><span class="cx"> void BytecodeLivenessAnalysis::computeFullLiveness(FullBytecodeLiveness&amp; result)
</span><span class="cx"> {
</span><span class="cx">     FastBitVector out;
</span><ins>+    CodeBlock* codeBlock = m_graph.codeBlock();
</ins><span class="cx">     
</span><del>-    result.m_map.resize(m_codeBlock-&gt;instructions().size());
</del><ins>+    result.m_map.resize(codeBlock-&gt;instructions().size());
</ins><span class="cx">     
</span><del>-    for (unsigned i = m_basicBlocks.size(); i--;) {
-        BytecodeBasicBlock* block = m_basicBlocks[i].get();
</del><ins>+    for (std::unique_ptr&lt;BytecodeBasicBlock&gt;&amp; block : m_graph.basicBlocksInReverseOrder()) {
</ins><span class="cx">         if (block-&gt;isEntryBlock() || block-&gt;isExitBlock())
</span><span class="cx">             continue;
</span><span class="cx">         
</span><span class="cx">         out = block-&gt;out();
</span><span class="cx">         
</span><del>-        for (unsigned i = block-&gt;bytecodeOffsets().size(); i--;) {
-            unsigned bytecodeOffset = block-&gt;bytecodeOffsets()[i];
-            stepOverInstruction(m_codeBlock, block, m_basicBlocks, bytecodeOffset, out);
</del><ins>+        for (unsigned i = block-&gt;offsets().size(); i--;) {
+            unsigned bytecodeOffset = block-&gt;offsets()[i];
+            stepOverInstruction(m_graph, bytecodeOffset, out);
</ins><span class="cx">             result.m_map[bytecodeOffset] = out;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -266,20 +104,20 @@
</span><span class="cx"> {
</span><span class="cx">     FastBitVector out;
</span><span class="cx">     
</span><del>-    result.m_codeBlock = m_codeBlock;
-    result.m_killSets = std::make_unique&lt;BytecodeKills::KillSet[]&gt;(m_codeBlock-&gt;instructions().size());
</del><ins>+    CodeBlock* codeBlock = m_graph.codeBlock();
+    result.m_codeBlock = codeBlock;
+    result.m_killSets = std::make_unique&lt;BytecodeKills::KillSet[]&gt;(codeBlock-&gt;instructions().size());
</ins><span class="cx">     
</span><del>-    for (unsigned i = m_basicBlocks.size(); i--;) {
-        BytecodeBasicBlock* block = m_basicBlocks[i].get();
</del><ins>+    for (std::unique_ptr&lt;BytecodeBasicBlock&gt;&amp; block : m_graph.basicBlocksInReverseOrder()) {
</ins><span class="cx">         if (block-&gt;isEntryBlock() || block-&gt;isExitBlock())
</span><span class="cx">             continue;
</span><span class="cx">         
</span><span class="cx">         out = block-&gt;out();
</span><span class="cx">         
</span><del>-        for (unsigned i = block-&gt;bytecodeOffsets().size(); i--;) {
-            unsigned bytecodeOffset = block-&gt;bytecodeOffsets()[i];
</del><ins>+        for (unsigned i = block-&gt;offsets().size(); i--;) {
+            unsigned bytecodeOffset = block-&gt;offsets()[i];
</ins><span class="cx">             stepOverInstruction(
</span><del>-                m_codeBlock, block, m_basicBlocks, bytecodeOffset,
</del><ins>+                m_graph, bytecodeOffset, out,
</ins><span class="cx">                 [&amp;] (unsigned index) {
</span><span class="cx">                     // This is for uses.
</span><span class="cx">                     if (out.get(index))
</span><span class="lines">@@ -297,12 +135,13 @@
</span><span class="cx"> 
</span><span class="cx"> void BytecodeLivenessAnalysis::dumpResults()
</span><span class="cx"> {
</span><del>-    dataLog(&quot;\nDumping bytecode liveness for &quot;, *m_codeBlock, &quot;:\n&quot;);
-    Interpreter* interpreter = m_codeBlock-&gt;vm()-&gt;interpreter;
-    Instruction* instructionsBegin = m_codeBlock-&gt;instructions().begin();
-    for (unsigned i = 0; i &lt; m_basicBlocks.size(); i++) {
-        BytecodeBasicBlock* block = m_basicBlocks[i].get();
-        dataLogF(&quot;\nBytecode basic block %u: %p (offset: %u, length: %u)\n&quot;, i, block, block-&gt;leaderBytecodeOffset(), block-&gt;totalBytecodeLength());
</del><ins>+    CodeBlock* codeBlock = m_graph.codeBlock();
+    dataLog(&quot;\nDumping bytecode liveness for &quot;, *codeBlock, &quot;:\n&quot;);
+    Interpreter* interpreter = codeBlock-&gt;vm()-&gt;interpreter;
+    Instruction* instructionsBegin = codeBlock-&gt;instructions().begin();
+    unsigned i = 0;
+    for (BytecodeBasicBlock* block : m_graph) {
+        dataLogF(&quot;\nBytecode basic block %u: %p (offset: %u, length: %u)\n&quot;, i++, block, block-&gt;leaderOffset(), block-&gt;totalLength());
</ins><span class="cx">         dataLogF(&quot;Successors: &quot;);
</span><span class="cx">         for (unsigned j = 0; j &lt; block-&gt;successors().size(); j++) {
</span><span class="cx">             BytecodeBasicBlock* successor = block-&gt;successors()[j];
</span><span class="lines">@@ -317,7 +156,7 @@
</span><span class="cx">             dataLogF(&quot;Exit block: %p\n&quot;, block);
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><del>-        for (unsigned bytecodeOffset = block-&gt;leaderBytecodeOffset(); bytecodeOffset &lt; block-&gt;leaderBytecodeOffset() + block-&gt;totalBytecodeLength();) {
</del><ins>+        for (unsigned bytecodeOffset = block-&gt;leaderOffset(); bytecodeOffset &lt; block-&gt;leaderOffset() + block-&gt;totalLength();) {
</ins><span class="cx">             const Instruction* currentInstruction = &amp;instructionsBegin[bytecodeOffset];
</span><span class="cx"> 
</span><span class="cx">             dataLogF(&quot;Live variables: &quot;);
</span><span class="lines">@@ -327,7 +166,7 @@
</span><span class="cx">                     dataLogF(&quot;%u &quot;, j);
</span><span class="cx">             }
</span><span class="cx">             dataLogF(&quot;\n&quot;);
</span><del>-            m_codeBlock-&gt;dumpBytecode(WTF::dataFile(), m_codeBlock-&gt;globalObject()-&gt;globalExec(), instructionsBegin, currentInstruction);
</del><ins>+            codeBlock-&gt;dumpBytecode(WTF::dataFile(), codeBlock-&gt;globalObject()-&gt;globalExec(), instructionsBegin, currentInstruction);
</ins><span class="cx"> 
</span><span class="cx">             OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode);
</span><span class="cx">             unsigned opcodeLength = opcodeLengths[opcodeID];
</span><span class="lines">@@ -346,9 +185,7 @@
</span><span class="cx"> 
</span><span class="cx"> void BytecodeLivenessAnalysis::compute()
</span><span class="cx"> {
</span><del>-    computeBytecodeBasicBlocks(m_codeBlock, m_basicBlocks);
-    ASSERT(m_basicBlocks.size());
-    runLivenessFixpoint();
</del><ins>+    runLivenessFixpoint(m_graph);
</ins><span class="cx"> 
</span><span class="cx">     if (Options::dumpBytecodeLivenessResults())
</span><span class="cx">         dumpResults();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeLivenessAnalysish"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysis.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -23,10 +23,11 @@
</span><span class="cx">  * THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef BytecodeLivenessAnalysis_h
-#define BytecodeLivenessAnalysis_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;BytecodeBasicBlock.h&quot;
</span><ins>+#include &quot;BytecodeGraph.h&quot;
+#include &quot;CodeBlock.h&quot;
</ins><span class="cx"> #include &lt;wtf/FastBitVector.h&gt;
</span><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="lines">@@ -34,13 +35,29 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class BytecodeKills;
</span><del>-class CodeBlock;
</del><span class="cx"> class FullBytecodeLiveness;
</span><span class="cx"> 
</span><del>-class BytecodeLivenessAnalysis {
</del><ins>+template&lt;typename DerivedAnalysis&gt;
+class BytecodeLivenessPropagation {
+protected:
+    template&lt;typename Graph, typename UseFunctor, typename DefFunctor&gt; void stepOverInstruction(Graph&amp;, unsigned bytecodeOffset, FastBitVector&amp; out, const UseFunctor&amp;, const DefFunctor&amp;);
+
+    template&lt;typename Graph&gt; void stepOverInstruction(Graph&amp;, unsigned bytecodeOffset, FastBitVector&amp; out);
+
+    template&lt;typename Graph&gt; bool computeLocalLivenessForBytecodeOffset(Graph&amp;, BytecodeBasicBlock*, unsigned targetOffset, FastBitVector&amp; result);
+
+    template&lt;typename Graph&gt; bool computeLocalLivenessForBlock(Graph&amp;, BytecodeBasicBlock*);
+
+    template&lt;typename Graph&gt; FastBitVector getLivenessInfoAtBytecodeOffset(Graph&amp;, unsigned bytecodeOffset);
+
+    template&lt;typename Graph&gt; void runLivenessFixpoint(Graph&amp;);
+};
+
+class BytecodeLivenessAnalysis : private BytecodeLivenessPropagation&lt;BytecodeLivenessAnalysis&gt; {
</ins><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(BytecodeLivenessAnalysis);
</span><span class="cx"> public:
</span><ins>+    friend class BytecodeLivenessPropagation&lt;BytecodeLivenessAnalysis&gt;;
</ins><span class="cx">     BytecodeLivenessAnalysis(CodeBlock*);
</span><span class="cx">     
</span><span class="cx">     bool operandIsLiveAtBytecodeOffset(int operand, unsigned bytecodeOffset);
</span><span class="lines">@@ -51,19 +68,19 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     void compute();
</span><del>-    void runLivenessFixpoint();
</del><span class="cx">     void dumpResults();
</span><span class="cx"> 
</span><span class="cx">     void getLivenessInfoAtBytecodeOffset(unsigned bytecodeOffset, FastBitVector&amp;);
</span><span class="cx"> 
</span><del>-    CodeBlock* m_codeBlock;
-    Vector&lt;std::unique_ptr&lt;BytecodeBasicBlock&gt;&gt; m_basicBlocks;
</del><ins>+    template&lt;typename Functor&gt; void computeDefsForBytecodeOffset(CodeBlock*, OpcodeID, Instruction*, FastBitVector&amp;, const Functor&amp;);
+    template&lt;typename Functor&gt; void computeUsesForBytecodeOffset(CodeBlock*, OpcodeID, Instruction*, FastBitVector&amp;, const Functor&amp;);
+
+    BytecodeGraph&lt;CodeBlock&gt; m_graph;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> inline bool operandIsAlwaysLive(int operand);
</span><span class="cx"> inline bool operandThatIsNotAlwaysLiveIsLive(const FastBitVector&amp; out, int operand);
</span><span class="cx"> inline bool operandIsLive(const FastBitVector&amp; out, int operand);
</span><ins>+inline bool isValidRegisterForLiveness(int operand);
</ins><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span><del>-
-#endif // BytecodeLivenessAnalysis_h
</del></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeLivenessAnalysisInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeLivenessAnalysisInlines.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -23,11 +23,12 @@
</span><span class="cx">  * THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef BytecodeLivenessAnalysisInlines_h
-#define BytecodeLivenessAnalysisInlines_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><ins>+#include &quot;BytecodeGraph.h&quot;
</ins><span class="cx"> #include &quot;BytecodeLivenessAnalysis.h&quot;
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><ins>+#include &quot;Interpreter.h&quot;
</ins><span class="cx"> #include &quot;Operations.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -50,7 +51,151 @@
</span><span class="cx">     return operandIsAlwaysLive(operand) || operandThatIsNotAlwaysLiveIsLive(out, operand);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-} // namespace JSC
</del><ins>+inline bool isValidRegisterForLiveness(int operand)
+{
+    VirtualRegister virtualReg(operand);
+    if (virtualReg.isConstant())
+        return false;
+    return virtualReg.isLocal();
+}
</ins><span class="cx"> 
</span><del>-#endif // BytecodeLivenessAnalysisInlines_h
</del><ins>+// Simplified interface to bytecode use/def, which determines defs first and then uses, and includes
+// exception handlers in the uses.
+template&lt;typename DerivedAnalysis&gt;
+template&lt;typename Graph, typename UseFunctor, typename DefFunctor&gt;
+inline void BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::stepOverInstruction(Graph&amp; graph, unsigned bytecodeOffset, FastBitVector&amp; out, const UseFunctor&amp; use, const DefFunctor&amp; 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
+    // operand, like:
+    //
+    //     op_add loc1, loc1, loc2
+    //
+    // The use of loc1 happens before the def of loc1. That's a semantic requirement since the add
+    // operation cannot travel forward in time to read the value that it will produce after reading that
+    // value. Since we are executing in reverse, this means that we must do defs before uses (reverse of
+    // uses before defs).
+    //
+    // Since this is a liveness analysis, this ordering ends up being particularly important: if we did
+    // 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).
</ins><span class="cx"> 
</span><ins>+    auto* codeBlock = graph.codeBlock();
+    Interpreter* interpreter = codeBlock-&gt;vm()-&gt;interpreter;
+    auto* instructionsBegin = graph.instructions().begin();
+    auto* instruction = &amp;instructionsBegin[bytecodeOffset];
+    OpcodeID opcodeID = interpreter-&gt;getOpcodeID(*instruction);
+
+    static_cast&lt;DerivedAnalysis*&gt;(this)-&gt;computeDefsForBytecodeOffset(
+        codeBlock, opcodeID, instruction, out,
+        [&amp;] (typename Graph::CodeBlock*, typename Graph::Instruction*, OpcodeID, int operand) {
+            if (isValidRegisterForLiveness(operand))
+                def(VirtualRegister(operand).toLocal());
+        });
+
+    static_cast&lt;DerivedAnalysis*&gt;(this)-&gt;computeUsesForBytecodeOffset(
+        codeBlock, opcodeID, instruction, out,
+        [&amp;] (typename Graph::CodeBlock*, typename Graph::Instruction*, OpcodeID, int operand) {
+            if (isValidRegisterForLiveness(operand))
+                use(VirtualRegister(operand).toLocal());
+        });
+
+    // If we have an exception handler, we want the live-in variables of the 
+    // exception handler block to be included in the live-in of this particular bytecode.
+    if (auto* handler = codeBlock-&gt;handlerForBytecodeOffset(bytecodeOffset)) {
+        BytecodeBasicBlock* handlerBlock = graph.findBasicBlockWithLeaderOffset(handler-&gt;target);
+        ASSERT(handlerBlock);
+        handlerBlock-&gt;in().forEachSetBit(use);
+    }
+}
+
+template&lt;typename DerivedAnalysis&gt;
+template&lt;typename Graph&gt;
+inline void BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::stepOverInstruction(Graph&amp; graph, unsigned bytecodeOffset, FastBitVector&amp; out)
+{
+    stepOverInstruction(
+        graph, bytecodeOffset, out,
+        [&amp;] (unsigned bitIndex) {
+            // This is the use functor, so we set the bit.
+            out.set(bitIndex);
+        },
+        [&amp;] (unsigned bitIndex) {
+            // This is the def functor, so we clear the bit.
+            out.clear(bitIndex);
+        });
+}
+
+template&lt;typename DerivedAnalysis&gt;
+template&lt;typename Graph&gt;
+inline bool BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::computeLocalLivenessForBytecodeOffset(Graph&amp; graph, BytecodeBasicBlock* block, unsigned targetOffset, FastBitVector&amp; result)
+{
+    ASSERT(!block-&gt;isExitBlock());
+    ASSERT(!block-&gt;isEntryBlock());
+
+    FastBitVector out = block-&gt;out();
+
+    for (int i = block-&gt;offsets().size() - 1; i &gt;= 0; i--) {
+        unsigned bytecodeOffset = block-&gt;offsets()[i];
+        if (targetOffset &gt; bytecodeOffset)
+            break;
+        stepOverInstruction(graph, bytecodeOffset, out);
+    }
+
+    return result.setAndCheck(out);
+}
+
+template&lt;typename DerivedAnalysis&gt;
+template&lt;typename Graph&gt;
+inline bool BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::computeLocalLivenessForBlock(Graph&amp; graph, BytecodeBasicBlock* block)
+{
+    if (block-&gt;isExitBlock() || block-&gt;isEntryBlock())
+        return false;
+    return computeLocalLivenessForBytecodeOffset(graph, block, block-&gt;leaderOffset(), block-&gt;in());
+}
+
+template&lt;typename DerivedAnalysis&gt;
+template&lt;typename Graph&gt;
+inline FastBitVector BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::getLivenessInfoAtBytecodeOffset(Graph&amp; graph, unsigned bytecodeOffset)
+{
+    BytecodeBasicBlock* block = graph.findBasicBlockForBytecodeOffset(bytecodeOffset);
+    ASSERT(block);
+    ASSERT(!block-&gt;isEntryBlock());
+    ASSERT(!block-&gt;isExitBlock());
+    FastBitVector out;
+    out.resize(block-&gt;out().numBits());
+    computeLocalLivenessForBytecodeOffset(graph, block, bytecodeOffset, out);
+    return out;
+}
+
+template&lt;typename DerivedAnalysis&gt;
+template&lt;typename Graph&gt;
+inline void BytecodeLivenessPropagation&lt;DerivedAnalysis&gt;::runLivenessFixpoint(Graph&amp; graph)
+{
+    auto* codeBlock = graph.codeBlock();
+    unsigned numberOfVariables = codeBlock-&gt;numCalleeLocals();
+    for (BytecodeBasicBlock* block : graph) {
+        block-&gt;in().resize(numberOfVariables);
+        block-&gt;out().resize(numberOfVariables);
+        block-&gt;in().clearAll();
+        block-&gt;out().clearAll();
+    }
+
+    bool changed;
+    BytecodeBasicBlock* lastBlock = graph.last();
+    lastBlock-&gt;in().clearAll();
+    lastBlock-&gt;out().clearAll();
+    FastBitVector newOut;
+    newOut.resize(lastBlock-&gt;out().numBits());
+    do {
+        changed = false;
+        for (std::unique_ptr&lt;BytecodeBasicBlock&gt;&amp; block : graph.basicBlocksInReverseOrder()) {
+            newOut.clearAll();
+            for (BytecodeBasicBlock* successor : block-&gt;successors())
+                newOut.merge(successor-&gt;in());
+            block-&gt;out().set(newOut);
+            changed |= computeLocalLivenessForBlock(graph, block.get());
+        }
+    } while (changed);
+}
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeRewritercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/BytecodeRewriter.cpp (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeRewriter.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeRewriter.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,115 @@
</span><ins>+/*
+ * Copyright (C) 2016 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;BytecodeRewriter.h&quot;
+
+#include &quot;PreciseJumpTargetsInlines.h&quot;
+#include &lt;wtf/BubbleSort.h&gt;
+
+namespace JSC {
+
+void BytecodeRewriter::applyModification()
+{
+    for (size_t insertionIndex = m_insertions.size(); insertionIndex--;) {
+        Insertion&amp; insertion = m_insertions[insertionIndex];
+        if (insertion.type == Insertion::Type::Remove)
+            m_graph.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_insertions.clear();
+}
+
+void BytecodeRewriter::execute()
+{
+    WTF::bubbleSort(m_insertions.begin(), m_insertions.end(), [] (const Insertion&amp; lhs, const Insertion&amp; rhs) {
+        return lhs.index &lt; rhs.index;
+    });
+
+    UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();
+    codeBlock-&gt;applyModification(*this);
+}
+
+void BytecodeRewriter::adjustJumpTargetsInFragment(unsigned finalOffset, Insertion&amp; insertion)
+{
+    auto&amp; fragment = insertion.instructions;
+    UnlinkedInstruction* instructionsBegin = fragment.data();
+    for (unsigned fragmentOffset = 0, fragmentCount = fragment.size(); fragmentOffset &lt; fragmentCount;) {
+        UnlinkedInstruction&amp; instruction = fragment[fragmentOffset];
+        OpcodeID opcodeID = instruction.u.opcode;
+        if (isBranch(opcodeID)) {
+            unsigned bytecodeOffset = finalOffset + fragmentOffset;
+            UnlinkedCodeBlock* codeBlock = m_graph.codeBlock();
+            extractStoredJumpTargetsForBytecodeOffset(codeBlock, codeBlock-&gt;vm()-&gt;interpreter, instructionsBegin, fragmentOffset, [&amp;](int32_t&amp; label) {
+                int absoluteOffset = adjustAbsoluteOffset(label);
+                label = absoluteOffset - static_cast&lt;int&gt;(bytecodeOffset);
+            });
+        }
+        fragmentOffset += opcodeLength(opcodeID);
+    }
+}
+
+void BytecodeRewriter::insertImpl(InsertionPoint insertionPoint, IncludeBranch includeBranch, Vector&lt;UnlinkedInstruction&gt;&amp;&amp; fragment)
+{
+    ASSERT(insertionPoint.position == Position::Before || insertionPoint.position == Position::After);
+    m_insertions.append(Insertion {
+        insertionPoint,
+        Insertion::Type::Insert,
+        includeBranch,
+        0,
+        WTFMove(fragment)
+    });
+}
+
+int BytecodeRewriter::adjustJumpTarget(InsertionPoint startPoint, InsertionPoint jumpTargetPoint)
+{
+    if (startPoint &lt; jumpTargetPoint) {
+        int jumpTarget = jumpTargetPoint.bytecodeOffset;
+        auto start = std::lower_bound(m_insertions.begin(), m_insertions.end(), startPoint, [&amp;] (const Insertion&amp; insertion, InsertionPoint startPoint) {
+            return insertion.index &lt; startPoint;
+        });
+        if (start != m_insertions.end()) {
+            auto end = std::lower_bound(m_insertions.begin(), m_insertions.end(), jumpTargetPoint, [&amp;] (const Insertion&amp; insertion, InsertionPoint jumpTargetPoint) {
+                return insertion.index &lt; jumpTargetPoint;
+            });
+            jumpTarget += calculateDifference(start, end);
+        }
+        return jumpTarget - startPoint.bytecodeOffset;
+    }
+
+    if (startPoint == jumpTargetPoint)
+        return 0;
+
+    return -adjustJumpTarget(jumpTargetPoint, startPoint);
+}
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeRewriterh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/BytecodeRewriter.h (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeRewriter.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeRewriter.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,235 @@
</span><ins>+/*
+ * Copyright (C) 2016 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &quot;BytecodeGraph.h&quot;
+#include &quot;Bytecodes.h&quot;
+#include &quot;Opcode.h&quot;
+#include &quot;UnlinkedCodeBlock.h&quot;
+#include &lt;wtf/Insertion.h&gt;
+
+namespace JSC {
+
+// BytecodeRewriter offers the ability to insert and remove the bytecodes including jump operations.
+//
+// We use the original bytecode offsets as labels. When you emit some jumps, you can specify the jump target by
+// using the original bytecode offsets. These bytecode offsets are later converted appropriate values by the
+// rewriter. And we also use the labels to represents the position the new bytecodes inserted.
+//
+//                      |  [bytecode]  |  [bytecode]  |
+//   offsets            A              B              C
+//
+// We can use the above &quot;A&quot;, &quot;B&quot;, and &quot;C&quot; offsets as labels. And the rewriter has the ability to insert bytecode fragments
+// before and after the label. For example, if you insert the fragment after &quot;B&quot;, the layout becomes like this.
+//
+//                      |  [bytecode]  |  [fragment]  [bytecode]  |
+//   offsets            A              B                          C
+//
+//  And even if you remove some original bytecodes, the offset remains as labels. For example, when you remove the A's bytecode,
+//  the layout becomes like this.
+//
+//                      |              |  [bytecode]  |
+//   offsets            A              B              C
+//
+//  And still you can insert fragments before and after &quot;A&quot;.
+//
+//                      |  [fragment]  |  [bytecode]  |
+//   offsets            A              B              C
+//
+//   We can insert bytecode fragments &quot;Before&quot; and &quot;After&quot; the labels. This inserted position, either &quot;Before&quot; and &quot;After&quot;,
+//   has effect when the label is involved with jumps. For example, when you have jump to the position &quot;B&quot;,
+//
+//                      |  [bytecode]  |  [bytecode]  |
+//   offsets            A              B              C
+//                                     ^
+//                                     jump to here.
+//
+//  and you insert the bytecode before/after &quot;B&quot;,
+//
+//                      |  [bytecode] [before]  |  [after] [bytecode]  |
+//   offsets            A                       B              C
+//                                              ^
+//                                              jump to here.
+//
+//  as you can see, the execution jumping into &quot;B&quot; does not execute [before] code.
+class BytecodeRewriter {
+WTF_MAKE_NONCOPYABLE(BytecodeRewriter);
+public:
+    enum class Position : int8_t {
+        EntryPoint = -2,
+        Before = -1,
+        LabelPoint = 0,
+        After = 1,
+        OriginalBytecodePoint = 2,
+    };
+
+    enum class IncludeBranch : uint8_t {
+        No = 0,
+        Yes = 1,
+    };
+
+    struct InsertionPoint {
+        int bytecodeOffset;
+        Position position;
+
+        InsertionPoint(int offset, Position pos)
+            : bytecodeOffset(offset)
+            , position(pos)
+        {
+        }
+
+        bool operator&lt;(const InsertionPoint&amp; other) const
+        {
+            if (bytecodeOffset == other.bytecodeOffset)
+                return position &lt; other.position;
+            return bytecodeOffset &lt; other.bytecodeOffset;
+        }
+
+        bool operator==(const InsertionPoint&amp; other) const
+        {
+            return bytecodeOffset == other.bytecodeOffset &amp;&amp; position == other.position;
+        }
+    };
+
+private:
+    struct Insertion {
+        enum class Type : uint8_t { Insert = 0, Remove = 1, };
+
+        size_t length() const
+        {
+            if (type == Type::Remove)
+                return removeLength;
+            return instructions.size();
+        }
+
+        InsertionPoint index;
+        Type type;
+        IncludeBranch includeBranch;
+        size_t removeLength;
+        Vector&lt;UnlinkedInstruction&gt; instructions;
+    };
+
+public:
+    class Fragment {
+    WTF_MAKE_NONCOPYABLE(Fragment);
+    public:
+        Fragment(Vector&lt;UnlinkedInstruction&gt;&amp; fragment, IncludeBranch&amp; includeBranch)
+            : m_fragment(fragment)
+            , m_includeBranch(includeBranch)
+        {
+        }
+
+        template&lt;class... Args&gt;
+        void appendInstruction(OpcodeID opcodeID, Args... args)
+        {
+            if (isBranch(opcodeID))
+                m_includeBranch = IncludeBranch::Yes;
+
+            UnlinkedInstruction instructions[sizeof...(args) + 1] = {
+                UnlinkedInstruction(opcodeID),
+                UnlinkedInstruction(args)...
+            };
+            m_fragment.append(instructions, sizeof...(args) + 1);
+        }
+
+    private:
+        Vector&lt;UnlinkedInstruction&gt;&amp; m_fragment;
+        IncludeBranch&amp; m_includeBranch;
+    };
+
+    BytecodeRewriter(BytecodeGraph&lt;UnlinkedCodeBlock&gt;&amp; graph)
+        : m_graph(graph)
+    {
+    }
+
+    template&lt;class Function&gt;
+    void insertFragmentBefore(unsigned bytecodeOffset, Function function)
+    {
+        IncludeBranch includeBranch = IncludeBranch::No;
+        Vector&lt;UnlinkedInstruction&gt; instructions;
+        Fragment fragment(instructions, includeBranch);
+        function(fragment);
+        insertImpl(InsertionPoint(bytecodeOffset, Position::Before), includeBranch, WTFMove(instructions));
+    }
+
+    template&lt;class Function&gt;
+    void insertFragmentAfter(unsigned bytecodeOffset, Function function)
+    {
+        IncludeBranch includeBranch = IncludeBranch::No;
+        Vector&lt;UnlinkedInstruction&gt; instructions;
+        Fragment fragment(instructions, includeBranch);
+        function(fragment);
+        insertImpl(InsertionPoint(bytecodeOffset, Position::After), includeBranch, WTFMove(instructions));
+    }
+
+    void removeBytecode(unsigned bytecodeOffset)
+    {
+        m_insertions.append(Insertion { InsertionPoint(bytecodeOffset, Position::OriginalBytecodePoint), Insertion::Type::Remove, IncludeBranch::No, opcodeLength(m_graph.instructions()[bytecodeOffset].u.opcode), { } });
+    }
+
+    void execute();
+
+    BytecodeGraph&lt;UnlinkedCodeBlock&gt;&amp; graph() { return m_graph; }
+
+    int adjustAbsoluteOffset(int absoluteOffset)
+    {
+        return adjustJumpTarget(InsertionPoint(0, Position::EntryPoint), InsertionPoint(absoluteOffset, Position::LabelPoint));
+    }
+
+    int adjustJumpTarget(int originalBytecodeOffset, int originalJumpTarget)
+    {
+        return adjustJumpTarget(InsertionPoint(originalBytecodeOffset, Position::LabelPoint), InsertionPoint(originalJumpTarget, Position::LabelPoint));
+    }
+
+private:
+    void insertImpl(InsertionPoint, IncludeBranch, Vector&lt;UnlinkedInstruction&gt;&amp;&amp; fragment);
+
+    friend class UnlinkedCodeBlock;
+    void applyModification();
+    void adjustJumpTargetsInFragment(unsigned finalOffset, Insertion&amp;);
+
+    int adjustJumpTarget(InsertionPoint startPoint, InsertionPoint jumpTargetPoint);
+    template&lt;typename Iterator&gt; int calculateDifference(Iterator begin, Iterator end);
+
+    BytecodeGraph&lt;UnlinkedCodeBlock&gt;&amp; m_graph;
+    Vector&lt;Insertion, 8&gt; m_insertions;
+};
+
+template&lt;typename Iterator&gt;
+inline int BytecodeRewriter::calculateDifference(Iterator begin, Iterator end)
+{
+    int result = 0;
+    for (; begin != end; ++begin) {
+        if (begin-&gt;type == Insertion::Type::Remove)
+            result -= begin-&gt;length();
+        else
+            result += begin-&gt;length();
+    }
+    return result;
+}
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -30,15 +30,9 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-template&lt;typename Functor&gt;
-void computeUsesForBytecodeOffset(
-    CodeBlock* codeBlock, BytecodeBasicBlock* block, unsigned bytecodeOffset, const Functor&amp; functor)
</del><ins>+template&lt;typename Block, typename Functor, typename Instruction&gt;
+void computeUsesForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, Instruction* instruction, const Functor&amp; functor)
</ins><span class="cx"> {
</span><del>-    Interpreter* interpreter = codeBlock-&gt;vm()-&gt;interpreter;
-    Instruction* instructionsBegin = codeBlock-&gt;instructions().begin();
-    Instruction* instruction = &amp;instructionsBegin[bytecodeOffset];
-    OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instruction-&gt;u.opcode);
-
</del><span class="cx">     if (opcodeID != op_enter &amp;&amp; codeBlock-&gt;wasCompiledWithDebuggingOpcodes() &amp;&amp; codeBlock-&gt;scopeRegister().isValid())
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, codeBlock-&gt;scopeRegister().offset());
</span><span class="cx"> 
</span><span class="lines">@@ -75,8 +69,7 @@
</span><span class="cx">     case op_jneq_null:
</span><span class="cx">     case op_dec:
</span><span class="cx">     case op_inc:
</span><del>-    case op_log_shadow_chicken_prologue:
-    case op_resume: {
</del><ins>+    case op_log_shadow_chicken_prologue: {
</ins><span class="cx">         ASSERT(opcodeLengths[opcodeID] &gt; 1);
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
</span><span class="cx">         return;
</span><span class="lines">@@ -287,20 +280,9 @@
</span><span class="cx">             functor(codeBlock, instruction, opcodeID, codeBlock-&gt;scopeRegister().offset());
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-    case op_save: {
</del><ins>+    case op_yield: {
</ins><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
</span><del>-        unsigned mergePointBytecodeOffset = bytecodeOffset + instruction[3].u.operand;
-        BytecodeBasicBlock* mergePointBlock = nullptr;
-        for (BytecodeBasicBlock* successor : block-&gt;successors()) {
-            if (successor-&gt;leaderBytecodeOffset() == mergePointBytecodeOffset) {
-                mergePointBlock = successor;
-                break;
-            }
-        }
-        ASSERT(mergePointBlock);
-        mergePointBlock-&gt;in().forEachSetBit([&amp;](unsigned local) {
-            functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(local).offset());
-        });
</del><ins>+        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     default:
</span><span class="lines">@@ -309,13 +291,9 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename Functor&gt;
-void computeDefsForBytecodeOffset(CodeBlock* codeBlock, BytecodeBasicBlock* block, unsigned bytecodeOffset, const Functor&amp; functor)
</del><ins>+template&lt;typename Block, typename Instruction, typename Functor&gt;
+void computeDefsForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, Instruction* instruction, const Functor&amp; functor)
</ins><span class="cx"> {
</span><del>-    Interpreter* interpreter = codeBlock-&gt;vm()-&gt;interpreter;
-    Instruction* instructionsBegin = codeBlock-&gt;instructions().begin();
-    Instruction* instruction = &amp;instructionsBegin[bytecodeOffset];
-    OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instruction-&gt;u.opcode);
</del><span class="cx">     switch (opcodeID) {
</span><span class="cx">     // These don't define anything.
</span><span class="cx">     case op_put_to_scope:
</span><span class="lines">@@ -322,7 +300,6 @@
</span><span class="cx">     case op_end:
</span><span class="cx">     case op_throw:
</span><span class="cx">     case op_throw_static_error:
</span><del>-    case op_save:
</del><span class="cx">     case op_assert:
</span><span class="cx">     case op_debug:
</span><span class="cx">     case op_ret:
</span><span class="lines">@@ -362,6 +339,7 @@
</span><span class="cx">     case op_watchdog:
</span><span class="cx">     case op_log_shadow_chicken_prologue:
</span><span class="cx">     case op_log_shadow_chicken_tail:
</span><ins>+    case op_yield:
</ins><span class="cx"> #define LLINT_HELPER_OPCODES(opcode, length) case opcode:
</span><span class="cx">         FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES);
</span><span class="cx"> #undef LLINT_HELPER_OPCODES
</span><span class="lines">@@ -480,16 +458,7 @@
</span><span class="cx">             functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(i).offset());
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-    case op_resume: {
-        RELEASE_ASSERT(block-&gt;successors().size() == 1);
-        // FIXME: This is really dirty.
-        // https://bugs.webkit.org/show_bug.cgi?id=159281
-        block-&gt;successors()[0]-&gt;in().forEachSetBit([&amp;](unsigned local) {
-            functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(local).offset());
-        });
-        return;
</del><span class="cx">     }
</span><del>-    }
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;ArithProfile.h&quot;
</span><span class="cx"> #include &quot;BasicBlockLocation.h&quot;
</span><span class="cx"> #include &quot;BytecodeGenerator.h&quot;
</span><ins>+#include &quot;BytecodeLivenessAnalysis.h&quot;
</ins><span class="cx"> #include &quot;BytecodeUseDef.h&quot;
</span><span class="cx"> #include &quot;CallLinkStatus.h&quot;
</span><span class="cx"> #include &quot;DFGCapabilities.h&quot;
</span><span class="lines">@@ -696,18 +697,6 @@
</span><span class="cx">         } while (i &lt; m_rareData-&gt;m_stringSwitchJumpTables.size());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_rareData &amp;&amp; !m_rareData-&gt;m_liveCalleeLocalsAtYield.isEmpty()) {
-        out.printf(&quot;\nLive Callee Locals:\n&quot;);
-        unsigned i = 0;
-        do {
-            const FastBitVector&amp; liveness = m_rareData-&gt;m_liveCalleeLocalsAtYield[i];
-            out.printf(&quot;  live%1u = &quot;, i);
-            liveness.dump(out);
-            out.printf(&quot;\n&quot;);
-            ++i;
-        } while (i &lt; m_rareData-&gt;m_liveCalleeLocalsAtYield.size());
-    }
-
</del><span class="cx">     out.printf(&quot;\n&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1672,31 +1661,6 @@
</span><span class="cx">             out.printf(&quot;%s, %d&quot;, debugHookName(debugHookID), hasBreakpointFlag);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><del>-        case op_save: {
-            int generator = (++it)-&gt;u.operand;
-            unsigned liveCalleeLocalsIndex = (++it)-&gt;u.unsignedValue;
-            int offset = (++it)-&gt;u.operand;
-            FastBitVector liveness;
-            if (liveCalleeLocalsIndex &lt; m_rareData-&gt;m_liveCalleeLocalsAtYield.size())
-                liveness = m_rareData-&gt;m_liveCalleeLocalsAtYield[liveCalleeLocalsIndex];
-            printLocationAndOp(out, exec, location, it, &quot;save&quot;);
-            out.printf(&quot;%s, &quot;, registerName(generator).data());
-            liveness.dump(out);
-            out.printf(&quot;(@live%1u), %d(-&gt;%d)&quot;, liveCalleeLocalsIndex, offset, location + offset);
-            break;
-        }
-        case op_resume: {
-            int generator = (++it)-&gt;u.operand;
-            unsigned liveCalleeLocalsIndex = (++it)-&gt;u.unsignedValue;
-            FastBitVector liveness;
-            if (liveCalleeLocalsIndex &lt; m_rareData-&gt;m_liveCalleeLocalsAtYield.size())
-                liveness = m_rareData-&gt;m_liveCalleeLocalsAtYield[liveCalleeLocalsIndex];
-            printLocationAndOp(out, exec, location, it, &quot;resume&quot;);
-            out.printf(&quot;%s, &quot;, registerName(generator).data());
-            liveness.dump(out);
-            out.printf(&quot;(@live%1u)&quot;, liveCalleeLocalsIndex);
-            break;
-        }
</del><span class="cx">         case op_assert: {
</span><span class="cx">             int condition = (++it)-&gt;u.operand;
</span><span class="cx">             int line = (++it)-&gt;u.operand;
</span><span class="lines">@@ -1908,7 +1872,6 @@
</span><span class="cx">         m_rareData-&gt;m_constantBuffers = other.m_rareData-&gt;m_constantBuffers;
</span><span class="cx">         m_rareData-&gt;m_switchJumpTables = other.m_rareData-&gt;m_switchJumpTables;
</span><span class="cx">         m_rareData-&gt;m_stringSwitchJumpTables = other.m_rareData-&gt;m_stringSwitchJumpTables;
</span><del>-        m_rareData-&gt;m_liveCalleeLocalsAtYield = other.m_rareData-&gt;m_liveCalleeLocalsAtYield;
</del><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     heap()-&gt;m_codeBlocks.add(this);
</span><span class="lines">@@ -2030,7 +1993,7 @@
</span><span class="cx">                 UnlinkedStringJumpTable::StringOffsetTable::iterator end = unlinkedCodeBlock-&gt;stringSwitchJumpTable(i).offsetTable.end();
</span><span class="cx">                 for (; ptr != end; ++ptr) {
</span><span class="cx">                     OffsetLocation offset;
</span><del>-                    offset.branchOffset = ptr-&gt;value;
</del><ins>+                    offset.branchOffset = ptr-&gt;value.branchOffset;
</ins><span class="cx">                     m_rareData-&gt;m_stringSwitchJumpTables[i].offsetTable.add(ptr-&gt;key, offset);
</span><span class="cx">                 }
</span><span class="cx">             }
</span><span class="lines">@@ -2070,11 +2033,17 @@
</span><span class="cx">     // Bookkeep the strongly referenced module environments.
</span><span class="cx">     HashSet&lt;JSModuleEnvironment*&gt; stronglyReferencedModuleEnvironments;
</span><span class="cx"> 
</span><del>-    // Bookkeep the merge point bytecode offsets.
-    Vector&lt;size_t&gt; mergePointBytecodeOffsets;
-
</del><span class="cx">     RefCountedArray&lt;Instruction&gt; instructions(instructionCount);
</span><span class="cx"> 
</span><ins>+    unsigned valueProfileCount = 0;
+    auto linkValueProfile = [&amp;](unsigned bytecodeOffset, unsigned opLength) {
+        unsigned valueProfileIndex = valueProfileCount++;
+        ValueProfile* profile = &amp;m_valueProfiles[valueProfileIndex];
+        ASSERT(profile-&gt;m_bytecodeOffset == -1);
+        profile-&gt;m_bytecodeOffset = bytecodeOffset;
+        instructions[bytecodeOffset + opLength - 1] = profile;
+    };
+
</ins><span class="cx">     for (unsigned i = 0; !instructionReader.atEnd(); ) {
</span><span class="cx">         const UnlinkedInstruction* pc = instructionReader.next();
</span><span class="cx"> 
</span><span class="lines">@@ -2110,10 +2079,7 @@
</span><span class="cx">         case op_try_get_by_id:
</span><span class="cx">         case op_get_from_arguments:
</span><span class="cx">         case op_to_number: {
</span><del>-            ValueProfile* profile = &amp;m_valueProfiles[pc[opLength - 1].u.operand];
-            ASSERT(profile-&gt;m_bytecodeOffset == -1);
-            profile-&gt;m_bytecodeOffset = i;
-            instructions[i + opLength - 1] = profile;
</del><ins>+            linkValueProfile(i, opLength);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case op_put_by_val: {
</span><span class="lines">@@ -2150,10 +2116,7 @@
</span><span class="cx">         case op_call:
</span><span class="cx">         case op_tail_call:
</span><span class="cx">         case op_call_eval: {
</span><del>-            ValueProfile* profile = &amp;m_valueProfiles[pc[opLength - 1].u.operand];
-            ASSERT(profile-&gt;m_bytecodeOffset == -1);
-            profile-&gt;m_bytecodeOffset = i;
-            instructions[i + opLength - 1] = profile;
</del><ins>+            linkValueProfile(i, opLength);
</ins><span class="cx">             int arrayProfileIndex = pc[opLength - 2].u.operand;
</span><span class="cx">             m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
</span><span class="cx">             instructions[i + opLength - 2] = &amp;m_arrayProfiles[arrayProfileIndex];
</span><span class="lines">@@ -2162,10 +2125,7 @@
</span><span class="cx">         }
</span><span class="cx">         case op_construct: {
</span><span class="cx">             instructions[i + 5] = &amp;m_llintCallLinkInfos[pc[5].u.operand];
</span><del>-            ValueProfile* profile = &amp;m_valueProfiles[pc[opLength - 1].u.operand];
-            ASSERT(profile-&gt;m_bytecodeOffset == -1);
-            profile-&gt;m_bytecodeOffset = i;
-            instructions[i + opLength - 1] = profile;
</del><ins>+            linkValueProfile(i, opLength);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case op_get_array_length:
</span><span class="lines">@@ -2196,10 +2156,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case op_get_from_scope: {
</span><del>-            ValueProfile* profile = &amp;m_valueProfiles[pc[opLength - 1].u.operand];
-            ASSERT(profile-&gt;m_bytecodeOffset == -1);
-            profile-&gt;m_bytecodeOffset = i;
-            instructions[i + opLength - 1] = profile;
</del><ins>+            linkValueProfile(i, opLength);
</ins><span class="cx"> 
</span><span class="cx">             // get_from_scope dst, scope, id, GetPutInfo, Structure, Operand
</span><span class="cx"> 
</span><span class="lines">@@ -2356,15 +2313,6 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case op_save: {
-            unsigned liveCalleeLocalsIndex = pc[2].u.index;
-            int offset = pc[3].u.operand;
-            if (liveCalleeLocalsIndex &gt;= mergePointBytecodeOffsets.size())
-                mergePointBytecodeOffsets.resize(liveCalleeLocalsIndex + 1);
-            mergePointBytecodeOffsets[liveCalleeLocalsIndex] = i + offset;
-            break;
-        }
-
</del><span class="cx">         default:
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -2376,20 +2324,6 @@
</span><span class="cx"> 
</span><span class="cx">     m_instructions = WTFMove(instructions);
</span><span class="cx"> 
</span><del>-    // Perform bytecode liveness analysis to determine which locals are live and should be resumed when executing op_resume.
-    if (unlinkedCodeBlock-&gt;parseMode() == SourceParseMode::GeneratorBodyMode) {
-        if (size_t count = mergePointBytecodeOffsets.size()) {
-            createRareDataIfNecessary();
-            BytecodeLivenessAnalysis liveness(this);
-            m_rareData-&gt;m_liveCalleeLocalsAtYield.grow(count);
-            size_t liveCalleeLocalsIndex = 0;
-            for (size_t bytecodeOffset : mergePointBytecodeOffsets) {
-                m_rareData-&gt;m_liveCalleeLocalsAtYield[liveCalleeLocalsIndex] = liveness.getLivenessInfoAtBytecodeOffset(bytecodeOffset);
-                ++liveCalleeLocalsIndex;
-            }
-        }
-    }
-
</del><span class="cx">     // Set optimization thresholds only after m_instructions is initialized, since these
</span><span class="cx">     // rely on the instruction count (and are in theory permitted to also inspect the
</span><span class="cx">     // instruction stream to more accurate assess the cost of tier-up).
</span><span class="lines">@@ -3246,21 +3180,7 @@
</span><span class="cx"> {
</span><span class="cx">     if (!m_rareData)
</span><span class="cx">         return 0;
</span><del>-    
-    Vector&lt;HandlerInfo&gt;&amp; exceptionHandlers = m_rareData-&gt;m_exceptionHandlers;
-    for (size_t i = 0; i &lt; exceptionHandlers.size(); ++i) {
-        HandlerInfo&amp; handler = exceptionHandlers[i];
-        if ((requiredHandler == RequiredHandler::CatchHandler) &amp;&amp; !handler.isCatchHandler())
-            continue;
-
-        // Handlers are ordered innermost first, so the first handler we encounter
-        // that contains the source address is the correct handler to use.
-        // This index used is either the BytecodeOffset or a CallSiteIndex.
-        if (handler.start &lt;= index &amp;&amp; handler.end &gt; index)
-            return &amp;handler;
-    }
-
-    return 0;
</del><ins>+    return HandlerInfo::handlerForIndex(m_rareData-&gt;m_exceptionHandlers, index, requiredHandler);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> CallSiteIndex CodeBlock::newExceptionHandlingCallSiteIndex(CallSiteIndex originalCallSite)
</span><span class="lines">@@ -3355,7 +3275,6 @@
</span><span class="cx">         if (m_rareData) {
</span><span class="cx">             m_rareData-&gt;m_switchJumpTables.shrinkToFit();
</span><span class="cx">             m_rareData-&gt;m_stringSwitchJumpTables.shrinkToFit();
</span><del>-            m_rareData-&gt;m_liveCalleeLocalsAtYield.shrinkToFit();
</del><span class="cx">         }
</span><span class="cx">     } // else don't shrink these, because we would have already pointed pointers into these tables.
</span><span class="cx"> }
</span><span class="lines">@@ -4337,14 +4256,9 @@
</span><span class="cx"> 
</span><span class="cx"> ValueProfile* CodeBlock::valueProfileForBytecodeOffset(int bytecodeOffset)
</span><span class="cx"> {
</span><del>-    ValueProfile* result = binarySearch&lt;ValueProfile, int&gt;(
-        m_valueProfiles, m_valueProfiles.size(), bytecodeOffset,
-        getValueProfileBytecodeOffset&lt;ValueProfile&gt;);
-    ASSERT(result-&gt;m_bytecodeOffset != -1);
-    ASSERT(instructions()[bytecodeOffset + opcodeLength(
-        m_vm-&gt;interpreter-&gt;getOpcodeID(
-            instructions()[bytecodeOffset].u.opcode)) - 1].u.profile == result);
-    return result;
</del><ins>+    OpcodeID opcodeID = m_vm-&gt;interpreter-&gt;getOpcodeID(instructions()[bytecodeOffset].u.opcode);
+    unsigned length = opcodeLength(opcodeID);
+    return instructions()[bytecodeOffset + length - 1].u.profile;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CodeBlock::validate()
</span><span class="lines">@@ -4673,4 +4587,16 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+BytecodeLivenessAnalysis&amp; CodeBlock::livenessAnalysisSlow()
+{
+    std::unique_ptr&lt;BytecodeLivenessAnalysis&gt; analysis = std::make_unique&lt;BytecodeLivenessAnalysis&gt;(this);
+    {
+        ConcurrentJITLocker locker(m_lock);
+        if (!m_livenessAnalysis)
+            m_livenessAnalysis = WTFMove(analysis);
+        return *m_livenessAnalysis;
+    }
+}
+
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -33,7 +33,6 @@
</span><span class="cx"> #include &quot;ArrayProfile.h&quot;
</span><span class="cx"> #include &quot;ByValInfo.h&quot;
</span><span class="cx"> #include &quot;BytecodeConventions.h&quot;
</span><del>-#include &quot;BytecodeLivenessAnalysis.h&quot;
</del><span class="cx"> #include &quot;CallLinkInfo.h&quot;
</span><span class="cx"> #include &quot;CallReturnOffsetToBytecodeOffset.h&quot;
</span><span class="cx"> #include &quot;CodeBlockHash.h&quot;
</span><span class="lines">@@ -79,6 +78,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+class BytecodeLivenessAnalysis;
</ins><span class="cx"> class ExecState;
</span><span class="cx"> class JITAddGenerator;
</span><span class="cx"> class JSModuleEnvironment;
</span><span class="lines">@@ -226,10 +226,6 @@
</span><span class="cx">         return index &gt;= m_numVars;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    enum class RequiredHandler {
-        CatchHandler,
-        AnyHandler
-    };
</del><span class="cx">     HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler = RequiredHandler::AnyHandler);
</span><span class="cx">     HandlerInfo* handlerForIndex(unsigned, RequiredHandler = RequiredHandler::AnyHandler);
</span><span class="cx">     void removeExceptionHandlerForCallSite(CallSiteIndex);
</span><span class="lines">@@ -304,6 +300,9 @@
</span><span class="cx">         return static_cast&lt;Instruction*&gt;(returnAddress) - instructions().begin();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    typedef JSC::Instruction Instruction;
+    typedef RefCountedArray&lt;Instruction&gt;&amp; UnpackedInstructions;
+
</ins><span class="cx">     unsigned numberOfInstructions() const { return m_instructions.size(); }
</span><span class="cx">     RefCountedArray&lt;Instruction&gt;&amp; instructions() { return m_instructions; }
</span><span class="cx">     const RefCountedArray&lt;Instruction&gt;&amp; instructions() const { return m_instructions; }
</span><span class="lines">@@ -546,7 +545,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     WriteBarrier&lt;Unknown&gt;&amp; constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; }
</span><del>-    ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index &gt;= FirstConstantRegisterIndex; }
</del><ins>+    static ALWAYS_INLINE bool isConstantRegisterIndex(int index) { return index &gt;= FirstConstantRegisterIndex; }
</ins><span class="cx">     ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].get(); }
</span><span class="cx">     ALWAYS_INLINE SourceCodeRepresentation constantSourceCodeRepresentation(int index) const { return m_constantsSourceCodeRepresentation[index - FirstConstantRegisterIndex]; }
</span><span class="cx"> 
</span><span class="lines">@@ -592,14 +591,7 @@
</span><span class="cx">             if (!!m_livenessAnalysis)
</span><span class="cx">                 return *m_livenessAnalysis;
</span><span class="cx">         }
</span><del>-        std::unique_ptr&lt;BytecodeLivenessAnalysis&gt; analysis =
-            std::make_unique&lt;BytecodeLivenessAnalysis&gt;(this);
-        {
-            ConcurrentJITLocker locker(m_lock);
-            if (!m_livenessAnalysis)
-                m_livenessAnalysis = WTFMove(analysis);
-            return *m_livenessAnalysis;
-        }
</del><ins>+        return livenessAnalysisSlow();
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void validate();
</span><span class="lines">@@ -620,18 +612,6 @@
</span><span class="cx">     StringJumpTable&amp; addStringSwitchJumpTable() { createRareDataIfNecessary(); m_rareData-&gt;m_stringSwitchJumpTables.append(StringJumpTable()); return m_rareData-&gt;m_stringSwitchJumpTables.last(); }
</span><span class="cx">     StringJumpTable&amp; stringSwitchJumpTable(int tableIndex) { RELEASE_ASSERT(m_rareData); return m_rareData-&gt;m_stringSwitchJumpTables[tableIndex]; }
</span><span class="cx"> 
</span><del>-    // Live callee registers at yield points.
-    const FastBitVector&amp; liveCalleeLocalsAtYield(unsigned index) const
-    {
-        RELEASE_ASSERT(m_rareData);
-        return m_rareData-&gt;m_liveCalleeLocalsAtYield[index];
-    }
-    FastBitVector&amp; liveCalleeLocalsAtYield(unsigned index)
-    {
-        RELEASE_ASSERT(m_rareData);
-        return m_rareData-&gt;m_liveCalleeLocalsAtYield[index];
-    }
-
</del><span class="cx">     EvalCodeCache&amp; evalCodeCache() { createRareDataIfNecessary(); return m_rareData-&gt;m_evalCodeCache; }
</span><span class="cx"> 
</span><span class="cx">     enum ShrinkMode {
</span><span class="lines">@@ -886,8 +866,6 @@
</span><span class="cx">         Vector&lt;SimpleJumpTable&gt; m_switchJumpTables;
</span><span class="cx">         Vector&lt;StringJumpTable&gt; m_stringSwitchJumpTables;
</span><span class="cx"> 
</span><del>-        Vector&lt;FastBitVector&gt; m_liveCalleeLocalsAtYield;
-
</del><span class="cx">         EvalCodeCache m_evalCodeCache;
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -922,6 +900,8 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class CodeBlockSet;
</span><ins>+
+    BytecodeLivenessAnalysis&amp; livenessAnalysisSlow();
</ins><span class="cx">     
</span><span class="cx">     CodeBlock* specialOSREntryBlockOrNull();
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeHandlerInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/HandlerInfo.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/HandlerInfo.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/HandlerInfo.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #define HandlerInfo_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CodeLocation.h&quot;
</span><ins>+#include &lt;wtf/Vector.h&gt;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -37,6 +38,11 @@
</span><span class="cx">     SynthesizedFinally = 3
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+enum class RequiredHandler {
+    CatchHandler,
+    AnyHandler
+};
+
</ins><span class="cx"> struct HandlerInfoBase {
</span><span class="cx">     HandlerType type() const { return static_cast&lt;HandlerType&gt;(typeBits); }
</span><span class="cx">     void setType(HandlerType type) { typeBits = static_cast&lt;uint32_t&gt;(type); }
</span><span class="lines">@@ -58,6 +64,23 @@
</span><span class="cx"> 
</span><span class="cx">     bool isCatchHandler() const { return type() == HandlerType::Catch; }
</span><span class="cx"> 
</span><ins>+    template&lt;typename Handler&gt;
+    static Handler* handlerForIndex(Vector&lt;Handler&gt;&amp; exeptionHandlers, unsigned index, RequiredHandler requiredHandler)
+    {
+        for (Handler&amp; handler : exeptionHandlers) {
+            if ((requiredHandler == RequiredHandler::CatchHandler) &amp;&amp; !handler.isCatchHandler())
+                continue;
+
+            // Handlers are ordered innermost first, so the first handler we encounter
+            // that contains the source address is the correct handler to use.
+            // This index used is either the BytecodeOffset or a CallSiteIndex.
+            if (handler.start &lt;= index &amp;&amp; handler.end &gt; index)
+                return &amp;handler;
+        }
+
+        return nullptr;
+    }
+
</ins><span class="cx">     uint32_t start;
</span><span class="cx">     uint32_t end;
</span><span class="cx">     uint32_t target;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeOpcodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/Opcode.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/Opcode.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/Opcode.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -126,6 +126,64 @@
</span><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool isBranch(OpcodeID opcodeID)
+{
+    switch (opcodeID) {
+    case op_jmp:
+    case op_jtrue:
+    case op_jfalse:
+    case op_jeq_null:
+    case op_jneq_null:
+    case op_jneq_ptr:
+    case op_jless:
+    case op_jlesseq:
+    case op_jgreater:
+    case op_jgreatereq:
+    case op_jnless:
+    case op_jnlesseq:
+    case op_jngreater:
+    case op_jngreatereq:
+    case op_switch_imm:
+    case op_switch_char:
+    case op_switch_string:
+        return true;
+    default:
+        return false;
+    }
+}
+
+inline bool isUnconditionalBranch(OpcodeID opcodeID)
+{
+    switch (opcodeID) {
+    case op_jmp:
+        return true;
+    default:
+        return false;
+    }
+}
+
+inline bool isTerminal(OpcodeID opcodeID)
+{
+    switch (opcodeID) {
+    case op_ret:
+    case op_end:
+        return true;
+    default:
+        return false;
+    }
+}
+
+inline bool isThrow(OpcodeID opcodeID)
+{
+    switch (opcodeID) {
+    case op_throw:
+    case op_throw_static_error:
+        return true;
+    default:
+        return false;
+    }
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePreciseJumpTargetscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -26,69 +26,37 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;PreciseJumpTargets.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;InterpreterInlines.h&quot;
</ins><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;PreciseJumpTargetsInlines.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-template &lt;size_t vectorSize&gt;
-static void getJumpTargetsForBytecodeOffset(CodeBlock* codeBlock, Interpreter* interpreter, Instruction* instructionsBegin, unsigned bytecodeOffset, Vector&lt;unsigned, vectorSize&gt;&amp; out)
</del><ins>+template &lt;size_t vectorSize, typename Block, typename Instruction&gt;
+static void getJumpTargetsForBytecodeOffset(Block* codeBlock, Interpreter* interpreter, Instruction* instructionsBegin, unsigned bytecodeOffset, Vector&lt;unsigned, vectorSize&gt;&amp; out)
</ins><span class="cx"> {
</span><del>-    OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode);
-    Instruction* current = instructionsBegin + bytecodeOffset;
-    switch (opcodeID) {
-    case op_jmp:
-        out.append(bytecodeOffset + current[1].u.operand);
-        break;
-    case op_jtrue:
-    case op_jfalse:
-    case op_jeq_null:
-    case op_jneq_null:
-        out.append(bytecodeOffset + current[2].u.operand);
-        break;
-    case op_jneq_ptr:
-    case op_jless:
-    case op_jlesseq:
-    case op_jgreater:
-    case op_jgreatereq:
-    case op_jnless:
-    case op_jnlesseq:
-    case op_jngreater:
-    case op_jngreatereq:
-    case op_save: // The jump of op_save is purely for calculating liveness.
-        out.append(bytecodeOffset + current[3].u.operand);
-        break;
-    case op_switch_imm:
-    case op_switch_char: {
-        SimpleJumpTable&amp; table = codeBlock-&gt;switchJumpTable(current[1].u.operand);
-        for (unsigned i = table.branchOffsets.size(); i--;)
-            out.append(bytecodeOffset + table.branchOffsets[i]);
-        out.append(bytecodeOffset + current[2].u.operand);
-        break;
-    }
-    case op_switch_string: {
-        StringJumpTable&amp; table = codeBlock-&gt;stringSwitchJumpTable(current[1].u.operand);
-        StringJumpTable::StringOffsetTable::iterator iter = table.offsetTable.begin();
-        StringJumpTable::StringOffsetTable::iterator end = table.offsetTable.end();
-        for (; iter != end; ++iter)
-            out.append(bytecodeOffset + iter-&gt;value.branchOffset);
-        out.append(bytecodeOffset + current[2].u.operand);
-        break;
-    }
-    case op_loop_hint:
</del><ins>+    OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instructionsBegin[bytecodeOffset]);
+    extractStoredJumpTargetsForBytecodeOffset(codeBlock, interpreter, instructionsBegin, bytecodeOffset, [&amp;](int32_t&amp; relativeOffset) {
+        out.append(bytecodeOffset + relativeOffset);
+    });
+    // op_loop_hint does not have jump target stored in bytecode instructions.
+    if (opcodeID == op_loop_hint)
</ins><span class="cx">         out.append(bytecodeOffset);
</span><del>-        break;
-    default:
-        break;
-    }
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-void computePreciseJumpTargets(CodeBlock* codeBlock, Vector&lt;unsigned, 32&gt;&amp; out)
</del><ins>+enum class ComputePreciseJumpTargetsMode {
+    FollowCodeBlockClaim,
+    ForceCompute,
+};
+
+template&lt;ComputePreciseJumpTargetsMode Mode, typename Block, typename Instruction, size_t vectorSize&gt;
+void computePreciseJumpTargetsInternal(Block* codeBlock, Instruction* instructionsBegin, unsigned instructionCount, Vector&lt;unsigned, vectorSize&gt;&amp; out)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(out.isEmpty());
</span><span class="cx">     
</span><span class="cx">     // We will derive a superset of the jump targets that the code block thinks it has.
</span><span class="cx">     // So, if the code block claims there are none, then we are done.
</span><del>-    if (!codeBlock-&gt;numberOfJumpTargets())
</del><ins>+    if (Mode == ComputePreciseJumpTargetsMode::FollowCodeBlockClaim &amp;&amp; !codeBlock-&gt;numberOfJumpTargets())
</ins><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     for (unsigned i = codeBlock-&gt;numberOfExceptionHandlers(); i--;) {
</span><span class="lines">@@ -98,10 +66,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Interpreter* interpreter = codeBlock-&gt;vm()-&gt;interpreter;
</span><del>-    Instruction* instructionsBegin = codeBlock-&gt;instructions().begin();
-    unsigned instructionCount = codeBlock-&gt;instructions().size();
</del><span class="cx">     for (unsigned bytecodeOffset = 0; bytecodeOffset &lt; instructionCount;) {
</span><del>-        OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode);
</del><ins>+        OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instructionsBegin[bytecodeOffset]);
</ins><span class="cx">         getJumpTargetsForBytecodeOffset(codeBlock, interpreter, instructionsBegin, bytecodeOffset, out);
</span><span class="cx">         bytecodeOffset += opcodeLengths[opcodeID];
</span><span class="cx">     }
</span><span class="lines">@@ -123,12 +89,35 @@
</span><span class="cx">     out.shrinkToFit();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void findJumpTargetsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset, Vector&lt;unsigned, 1&gt;&amp; out)
</del><ins>+void computePreciseJumpTargets(CodeBlock* codeBlock, Vector&lt;unsigned, 32&gt;&amp; out)
</ins><span class="cx"> {
</span><del>-    Interpreter* interpreter = codeBlock-&gt;vm()-&gt;interpreter;
-    Instruction* instructionsBegin = codeBlock-&gt;instructions().begin();
-    getJumpTargetsForBytecodeOffset(codeBlock, interpreter, instructionsBegin, bytecodeOffset, out);
</del><ins>+    computePreciseJumpTargetsInternal&lt;ComputePreciseJumpTargetsMode::FollowCodeBlockClaim&gt;(codeBlock, codeBlock-&gt;instructions().begin(), codeBlock-&gt;instructions().size(), out);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void computePreciseJumpTargets(CodeBlock* codeBlock, Instruction* instructionsBegin, unsigned instructionCount, Vector&lt;unsigned, 32&gt;&amp; out)
+{
+    computePreciseJumpTargetsInternal&lt;ComputePreciseJumpTargetsMode::FollowCodeBlockClaim&gt;(codeBlock, instructionsBegin, instructionCount, out);
+}
+
+void computePreciseJumpTargets(UnlinkedCodeBlock* codeBlock, UnlinkedInstruction* instructionsBegin, unsigned instructionCount, Vector&lt;unsigned, 32&gt;&amp; out)
+{
+    computePreciseJumpTargetsInternal&lt;ComputePreciseJumpTargetsMode::FollowCodeBlockClaim&gt;(codeBlock, instructionsBegin, instructionCount, out);
+}
+
+void recomputePreciseJumpTargets(UnlinkedCodeBlock* codeBlock, UnlinkedInstruction* instructionsBegin, unsigned instructionCount, Vector&lt;unsigned&gt;&amp; out)
+{
+    computePreciseJumpTargetsInternal&lt;ComputePreciseJumpTargetsMode::ForceCompute&gt;(codeBlock, instructionsBegin, instructionCount, out);
+}
+
+void findJumpTargetsForBytecodeOffset(CodeBlock* codeBlock, Instruction* instructionsBegin, unsigned bytecodeOffset, Vector&lt;unsigned, 1&gt;&amp; out)
+{
+    getJumpTargetsForBytecodeOffset(codeBlock, codeBlock-&gt;vm()-&gt;interpreter, instructionsBegin, bytecodeOffset, out);
+}
+
+void findJumpTargetsForBytecodeOffset(UnlinkedCodeBlock* codeBlock, UnlinkedInstruction* instructionsBegin, unsigned bytecodeOffset, Vector&lt;unsigned, 1&gt;&amp; out)
+{
+    getJumpTargetsForBytecodeOffset(codeBlock, codeBlock-&gt;vm()-&gt;interpreter, instructionsBegin, bytecodeOffset, out);
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePreciseJumpTargetsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -23,19 +23,23 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef PreciseJumpTargets_h
-#define PreciseJumpTargets_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+class UnlinkedCodeBlock;
+struct UnlinkedInstruction;
+
</ins><span class="cx"> // Return a sorted list of bytecode index that are the destination of a jump.
</span><span class="cx"> void computePreciseJumpTargets(CodeBlock*, Vector&lt;unsigned, 32&gt;&amp; out);
</span><ins>+void computePreciseJumpTargets(CodeBlock*, Instruction* instructionsBegin, unsigned instructionCount, Vector&lt;unsigned, 32&gt;&amp; out);
+void computePreciseJumpTargets(UnlinkedCodeBlock*, UnlinkedInstruction* instructionsBegin, unsigned instructionCount, Vector&lt;unsigned, 32&gt;&amp; out);
</ins><span class="cx"> 
</span><del>-void findJumpTargetsForBytecodeOffset(CodeBlock*, unsigned bytecodeOffset, Vector&lt;unsigned, 1&gt;&amp; out);
</del><ins>+void recomputePreciseJumpTargets(UnlinkedCodeBlock*, UnlinkedInstruction* instructionsBegin, unsigned instructionCount, Vector&lt;unsigned&gt;&amp; out);
</ins><span class="cx"> 
</span><ins>+void findJumpTargetsForBytecodeOffset(CodeBlock*, Instruction* instructionsBegin, unsigned bytecodeOffset, Vector&lt;unsigned, 1&gt;&amp; out);
+void findJumpTargetsForBytecodeOffset(UnlinkedCodeBlock*, UnlinkedInstruction* instructionsBegin, unsigned bytecodeOffset, Vector&lt;unsigned, 1&gt;&amp; out);
+
</ins><span class="cx"> } // namespace JSC
</span><del>-
-#endif // PreciseJumpTargets_h
-
</del></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePreciseJumpTargetsInlinesh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargetsInlines.h (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargetsInlines.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargetsInlines.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &quot;InterpreterInlines.h&quot;
+#include &quot;Opcode.h&quot;
+#include &quot;PreciseJumpTargets.h&quot;
+
+namespace JSC {
+
+template&lt;typename Block, typename Instruction, typename Function&gt;
+inline void extractStoredJumpTargetsForBytecodeOffset(Block* codeBlock, Interpreter* interpreter, Instruction* instructionsBegin, unsigned bytecodeOffset, Function function)
+{
+    OpcodeID opcodeID = interpreter-&gt;getOpcodeID(instructionsBegin[bytecodeOffset]);
+    Instruction* current = instructionsBegin + bytecodeOffset;
+    switch (opcodeID) {
+    case op_jmp:
+        function(current[1].u.operand);
+        break;
+    case op_jtrue:
+    case op_jfalse:
+    case op_jeq_null:
+    case op_jneq_null:
+        function(current[2].u.operand);
+        break;
+    case op_jneq_ptr:
+    case op_jless:
+    case op_jlesseq:
+    case op_jgreater:
+    case op_jgreatereq:
+    case op_jnless:
+    case op_jnlesseq:
+    case op_jngreater:
+    case op_jngreatereq:
+        function(current[3].u.operand);
+        break;
+    case op_switch_imm:
+    case op_switch_char: {
+        auto&amp; table = codeBlock-&gt;switchJumpTable(current[1].u.operand);
+        for (unsigned i = table.branchOffsets.size(); i--;)
+            function(table.branchOffsets[i]);
+        function(current[2].u.operand);
+        break;
+    }
+    case op_switch_string: {
+        auto&amp; table = codeBlock-&gt;stringSwitchJumpTable(current[1].u.operand);
+        auto iter = table.offsetTable.begin();
+        auto end = table.offsetTable.end();
+        for (; iter != end; ++iter)
+            function(iter-&gt;value.branchOffset);
+        function(current[2].u.operand);
+        break;
+    }
+    default:
+        break;
+    }
+}
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #include &quot;UnlinkedCodeBlock.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;BytecodeGenerator.h&quot;
</span><ins>+#include &quot;BytecodeRewriter.h&quot;
</ins><span class="cx"> #include &quot;ClassInfo.h&quot;
</span><span class="cx"> #include &quot;CodeCache.h&quot;
</span><span class="cx"> #include &quot;Executable.h&quot;
</span><span class="lines">@@ -36,6 +37,7 @@
</span><span class="cx"> #include &quot;JSString.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;Parser.h&quot;
</span><ins>+#include &quot;PreciseJumpTargetsInlines.h&quot;
</ins><span class="cx"> #include &quot;SourceProvider.h&quot;
</span><span class="cx"> #include &quot;Structure.h&quot;
</span><span class="cx"> #include &quot;SymbolTable.h&quot;
</span><span class="lines">@@ -367,5 +369,67 @@
</span><span class="cx">     return *m_unlinkedInstructions;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+UnlinkedHandlerInfo* UnlinkedCodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler requiredHandler)
+{
+    return handlerForIndex(bytecodeOffset, requiredHandler);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+UnlinkedHandlerInfo* UnlinkedCodeBlock::handlerForIndex(unsigned index, RequiredHandler requiredHandler)
+{
+    if (!m_rareData)
+        return nullptr;
+    return UnlinkedHandlerInfo::handlerForIndex(m_rareData-&gt;m_exceptionHandlers, index, requiredHandler);
+}
+
+void UnlinkedCodeBlock::applyModification(BytecodeRewriter&amp; rewriter)
+{
+    // 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&lt;UnlinkedCodeBlock&gt;&amp; graph = rewriter.graph();
+    UnlinkedInstruction* instructionsBegin = graph.instructions().begin();
+
+    for (int bytecodeOffset = 0, instructionCount = graph.instructions().size(); bytecodeOffset &lt; instructionCount;) {
+        UnlinkedInstruction* current = instructionsBegin + bytecodeOffset;
+        OpcodeID opcodeID = current[0].u.opcode;
+        extractStoredJumpTargetsForBytecodeOffset(this, vm()-&gt;interpreter, instructionsBegin, bytecodeOffset, [&amp;](int32_t&amp; relativeOffset) {
+            relativeOffset = rewriter.adjustJumpTarget(bytecodeOffset, bytecodeOffset + relativeOffset);
+        });
+        bytecodeOffset += opcodeLength(opcodeID);
+    }
+
+    // Then, exception handlers should be adjusted.
+    if (m_rareData) {
+        for (UnlinkedHandlerInfo&amp; handler : m_rareData-&gt;m_exceptionHandlers) {
+            handler.target = rewriter.adjustAbsoluteOffset(handler.target);
+            handler.start = rewriter.adjustAbsoluteOffset(handler.start);
+            handler.end = rewriter.adjustAbsoluteOffset(handler.end);
+        }
+
+        for (size_t i = 0; i &lt; m_rareData-&gt;m_opProfileControlFlowBytecodeOffsets.size(); ++i)
+            m_rareData-&gt;m_opProfileControlFlowBytecodeOffsets[i] = rewriter.adjustAbsoluteOffset(m_rareData-&gt;m_opProfileControlFlowBytecodeOffsets[i]);
+
+        if (!m_rareData-&gt;m_typeProfilerInfoMap.isEmpty()) {
+            HashMap&lt;unsigned, RareData::TypeProfilerExpressionRange&gt; adjustedTypeProfilerInfoMap;
+            for (auto&amp; entry : m_rareData-&gt;m_typeProfilerInfoMap)
+                adjustedTypeProfilerInfoMap.set(rewriter.adjustAbsoluteOffset(entry.key), entry.value);
+            m_rareData-&gt;m_typeProfilerInfoMap.swap(adjustedTypeProfilerInfoMap);
+        }
+    }
+
+    for (size_t i = 0; i &lt; m_propertyAccessInstructions.size(); ++i)
+        m_propertyAccessInstructions[i] = rewriter.adjustAbsoluteOffset(m_propertyAccessInstructions[i]);
+
+    for (size_t i = 0; i &lt; m_expressionInfo.size(); ++i)
+        m_expressionInfo[i].instructionOffset = rewriter.adjustAbsoluteOffset(m_expressionInfo[i].instructionOffset);
+
+    // Then, modify the unlinked instructions.
+    rewriter.applyModification();
+
+    // And recompute the jump target based on the modified unlinked instructions.
+    m_jumpTargets.clear();
+    recomputePreciseJumpTargets(this, graph.instructions().begin(), graph.instructions().size(), m_jumpTargets);
+}
+
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -45,6 +45,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+class BytecodeRewriter;
+class Debugger;
</ins><span class="cx"> class FunctionMetadataNode;
</span><span class="cx"> class FunctionExecutable;
</span><span class="cx"> class JSScope;
</span><span class="lines">@@ -65,7 +67,11 @@
</span><span class="cx"> typedef unsigned UnlinkedLLIntCallLinkInfo;
</span><span class="cx"> 
</span><span class="cx"> struct UnlinkedStringJumpTable {
</span><del>-    typedef HashMap&lt;RefPtr&lt;StringImpl&gt;, int32_t&gt; StringOffsetTable;
</del><ins>+    struct OffsetLocation {
+        int32_t branchOffset;
+    };
+
+    typedef HashMap&lt;RefPtr&lt;StringImpl&gt;, OffsetLocation&gt; StringOffsetTable;
</ins><span class="cx">     StringOffsetTable offsetTable;
</span><span class="cx"> 
</span><span class="cx">     inline int32_t offsetForValue(StringImpl* value, int32_t defaultOffset)
</span><span class="lines">@@ -74,7 +80,7 @@
</span><span class="cx">         StringOffsetTable::const_iterator loc = offsetTable.find(value);
</span><span class="cx">         if (loc == end)
</span><span class="cx">             return defaultOffset;
</span><del>-        return loc-&gt;value;
</del><ins>+        return loc-&gt;value.branchOffset;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> };
</span><span class="lines">@@ -102,6 +108,8 @@
</span><span class="cx">     } u;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class BytecodeGeneratorification;
+
</ins><span class="cx"> class UnlinkedCodeBlock : public JSCell {
</span><span class="cx"> public:
</span><span class="cx">     typedef JSCell Base;
</span><span class="lines">@@ -111,6 +119,9 @@
</span><span class="cx"> 
</span><span class="cx">     enum { CallFunction, ApplyFunction };
</span><span class="cx"> 
</span><ins>+    typedef UnlinkedInstruction Instruction;
+    typedef Vector&lt;UnlinkedInstruction, 0, UnsafeVectorOverflow&gt; UnpackedInstructions;
+
</ins><span class="cx">     bool isConstructor() const { return m_isConstructor; }
</span><span class="cx">     bool isStrictMode() const { return m_isStrictMode; }
</span><span class="cx">     bool usesEval() const { return m_usesEval; }
</span><span class="lines">@@ -200,6 +211,9 @@
</span><span class="cx">     unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
</span><span class="cx">     unsigned lastJumpTarget() const { return m_jumpTargets.last(); }
</span><span class="cx"> 
</span><ins>+    UnlinkedHandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset, RequiredHandler = RequiredHandler::AnyHandler);
+    UnlinkedHandlerInfo* handlerForIndex(unsigned, RequiredHandler = RequiredHandler::AnyHandler);
+
</ins><span class="cx">     bool isBuiltinFunction() const { return m_isBuiltinFunction; }
</span><span class="cx"> 
</span><span class="cx">     ConstructorKind constructorKind() const { return static_cast&lt;ConstructorKind&gt;(m_constructorKind); }
</span><span class="lines">@@ -230,6 +244,8 @@
</span><span class="cx">     void setInstructions(std::unique_ptr&lt;UnlinkedInstructionStream&gt;);
</span><span class="cx">     const UnlinkedInstructionStream&amp; instructions() const;
</span><span class="cx"> 
</span><ins>+    int numCalleeLocals() const { return m_numCalleeLocals; }
+
</ins><span class="cx">     int m_numVars;
</span><span class="cx">     int m_numCapturedVars;
</span><span class="cx">     int m_numCalleeLocals;
</span><span class="lines">@@ -381,6 +397,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><ins>+    friend class BytecodeRewriter;
+    void applyModification(BytecodeRewriter&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void createRareDataIfNecessary()
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeVirtualRegisterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/VirtualRegister.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/VirtualRegister.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecode/VirtualRegister.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -26,8 +26,8 @@
</span><span class="cx"> #ifndef VirtualRegister_h
</span><span class="cx"> #define VirtualRegister_h
</span><span class="cx"> 
</span><ins>+#include &quot;BytecodeConventions.h&quot;
</ins><span class="cx"> #include &quot;CallFrame.h&quot;
</span><del>-
</del><span class="cx"> #include &lt;wtf/PrintStream.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -103,7 +103,7 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     static const int s_invalidVirtualRegister = 0x3fffffff;
</span><del>-    static const int s_firstConstantRegisterIndex = 0x40000000;
</del><ins>+    static const int s_firstConstantRegisterIndex = FirstConstantRegisterIndex;
</ins><span class="cx"> 
</span><span class="cx">     static int localToOperand(int local) { return -1 - local; }
</span><span class="cx">     static int operandToLocal(int operand) { return -1 - operand; }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ArithProfile.h&quot;
</span><span class="cx"> #include &quot;BuiltinExecutables.h&quot;
</span><ins>+#include &quot;BytecodeGeneratorification.h&quot;
</ins><span class="cx"> #include &quot;BytecodeLivenessAnalysis.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="lines">@@ -155,6 +156,10 @@
</span><span class="cx">         m_codeBlock-&gt;addExceptionHandler(info);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+
+    if (m_codeBlock-&gt;parseMode() == SourceParseMode::GeneratorBodyMode)
+        performGeneratorification(m_codeBlock.get(), m_instructions, m_generatorFrameSymbolTable.get(), m_generatorFrameSymbolTableIndex);
+
</ins><span class="cx">     m_codeBlock-&gt;setInstructions(std::make_unique&lt;UnlinkedInstructionStream&gt;(m_instructions));
</span><span class="cx"> 
</span><span class="cx">     m_codeBlock-&gt;shrinkToFit();
</span><span class="lines">@@ -262,10 +267,14 @@
</span><span class="cx">     bool shouldCaptureAllOfTheThings = m_shouldEmitDebugHooks || codeBlock-&gt;usesEval();
</span><span class="cx">     bool needsArguments = (functionNode-&gt;usesArguments() || codeBlock-&gt;usesEval() || (functionNode-&gt;usesArrowFunction() &amp;&amp; !codeBlock-&gt;isArrowFunction() &amp;&amp; isArgumentsUsedInInnerArrowFunction()));
</span><span class="cx"> 
</span><del>-    // Generator never provides &quot;arguments&quot;. &quot;arguments&quot; reference will be resolved in an upper generator function scope.
-    if (parseMode == SourceParseMode::GeneratorBodyMode)
</del><ins>+    if (parseMode == SourceParseMode::GeneratorBodyMode) {
+        // Generator never provides &quot;arguments&quot;. &quot;arguments&quot; reference will be resolved in an upper generator function scope.
</ins><span class="cx">         needsArguments = false;
</span><span class="cx"> 
</span><ins>+        // Generator uses the var scope to save and resume its variables. So the lexical scope is always instantiated.
+        shouldCaptureSomeOfTheThings = true;
+    }
+
</ins><span class="cx">     if (parseMode == SourceParseMode::GeneratorWrapperFunctionMode &amp;&amp; needsArguments) {
</span><span class="cx">         // Generator does not provide &quot;arguments&quot;. Instead, wrapping GeneratorFunction provides &quot;arguments&quot;.
</span><span class="cx">         // This is because arguments of a generator should be evaluated before starting it.
</span><span class="lines">@@ -274,7 +283,7 @@
</span><span class="cx">         //    function *gen(a, b = hello())
</span><span class="cx">         //    {
</span><span class="cx">         //        return {
</span><del>-        //            @generatorNext: function (@generator, @generatorState, @generatorValue, @generatorResumeMode)
</del><ins>+        //            @generatorNext: function (@generator, @generatorState, @generatorValue, @generatorResumeMode, @generatorFrame)
</ins><span class="cx">         //            {
</span><span class="cx">         //                arguments;  // This `arguments` should reference to the gen's arguments.
</span><span class="cx">         //                ...
</span><span class="lines">@@ -303,29 +312,18 @@
</span><span class="cx">         return captures(uid) ? VarKind::Scope : VarKind::Stack;
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    emitEnter();
-
-    allocateAndEmitScope();
-
</del><span class="cx">     m_calleeRegister.setIndex(CallFrameSlot::callee);
</span><span class="cx"> 
</span><span class="cx">     initializeParameters(parameters);
</span><span class="cx">     ASSERT(!(isSimpleParameterList &amp;&amp; m_restParameter));
</span><span class="cx"> 
</span><del>-    // Before emitting a scope creation, emit a generator prologue that contains jump based on a generator's state.
-    if (parseMode == SourceParseMode::GeneratorBodyMode) {
</del><ins>+    emitEnter();
+
+    if (parseMode == SourceParseMode::GeneratorBodyMode)
</ins><span class="cx">         m_generatorRegister = &amp;m_parameters[1];
</span><span class="cx"> 
</span><del>-        // Jump with switch_imm based on @generatorState. We don't take the coroutine styled generator implementation.
-        // When calling `next()`, we would like to enter the same prologue instead of jumping based on the saved instruction pointer.
-        // It's suitale for inlining, because it just inlines one `next` function implementation.
</del><ins>+    allocateAndEmitScope();
</ins><span class="cx"> 
</span><del>-        beginGenerator(generatorStateRegister());
-
-        // Initial state.
-        emitGeneratorStateLabel();
-    }
-
</del><span class="cx">     if (functionNameIsInScope(functionNode-&gt;ident(), functionNode-&gt;functionMode())) {
</span><span class="cx">         ASSERT(parseMode != SourceParseMode::GeneratorBodyMode);
</span><span class="cx">         bool isDynamicScope = functionNameScopeIsDynamic(codeBlock-&gt;usesEval(), codeBlock-&gt;isStrictMode());
</span><span class="lines">@@ -641,6 +639,16 @@
</span><span class="cx">             emitLoadNewTargetFromArrowFunctionLexicalEnvironment();
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    // Set up the lexical environment scope as the generator frame. We store the saved and resumed generator registers into this scope with the symbol keys.
+    // Since they are symbol keyed, these variables cannot be reached from the usual code.
+    if (SourceParseMode::GeneratorBodyMode == parseMode) {
+        ASSERT(m_lexicalEnvironmentRegister);
+        m_generatorFrameSymbolTable.set(*m_vm, functionSymbolTable);
+        m_generatorFrameSymbolTableIndex = symbolTableConstantIndex;
+        emitMove(generatorFrameRegister(), m_lexicalEnvironmentRegister);
+        emitPutById(generatorRegister(), propertyNames().builtinNames().generatorFramePrivateName(), generatorFrameRegister());
+    }
+
</ins><span class="cx">     bool shouldInitializeBlockScopedFunctions = false; // We generate top-level function declarations in ::generate().
</span><span class="cx">     pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
</span><span class="cx"> }
</span><span class="lines">@@ -3673,8 +3681,7 @@
</span><span class="cx">             if (flipTries) {
</span><span class="cx">                 while (m_tryContextStack.size() != finallyContext.tryContextStackSize) {
</span><span class="cx">                     ASSERT(m_tryContextStack.size() &gt; finallyContext.tryContextStackSize);
</span><del>-                    TryContext context = m_tryContextStack.last();
-                    m_tryContextStack.removeLast();
</del><ins>+                    TryContext context = m_tryContextStack.takeLast();
</ins><span class="cx">                     TryRange range;
</span><span class="cx">                     range.start = context.start;
</span><span class="cx">                     range.end = beforeFinally;
</span><span class="lines">@@ -3958,7 +3965,7 @@
</span><span class="cx">         
</span><span class="cx">         ASSERT(nodes[i]-&gt;isString());
</span><span class="cx">         StringImpl* clause = static_cast&lt;StringNode*&gt;(nodes[i])-&gt;value().impl();
</span><del>-        jumpTable.offsetTable.add(clause, labels[i]-&gt;bind(switchAddress, switchAddress + 3));
</del><ins>+        jumpTable.offsetTable.add(clause, UnlinkedStringJumpTable::OffsetLocation { labels[i]-&gt;bind(switchAddress, switchAddress + 3) });
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -4460,31 +4467,33 @@
</span><span class="cx"> void BytecodeGenerator::emitYieldPoint(RegisterID* argument)
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;Label&gt; mergePoint = newLabel();
</span><del>-    size_t yieldPointIndex = m_generatorResumeLabels.size();
-    emitGeneratorStateChange(yieldPointIndex);
-    // First yield point is used for initial sequence.
-    unsigned liveCalleeLocalsIndex = yieldPointIndex - 1;
-    emitSave(mergePoint.get(), liveCalleeLocalsIndex);
-    emitReturn(argument);
-    emitResume(mergePoint.get(), liveCalleeLocalsIndex);
-}
</del><ins>+    unsigned yieldPointIndex = m_yieldPoints++;
+    emitGeneratorStateChange(yieldPointIndex + 1);
</ins><span class="cx"> 
</span><del>-void BytecodeGenerator::emitSave(Label* mergePoint, unsigned liveCalleeLocalsIndex)
-{
-    size_t begin = instructions().size();
-    emitOpcode(op_save);
-    instructions().append(m_generatorRegister-&gt;index());
-    instructions().append(liveCalleeLocalsIndex);
-    instructions().append(mergePoint-&gt;bind(begin, instructions().size()));
-}
</del><ins>+    // Split the try range here.
+    RefPtr&lt;Label&gt; savePoint = emitLabel(newLabel().get());
+    for (unsigned i = m_tryContextStack.size(); i--;) {
+        TryContext&amp; context = m_tryContextStack[i];
+        TryRange range;
+        range.start = context.start;
+        range.end = savePoint;
+        range.tryData = context.tryData;
+        m_tryRanges.append(range);
</ins><span class="cx"> 
</span><del>-void BytecodeGenerator::emitResume(Label* mergePoint, unsigned liveCalleeLocalsIndex)
-{
-    emitGeneratorStateLabel();
-    emitOpcode(op_resume);
-    instructions().append(m_generatorRegister-&gt;index());
-    instructions().append(liveCalleeLocalsIndex);
-    emitLabel(mergePoint);
</del><ins>+        // Try range will be restared at the merge point.
+        context.start = mergePoint;
+    }
+    Vector&lt;TryContext&gt; savedTryContextStack;
+    m_tryContextStack.swap(savedTryContextStack);
+
+    emitOpcode(op_yield);
+    instructions().append(generatorFrameRegister()-&gt;index());
+    instructions().append(yieldPointIndex);
+    instructions().append(argument-&gt;index());
+
+    // Restore the try contexts, which start offset is updated to the merge point.
+    m_tryContextStack.swap(savedTryContextStack);
+    emitLabel(mergePoint.get());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterID* BytecodeGenerator::emitYield(RegisterID* argument)
</span><span class="lines">@@ -4641,39 +4650,6 @@
</span><span class="cx">     emitPutById(generatorRegister(), propertyNames().builtinNames().generatorStatePrivateName(), completedState);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void BytecodeGenerator::emitGeneratorStateLabel()
-{
-    RefPtr&lt;Label&gt; label = newLabel();
-    m_generatorResumeLabels.append(label.get());
-    emitLabel(label.get());
-}
-
-void BytecodeGenerator::beginGenerator(RegisterID* state)
-{
-    beginSwitch(state, SwitchInfo::SwitchImmediate);
-}
-
-void BytecodeGenerator::endGenerator(Label* defaultLabel)
-{
-    SwitchInfo switchInfo = m_switchContextStack.last();
-    m_switchContextStack.removeLast();
-
-    instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock-&gt;numberOfSwitchJumpTables();
-    instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel-&gt;bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
-
-    UnlinkedSimpleJumpTable&amp; jumpTable = m_codeBlock-&gt;addSwitchJumpTable();
-    int32_t switchAddress = switchInfo.bytecodeOffset;
-    jumpTable.min = 0;
-    jumpTable.branchOffsets.resize(m_generatorResumeLabels.size() + 1);
-    jumpTable.branchOffsets.fill(0);
-    for (uint32_t i = 0; i &lt; m_generatorResumeLabels.size(); ++i) {
-        // We're emitting this after the clause labels should have been fixed, so
-        // the labels should not be &quot;forward&quot; references
-        ASSERT(!m_generatorResumeLabels[i]-&gt;isForward());
-        jumpTable.add(i, m_generatorResumeLabels[i]-&gt;bind(switchAddress, switchAddress + 3));
-    }
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;Instruction.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><ins>+#include &quot;JSGeneratorFunction.h&quot;
</ins><span class="cx"> #include &quot;Label.h&quot;
</span><span class="cx"> #include &quot;LabelScope.h&quot;
</span><span class="cx"> #include &quot;Nodes.h&quot;
</span><span class="lines">@@ -690,18 +691,15 @@
</span><span class="cx">         void endSwitch(uint32_t clauseCount, RefPtr&lt;Label&gt;*, ExpressionNode**, Label* defaultLabel, int32_t min, int32_t range);
</span><span class="cx"> 
</span><span class="cx">         void emitYieldPoint(RegisterID*);
</span><del>-        void emitSave(Label* mergePoint, unsigned liveCalleeLocalsIndex);
-        void emitResume(Label* mergePoint, unsigned liveCalleeLocalsIndex);
</del><span class="cx"> 
</span><span class="cx">         void emitGeneratorStateLabel();
</span><span class="cx">         void emitGeneratorStateChange(int32_t state);
</span><span class="cx">         RegisterID* emitYield(RegisterID* argument);
</span><span class="cx">         RegisterID* emitDelegateYield(RegisterID* argument, ThrowableExpressionData*);
</span><del>-        void beginGenerator(RegisterID*);
-        void endGenerator(Label* defaultLabel);
-        RegisterID* generatorStateRegister() { return &amp;m_parameters[2]; }
-        RegisterID* generatorValueRegister() { return &amp;m_parameters[3]; }
-        RegisterID* generatorResumeModeRegister() { return &amp;m_parameters[4]; }
</del><ins>+        RegisterID* generatorStateRegister() { return &amp;m_parameters[static_cast&lt;int32_t&gt;(JSGeneratorFunction::GeneratorArgument::State)]; }
+        RegisterID* generatorValueRegister() { return &amp;m_parameters[static_cast&lt;int32_t&gt;(JSGeneratorFunction::GeneratorArgument::Value)]; }
+        RegisterID* generatorResumeModeRegister() { return &amp;m_parameters[static_cast&lt;int32_t&gt;(JSGeneratorFunction::GeneratorArgument::ResumeMode)]; }
+        RegisterID* generatorFrameRegister() { return &amp;m_parameters[static_cast&lt;int32_t&gt;(JSGeneratorFunction::GeneratorArgument::Frame)]; }
</ins><span class="cx"> 
</span><span class="cx">         CodeType codeType() const { return m_codeType; }
</span><span class="cx"> 
</span><span class="lines">@@ -929,7 +927,11 @@
</span><span class="cx">         Vector&lt;SwitchInfo&gt; m_switchContextStack;
</span><span class="cx">         Vector&lt;RefPtr&lt;ForInContext&gt;&gt; m_forInContextStack;
</span><span class="cx">         Vector&lt;TryContext&gt; m_tryContextStack;
</span><del>-        Vector&lt;RefPtr&lt;Label&gt;&gt; m_generatorResumeLabels;
</del><ins>+        unsigned m_yieldPoints { 0 };
+
+        Strong&lt;SymbolTable&gt; m_generatorFrameSymbolTable;
+        int m_generatorFrameSymbolTableIndex { 0 };
+
</ins><span class="cx">         enum FunctionVariableType : uint8_t { NormalFunctionVariable, GlobalFunctionVariable };
</span><span class="cx">         Vector&lt;std::pair&lt;FunctionMetadataNode*, FunctionVariableType&gt;&gt; m_functionsToInitialize;
</span><span class="cx">         bool m_needToInitializeArguments { false };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -3377,7 +3377,6 @@
</span><span class="cx">         RefPtr&lt;Label&gt; done = generator.newLabel();
</span><span class="cx">         generator.emitLabel(done.get());
</span><span class="cx">         generator.emitReturn(generator.emitLoad(nullptr, jsUndefined()));
</span><del>-        generator.endGenerator(done.get());
</del><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -42,8 +42,8 @@
</span><span class="cx"> #include &quot;DirectArguments.h&quot;
</span><span class="cx"> #include &quot;FTLForOSREntryJITCode.h&quot;
</span><span class="cx"> #include &quot;FTLOSREntry.h&quot;
</span><ins>+#include &quot;GetterSetter.h&quot;
</ins><span class="cx"> #include &quot;HostCallReturnValue.h&quot;
</span><del>-#include &quot;GetterSetter.h&quot;
</del><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;JIT.h&quot;
</span><span class="cx"> #include &quot;JITExceptions.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -609,7 +609,7 @@
</span><span class="cx">     return jsString(&amp;vm, builder.toString());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE static HandlerInfo* findExceptionHandler(StackVisitor&amp; visitor, CodeBlock* codeBlock, CodeBlock::RequiredHandler requiredHandler)
</del><ins>+ALWAYS_INLINE static HandlerInfo* findExceptionHandler(StackVisitor&amp; visitor, CodeBlock* codeBlock, RequiredHandler requiredHandler)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(codeBlock);
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="lines">@@ -643,7 +643,7 @@
</span><span class="cx">         if (!codeBlock)
</span><span class="cx">             return StackVisitor::Continue;
</span><span class="cx"> 
</span><del>-        m_handler = findExceptionHandler(visitor, codeBlock, CodeBlock::RequiredHandler::CatchHandler);
</del><ins>+        m_handler = findExceptionHandler(visitor, codeBlock, RequiredHandler::CatchHandler);
</ins><span class="cx">         if (m_handler)
</span><span class="cx">             return StackVisitor::Done;
</span><span class="cx"> 
</span><span class="lines">@@ -685,7 +685,7 @@
</span><span class="cx">         m_handler = nullptr;
</span><span class="cx">         if (!m_isTermination) {
</span><span class="cx">             if (m_codeBlock &amp;&amp; !isWebAssemblyExecutable(m_codeBlock-&gt;ownerExecutable()))
</span><del>-                m_handler = findExceptionHandler(visitor, m_codeBlock, CodeBlock::RequiredHandler::AnyHandler);
</del><ins>+                m_handler = findExceptionHandler(visitor, m_codeBlock, RequiredHandler::AnyHandler);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (m_handler)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -65,6 +65,7 @@
</span><span class="cx">     struct HandlerInfo;
</span><span class="cx">     struct Instruction;
</span><span class="cx">     struct ProtoCallFrame;
</span><ins>+    struct UnlinkedInstruction;
</ins><span class="cx"> 
</span><span class="cx">     enum UnwindStart { UnwindFromCurrentFrame, UnwindFromCallerFrame };
</span><span class="cx"> 
</span><span class="lines">@@ -207,7 +208,10 @@
</span><span class="cx">             return opcode;
</span><span class="cx"> #endif
</span><span class="cx">         }
</span><del>-        
</del><ins>+
+        OpcodeID getOpcodeID(const Instruction&amp;);
+        OpcodeID getOpcodeID(const UnlinkedInstruction&amp;);
+
</ins><span class="cx">         bool isOpcode(Opcode);
</span><span class="cx"> 
</span><span class="cx">         JSValue execute(ProgramExecutable*, CallFrame*, JSObject* thisObj);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpreterInlineshfromrev204993trunkSourceJavaScriptCorebytecodePreciseJumpTargetsh"></a>
<div class="copfile"><h4>Copied: trunk/Source/JavaScriptCore/interpreter/InterpreterInlines.h (from rev 204993, trunk/Source/JavaScriptCore/bytecode/PreciseJumpTargets.h) (0 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/InterpreterInlines.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/interpreter/InterpreterInlines.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+/*
+ * Copyright (C) 2016 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &quot;Instruction.h&quot;
+#include &quot;Interpreter.h&quot;
+#include &quot;UnlinkedCodeBlock.h&quot;
+
+namespace JSC {
+
+inline OpcodeID Interpreter::getOpcodeID(const Instruction&amp; instruction)
+{
+    return getOpcodeID(instruction.u.opcode);
+}
+
+inline OpcodeID Interpreter::getOpcodeID(const UnlinkedInstruction&amp; instruction)
+{
+    return instruction.u.opcode;
+}
+
+} // namespace JSC
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -235,8 +235,6 @@
</span><span class="cx">         DEFINE_OP(op_get_rest_length)
</span><span class="cx">         DEFINE_OP(op_check_tdz)
</span><span class="cx">         DEFINE_OP(op_assert)
</span><del>-        DEFINE_OP(op_save)
-        DEFINE_OP(op_resume)
</del><span class="cx">         DEFINE_OP(op_debug)
</span><span class="cx">         DEFINE_OP(op_del_by_id)
</span><span class="cx">         DEFINE_OP(op_del_by_val)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -497,8 +497,6 @@
</span><span class="cx">         void emit_op_get_rest_length(Instruction*);
</span><span class="cx">         void emit_op_check_tdz(Instruction*);
</span><span class="cx">         void emit_op_assert(Instruction*);
</span><del>-        void emit_op_save(Instruction*);
-        void emit_op_resume(Instruction*);
</del><span class="cx">         void emit_op_debug(Instruction*);
</span><span class="cx">         void emit_op_del_by_id(Instruction*);
</span><span class="cx">         void emit_op_del_by_val(Instruction*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -1492,18 +1492,6 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::emit_op_save(Instruction* currentInstruction)
-{
-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_save);
-    slowPathCall.call();
-}
-
-void JIT::emit_op_resume(Instruction* currentInstruction)
-{
-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_resume);
-    slowPathCall.call();
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -1709,18 +1709,10 @@
</span><span class="cx">     dispatch(3)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-_llint_op_save:
-    traceExecution()
-    callOpcodeSlowPath(_slow_path_save)
-    dispatch(4)
</del><ins>+_llint_op_yield:
+    notSupported()
</ins><span class="cx"> 
</span><span class="cx"> 
</span><del>-_llint_op_resume:
-    traceExecution()
-    callOpcodeSlowPath(_slow_path_resume)
-    dispatch(3)
-
-
</del><span class="cx"> _llint_op_create_lexical_environment:
</span><span class="cx">     traceExecution()
</span><span class="cx">     callOpcodeSlowPath(_slow_path_create_lexical_environment)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -260,7 +260,7 @@
</span><span class="cx">     if (m_lexer-&gt;isReparsingFunction()) {
</span><span class="cx">         ParserFunctionInfo&lt;ASTBuilder&gt; functionInfo;
</span><span class="cx">         if (parseMode == SourceParseMode::GeneratorBodyMode)
</span><del>-            m_parameters = createGeneratorParameters(context);
</del><ins>+            m_parameters = createGeneratorParameters(context, functionInfo.parameterCount);
</ins><span class="cx">         else
</span><span class="cx">             m_parameters = parseFunctionParameters(context, parseMode, functionInfo);
</span><span class="cx"> 
</span><span class="lines">@@ -512,10 +512,9 @@
</span><span class="cx"> 
</span><span class="cx">     ParserFunctionInfo&lt;TreeBuilder&gt; info;
</span><span class="cx">     info.name = &amp;m_vm-&gt;propertyNames-&gt;nullIdentifier;
</span><del>-    createGeneratorParameters(context);
</del><ins>+    createGeneratorParameters(context, info.parameterCount);
</ins><span class="cx">     info.startOffset = parametersStart;
</span><span class="cx">     info.startLine = tokenLine();
</span><del>-    info.parameterCount = 4; // generator, state, value, resume mode
</del><span class="cx"> 
</span><span class="cx">     {
</span><span class="cx">         AutoPopScopeRef generatorBodyScope(this, pushScope());
</span><span class="lines">@@ -1903,7 +1902,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template &lt;typename LexerType&gt;
</span><del>-template &lt;class TreeBuilder&gt; typename TreeBuilder::FormalParameterList Parser&lt;LexerType&gt;::createGeneratorParameters(TreeBuilder&amp; context)
</del><ins>+template &lt;class TreeBuilder&gt; typename TreeBuilder::FormalParameterList Parser&lt;LexerType&gt;::createGeneratorParameters(TreeBuilder&amp; context, unsigned&amp; parameterCount)
</ins><span class="cx"> {
</span><span class="cx">     auto parameters = context.createFormalParameterList();
</span><span class="cx"> 
</span><span class="lines">@@ -1910,25 +1909,23 @@
</span><span class="cx">     JSTokenLocation location(tokenLocation());
</span><span class="cx">     JSTextPosition position = tokenStartPosition();
</span><span class="cx"> 
</span><ins>+    auto addParameter = [&amp;](const Identifier&amp; name) {
+        declareParameter(&amp;name);
+        auto binding = context.createBindingLocation(location, name, position, position, AssignmentContext::DeclarationStatement);
+        context.appendParameter(parameters, binding, 0);
+        ++parameterCount;
+    };
+
</ins><span class="cx">     // @generator
</span><del>-    declareParameter(&amp;m_vm-&gt;propertyNames-&gt;builtinNames().generatorPrivateName());
-    auto generator = context.createBindingLocation(location, m_vm-&gt;propertyNames-&gt;builtinNames().generatorPrivateName(), position, position, AssignmentContext::DeclarationStatement);
-    context.appendParameter(parameters, generator, 0);
-
</del><ins>+    addParameter(m_vm-&gt;propertyNames-&gt;builtinNames().generatorPrivateName());
</ins><span class="cx">     // @generatorState
</span><del>-    declareParameter(&amp;m_vm-&gt;propertyNames-&gt;builtinNames().generatorStatePrivateName());
-    auto generatorState = context.createBindingLocation(location, m_vm-&gt;propertyNames-&gt;builtinNames().generatorStatePrivateName(), position, position, AssignmentContext::DeclarationStatement);
-    context.appendParameter(parameters, generatorState, 0);
-
</del><ins>+    addParameter(m_vm-&gt;propertyNames-&gt;builtinNames().generatorStatePrivateName());
</ins><span class="cx">     // @generatorValue
</span><del>-    declareParameter(&amp;m_vm-&gt;propertyNames-&gt;builtinNames().generatorValuePrivateName());
-    auto generatorValue = context.createBindingLocation(location, m_vm-&gt;propertyNames-&gt;builtinNames().generatorValuePrivateName(), position, position, AssignmentContext::DeclarationStatement);
-    context.appendParameter(parameters, generatorValue, 0);
-
</del><ins>+    addParameter(m_vm-&gt;propertyNames-&gt;builtinNames().generatorValuePrivateName());
</ins><span class="cx">     // @generatorResumeMode
</span><del>-    declareParameter(&amp;m_vm-&gt;propertyNames-&gt;builtinNames().generatorResumeModePrivateName());
-    auto generatorResumeMode = context.createBindingLocation(location, m_vm-&gt;propertyNames-&gt;builtinNames().generatorResumeModePrivateName(), position, position, AssignmentContext::DeclarationStatement);
-    context.appendParameter(parameters, generatorResumeMode, 0);
</del><ins>+    addParameter(m_vm-&gt;propertyNames-&gt;builtinNames().generatorResumeModePrivateName());
+    // @generatorFrame
+    addParameter(m_vm-&gt;propertyNames-&gt;builtinNames().generatorFramePrivateName());
</ins><span class="cx"> 
</span><span class="cx">     return parameters;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/parser/Parser.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -1426,7 +1426,7 @@
</span><span class="cx">     ALWAYS_INLINE bool isArrowFunctionParameters();
</span><span class="cx">     
</span><span class="cx">     template &lt;class TreeBuilder, class FunctionInfoType&gt; NEVER_INLINE typename TreeBuilder::FormalParameterList parseFunctionParameters(TreeBuilder&amp;, SourceParseMode, FunctionInfoType&amp;);
</span><del>-    template &lt;class TreeBuilder&gt; NEVER_INLINE typename TreeBuilder::FormalParameterList createGeneratorParameters(TreeBuilder&amp;);
</del><ins>+    template &lt;class TreeBuilder&gt; NEVER_INLINE typename TreeBuilder::FormalParameterList createGeneratorParameters(TreeBuilder&amp;, unsigned&amp; parameterCount);
</ins><span class="cx"> 
</span><span class="cx">     template &lt;class TreeBuilder&gt; NEVER_INLINE TreeClassExpression parseClass(TreeBuilder&amp;, FunctionNameRequirements, ParserClassInfo&lt;TreeBuilder&gt;&amp;);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -37,7 +37,6 @@
</span><span class="cx"> #include &quot;Error.h&quot;
</span><span class="cx"> #include &quot;ErrorHandlingScope.h&quot;
</span><span class="cx"> #include &quot;ExceptionFuzz.h&quot;
</span><del>-#include &quot;GeneratorFrame.h&quot;
</del><span class="cx"> #include &quot;GetterSetter.h&quot;
</span><span class="cx"> #include &quot;HostCallReturnValue.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="lines">@@ -753,38 +752,6 @@
</span><span class="cx">     END();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-SLOW_PATH_DECL(slow_path_save)
-{
-    // Only save variables and temporary registers. The scope registers are included in them.
-    // But parameters are not included. Because the generator implementation replaces the values of parameters on each generator.next() call.
-    BEGIN();
-    JSValue generator = OP(1).jsValue();
-    GeneratorFrame* frame = nullptr;
-    JSValue value = generator.get(exec, exec-&gt;propertyNames().builtinNames().generatorFramePrivateName());
-    if (!value.isNull())
-        frame = jsCast&lt;GeneratorFrame*&gt;(value);
-    else {
-        // FIXME: Once JSGenerator specialized object is introduced, this GeneratorFrame should be embeded into it to avoid allocations.
-        // https://bugs.webkit.org/show_bug.cgi?id=151545
-        frame = GeneratorFrame::create(exec-&gt;vm(),  exec-&gt;codeBlock()-&gt;numCalleeLocals());
-        PutPropertySlot slot(generator, true, PutPropertySlot::PutById);
-        asObject(generator)-&gt;methodTable(exec-&gt;vm())-&gt;put(asObject(generator), exec, exec-&gt;propertyNames().builtinNames().generatorFramePrivateName(), frame, slot);
-    }
-    unsigned liveCalleeLocalsIndex = pc[2].u.unsignedValue;
-    frame-&gt;save(exec, exec-&gt;codeBlock()-&gt;liveCalleeLocalsAtYield(liveCalleeLocalsIndex));
-    END();
-}
-
-SLOW_PATH_DECL(slow_path_resume)
-{
-    BEGIN();
-    JSValue generator = OP(1).jsValue();
-    GeneratorFrame* frame = jsCast&lt;GeneratorFrame*&gt;(generator.get(exec, exec-&gt;propertyNames().builtinNames().generatorFramePrivateName()));
-    unsigned liveCalleeLocalsIndex = pc[2].u.unsignedValue;
-    frame-&gt;resume(exec, exec-&gt;codeBlock()-&gt;liveCalleeLocalsAtYield(liveCalleeLocalsIndex));
-    END();
-}
-
</del><span class="cx"> SLOW_PATH_DECL(slow_path_create_lexical_environment)
</span><span class="cx"> {
</span><span class="cx">     BEGIN();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -248,8 +248,6 @@
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_to_index_string);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_profile_type_clear_log);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_assert);
</span><del>-SLOW_PATH_HIDDEN_DECL(slow_path_save);
-SLOW_PATH_HIDDEN_DECL(slow_path_resume);
</del><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_create_lexical_environment);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_push_with_scope);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_resolve_scope);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeGeneratorFramecpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/runtime/GeneratorFrame.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/GeneratorFrame.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/runtime/GeneratorFrame.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -1,97 +0,0 @@
</span><del>-/*
- * Copyright (C) 2015 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include &quot;config.h&quot;
-#include &quot;GeneratorFrame.h&quot;
-
-#include &quot;CodeBlock.h&quot;
-#include &quot;HeapIterationScope.h&quot;
-#include &quot;JSCJSValueInlines.h&quot;
-#include &quot;JSCellInlines.h&quot;
-#include &quot;SlotVisitorInlines.h&quot;
-#include &quot;StructureInlines.h&quot;
-
-namespace JSC {
-
-const ClassInfo GeneratorFrame::s_info = { &quot;GeneratorFrame&quot;, nullptr, nullptr, CREATE_METHOD_TABLE(GeneratorFrame) };
-
-GeneratorFrame::GeneratorFrame(VM&amp; vm, size_t numberOfCalleeLocals)
-    : Base(vm, vm.generatorFrameStructure.get())
-    , m_numberOfCalleeLocals(numberOfCalleeLocals)
-{
-}
-
-void GeneratorFrame::finishCreation(VM&amp; vm)
-{
-    Base::finishCreation(vm);
-    for (size_t i = 0; i &lt; m_numberOfCalleeLocals; ++i)
-        localAt(i).clear();
-}
-
-Structure* GeneratorFrame::createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
-{
-    return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
-}
-
-GeneratorFrame* GeneratorFrame::create(VM&amp; vm, size_t numberOfLocals)
-{
-    GeneratorFrame* result =
-        new (
-            NotNull,
-            allocateCell&lt;GeneratorFrame&gt;(vm.heap, allocationSizeForLocals(numberOfLocals)))
-        GeneratorFrame(vm, numberOfLocals);
-    result-&gt;finishCreation(vm);
-    return result;
-}
-
-void GeneratorFrame::save(ExecState* exec, const FastBitVector&amp; liveCalleeLocals)
-{
-    // Only save callee locals.
-    // Every time a generator is called (or resumed), parameters should be replaced.
-    ASSERT(liveCalleeLocals.numBits() &lt;= m_numberOfCalleeLocals);
-    liveCalleeLocals.forEachSetBit([&amp;](size_t index) {
-        localAt(index).set(exec-&gt;vm(), this, exec-&gt;uncheckedR(virtualRegisterForLocal(index)).jsValue());
-    });
-}
-
-void GeneratorFrame::resume(ExecState* exec, const FastBitVector&amp; liveCalleeLocals)
-{
-    // Only resume callee locals.
-    // Every time a generator is called (or resumed), parameters should be replaced.
-    liveCalleeLocals.forEachSetBit([&amp;](size_t index) {
-        exec-&gt;uncheckedR(virtualRegisterForLocal(index)) = localAt(index).get();
-        localAt(index).clear();
-    });
-}
-
-void GeneratorFrame::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
-{
-    GeneratorFrame* thisObject = jsCast&lt;GeneratorFrame*&gt;(cell);
-    Base::visitChildren(thisObject, visitor);
-    // Since only true cell pointers are stored as a cell, we can safely mark them.
-    visitor.appendValues(thisObject-&gt;locals(), thisObject-&gt;m_numberOfCalleeLocals);
-}
-
-} // namespace JSC
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeGeneratorFrameh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/runtime/GeneratorFrame.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/GeneratorFrame.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/runtime/GeneratorFrame.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -1,90 +0,0 @@
</span><del>-/*
- * Copyright (C) 2015 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef GeneratorFrame_h
-#define GeneratorFrame_h
-
-#include &quot;JSCell.h&quot;
-#include &lt;wtf/FastBitVector.h&gt;
-
-namespace JSC {
-
-class GeneratorFrame : public JSCell {
-    friend class JIT;
-#if ENABLE(DFG_JIT)
-    friend class DFG::SpeculativeJIT;
-    friend class DFG::JITCompiler;
-#endif
-    friend class VM;
-public:
-    typedef JSCell Base;
-    static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags;
-
-    DECLARE_EXPORT_INFO;
-
-    static GeneratorFrame* create(VM&amp;, size_t numberOfCalleeLocals);
-
-    WriteBarrierBase&lt;Unknown&gt;* locals()
-    {
-        return bitwise_cast&lt;WriteBarrierBase&lt;Unknown&gt;*&gt;(bitwise_cast&lt;char*&gt;(this) + offsetOfLocals());
-    }
-
-    WriteBarrierBase&lt;Unknown&gt;&amp; localAt(size_t index)
-    {
-        ASSERT(index &lt; m_numberOfCalleeLocals);
-        return locals()[index];
-    }
-
-    static size_t offsetOfLocals()
-    {
-        return WTF::roundUpToMultipleOf&lt;sizeof(WriteBarrier&lt;Unknown&gt;)&gt;(sizeof(GeneratorFrame));
-    }
-
-    static size_t allocationSizeForLocals(unsigned numberOfLocals)
-    {
-        return offsetOfLocals() + numberOfLocals * sizeof(WriteBarrier&lt;Unknown&gt;);
-    }
-
-    static Structure* createStructure(VM&amp;, JSGlobalObject*, JSValue prototype);
-
-    void save(ExecState*, const FastBitVector&amp; liveCalleeLocals);
-    void resume(ExecState*, const FastBitVector&amp; liveCalleeLocals);
-
-private:
-    GeneratorFrame(VM&amp;, size_t numberOfCalleeLocals);
-
-    size_t m_numberOfCalleeLocals;
-
-    friend class LLIntOffsetsExtractor;
-
-    void finishCreation(VM&amp;);
-
-protected:
-    static void visitChildren(JSCell*, SlotVisitor&amp;);
-};
-
-} // namespace JSC
-
-#endif // GeneratorFrame_h
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGeneratorFunctionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGeneratorFunction.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGeneratorFunction.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/runtime/JSGeneratorFunction.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -55,6 +55,16 @@
</span><span class="cx">         Executing = -2,
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    // [this], @generator, @generatorState, @generatorValue, @generatorResumeMode, @generatorFrame.
+    enum class GeneratorArgument : int32_t {
+        ThisValue = 0,
+        Generator = 1,
+        State = 2,
+        Value = 3,
+        ResumeMode = 4,
+        Frame = 5,
+    };
+
</ins><span class="cx">     const static unsigned StructureFlags = Base::StructureFlags;
</span><span class="cx"> 
</span><span class="cx">     DECLARE_EXPORT_INFO;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -46,7 +46,6 @@
</span><span class="cx"> #include &quot;FTLThunks.h&quot;
</span><span class="cx"> #include &quot;FunctionConstructor.h&quot;
</span><span class="cx"> #include &quot;GCActivityCallback.h&quot;
</span><del>-#include &quot;GeneratorFrame.h&quot;
</del><span class="cx"> #include &quot;GetterSetter.h&quot;
</span><span class="cx"> #include &quot;Heap.h&quot;
</span><span class="cx"> #include &quot;HeapIterationScope.h&quot;
</span><span class="lines">@@ -240,7 +239,6 @@
</span><span class="cx">     inferredTypeStructure.set(*this, InferredType::createStructure(*this, 0, jsNull()));
</span><span class="cx">     inferredTypeTableStructure.set(*this, InferredTypeTable::createStructure(*this, 0, jsNull()));
</span><span class="cx">     functionRareDataStructure.set(*this, FunctionRareData::createStructure(*this, 0, jsNull()));
</span><del>-    generatorFrameStructure.set(*this, GeneratorFrame::createStructure(*this, 0, jsNull()));
</del><span class="cx">     exceptionStructure.set(*this, Exception::createStructure(*this, 0, jsNull()));
</span><span class="cx">     promiseDeferredStructure.set(*this, JSPromiseDeferred::createStructure(*this, 0, jsNull()));
</span><span class="cx">     internalPromiseDeferredStructure.set(*this, JSInternalPromiseDeferred::createStructure(*this, 0, jsNull()));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -320,7 +320,6 @@
</span><span class="cx">     Strong&lt;Structure&gt; inferredTypeStructure;
</span><span class="cx">     Strong&lt;Structure&gt; inferredTypeTableStructure;
</span><span class="cx">     Strong&lt;Structure&gt; functionRareDataStructure;
</span><del>-    Strong&lt;Structure&gt; generatorFrameStructure;
</del><span class="cx">     Strong&lt;Structure&gt; exceptionStructure;
</span><span class="cx">     Strong&lt;Structure&gt; promiseDeferredStructure;
</span><span class="cx">     Strong&lt;Structure&gt; internalPromiseDeferredStructure;
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/WTF/ChangeLog        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2016-08-25  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        [DFG][FTL] Implement ES6 Generators in DFG / FTL
+        https://bugs.webkit.org/show_bug.cgi?id=152723
+
+        Reviewed by Filip Pizlo.
+
+        * wtf/FastBitVector.h:
+        (WTF::FastBitVector::FastBitVector):
+
</ins><span class="cx"> 2016-08-25  JF Bastien  &lt;jfbastien@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         TryGetById should have a ValueProfile so that it can predict its output type
</span></span></pre></div>
<a id="trunkSourceWTFwtfFastBitVectorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/FastBitVector.h (204993 => 204994)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/FastBitVector.h        2016-08-25 22:27:02 UTC (rev 204993)
+++ trunk/Source/WTF/wtf/FastBitVector.h        2016-08-25 22:55:10 UTC (rev 204994)
</span><span class="lines">@@ -23,8 +23,7 @@
</span><span class="cx">  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#ifndef FastBitVector_h
-#define FastBitVector_h
</del><ins>+#pragma once
</ins><span class="cx"> 
</span><span class="cx"> #include &lt;string.h&gt;
</span><span class="cx"> #include &lt;wtf/FastMalloc.h&gt;
</span><span class="lines">@@ -36,12 +35,14 @@
</span><span class="cx"> 
</span><span class="cx"> class FastBitVector {
</span><span class="cx"> public:
</span><del>-    FastBitVector()
-        : m_array(0)
-        , m_numBits(0)
</del><ins>+    FastBitVector() = default;
+
+    FastBitVector(FastBitVector&amp;&amp; other)
+        : m_array(std::exchange(other.m_array, nullptr))
+        , m_numBits(std::exchange(other.m_numBits, 0))
</ins><span class="cx">     {
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     FastBitVector(const FastBitVector&amp; other)
</span><span class="cx">         : m_array(0)
</span><span class="cx">         , m_numBits(0)
</span><span class="lines">@@ -202,13 +203,10 @@
</span><span class="cx">     static size_t arrayLength(size_t numBits) { return (numBits + 31) &gt;&gt; 5; }
</span><span class="cx">     size_t arrayLength() const { return arrayLength(m_numBits); }
</span><span class="cx">     
</span><del>-    uint32_t* m_array; // No, this can't be an std::unique_ptr&lt;uint32_t[]&gt;.
-    size_t m_numBits;
</del><ins>+    uint32_t* m_array { nullptr }; // No, this can't be an std::unique_ptr&lt;uint32_t[]&gt;.
+    size_t m_numBits { 0 };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WTF
</span><span class="cx"> 
</span><span class="cx"> using WTF::FastBitVector;
</span><del>-
-#endif // FastBitVector_h
-
</del></span></pre>
</div>
</div>

</body>
</html>