<!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>[189766] trunk/Source/JavaScriptCore</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/189766">189766</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-09-14 17:55:17 -0700 (Mon, 14 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>LLInt get/put inline caches shouldn't use tons of opcodes
https://bugs.webkit.org/show_bug.cgi?id=149106

Reviewed by Geoffrey Garen.

Our LLInt get/put inline caches currently use separate opcodes to reduce branching. For
example, instead of having get_by_id branch on the kind of offset (inline or
out-of-line), we have two get_by_id instructions: get_by_id and get_by_id_out_of_line.
But the problem with this approach is that it doesn't scale. In the property type
inference work (https://bugs.webkit.org/show_bug.cgi?id=148610), we need each kind of put
inline cache to support 11 different kinds of type checks. It seemed ridiculous to add 60
new put_by_id opcodes (there are currently 6 variants of put_by_id, so after adding type
checks, we'd have 6 * 11 = 66 variants of put_by_id).

So, this patch completely changes the strategy to mostly using branching inside the
opcode implementation. It's unlikely to have a performance effect. For example, the long
road to generational GC caused a seemingly prohibitive regression in LLInt inline caches,
and yet nobody noticed. The regression was because the inline cache was in terms of the
structure, not the structure ID, so the code was doing a structure ID table lookup. If we
didn't notice that, then we probably won't notice a couple new branches. (Also, this
patch fixes that regression - the code no longer does such lookups except in the one
unavoidable case in put_by_id transition chain checking.)

This patch also turns the isDirect operand of put_by_id into a flags field. I will use
this flags field to encode the desired type check in bug 148610.

This patch has no effect on performance according to run-jsc-benchmarks.

Relanding this patch with LLInt fixes for non-x86. Previous attempts to fix non-x86 LLInt
build also caused every 64-bit test to crash on every platform. So the patch got rolled
out. This fixes the non-x86 LLInt build while also ensuring that 64-bit platforms don't
crash.

* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::printGetByIdOp):
(JSC::CodeBlock::printGetByIdCacheStatus):
(JSC::CodeBlock::printPutByIdCacheStatus):
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):
(JSC::CodeBlock::propagateTransitions):
(JSC::CodeBlock::finalizeLLIntInlineCaches):
* bytecode/CodeBlock.h:
* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
* bytecode/Instruction.h:
(JSC::Instruction::Instruction):
* bytecode/PutByIdFlags.cpp: Added.
(WTF::printInternal):
* bytecode/PutByIdFlags.h: Added.
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFromLLInt):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedInstruction::UnlinkedInstruction):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitPutById):
(JSC::BytecodeGenerator::emitDirectPutById):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_put_by_id):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emit_op_put_by_id):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeListjson">trunk/Source/JavaScriptCore/bytecode/BytecodeList.json</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="#trunkSourceJavaScriptCorebytecodeGetByIdStatuscpp">trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeInstructionh">trunk/Source/JavaScriptCore/bytecode/Instruction.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePutByIdStatuscpp">trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCapabilitiescpp">trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccesscpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccess32_64cpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCorebytecodePutByIdFlagscpp">trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePutByIdFlagsh">trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -107,6 +107,7 @@
</span><span class="cx">     bytecode/PolymorphicAccess.cpp
</span><span class="cx">     bytecode/PreciseJumpTargets.cpp
</span><span class="cx">     bytecode/PropertyCondition.cpp
</span><ins>+    bytecode/PutByIdFlags.cpp
</ins><span class="cx">     bytecode/PutByIdStatus.cpp
</span><span class="cx">     bytecode/PutByIdVariant.cpp
</span><span class="cx">     bytecode/ReduceWhitespace.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -1,3 +1,85 @@
</span><ins>+2015-09-14  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        LLInt get/put inline caches shouldn't use tons of opcodes
+        https://bugs.webkit.org/show_bug.cgi?id=149106
+
+        Reviewed by Geoffrey Garen.
+
+        Our LLInt get/put inline caches currently use separate opcodes to reduce branching. For
+        example, instead of having get_by_id branch on the kind of offset (inline or
+        out-of-line), we have two get_by_id instructions: get_by_id and get_by_id_out_of_line.
+        But the problem with this approach is that it doesn't scale. In the property type
+        inference work (https://bugs.webkit.org/show_bug.cgi?id=148610), we need each kind of put
+        inline cache to support 11 different kinds of type checks. It seemed ridiculous to add 60
+        new put_by_id opcodes (there are currently 6 variants of put_by_id, so after adding type
+        checks, we'd have 6 * 11 = 66 variants of put_by_id).
+
+        So, this patch completely changes the strategy to mostly using branching inside the
+        opcode implementation. It's unlikely to have a performance effect. For example, the long
+        road to generational GC caused a seemingly prohibitive regression in LLInt inline caches,
+        and yet nobody noticed. The regression was because the inline cache was in terms of the
+        structure, not the structure ID, so the code was doing a structure ID table lookup. If we
+        didn't notice that, then we probably won't notice a couple new branches. (Also, this
+        patch fixes that regression - the code no longer does such lookups except in the one
+        unavoidable case in put_by_id transition chain checking.)
+
+        This patch also turns the isDirect operand of put_by_id into a flags field. I will use
+        this flags field to encode the desired type check in bug 148610.
+
+        This patch has no effect on performance according to run-jsc-benchmarks.
+
+        Relanding this patch with LLInt fixes for non-x86. Previous attempts to fix non-x86 LLInt
+        build also caused every 64-bit test to crash on every platform. So the patch got rolled
+        out. This fixes the non-x86 LLInt build while also ensuring that 64-bit platforms don't
+        crash.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::printGetByIdOp):
+        (JSC::CodeBlock::printGetByIdCacheStatus):
+        (JSC::CodeBlock::printPutByIdCacheStatus):
+        (JSC::CodeBlock::dumpBytecode):
+        (JSC::CodeBlock::CodeBlock):
+        (JSC::CodeBlock::propagateTransitions):
+        (JSC::CodeBlock::finalizeLLIntInlineCaches):
+        * bytecode/CodeBlock.h:
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeFromLLInt):
+        * bytecode/Instruction.h:
+        (JSC::Instruction::Instruction):
+        * bytecode/PutByIdFlags.cpp: Added.
+        (WTF::printInternal):
+        * bytecode/PutByIdFlags.h: Added.
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::computeFromLLInt):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedInstruction::UnlinkedInstruction):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitPutById):
+        (JSC::BytecodeGenerator::emitDirectPutById):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCapabilities.cpp:
+        (JSC::DFG::capabilityLevel):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_put_by_id):
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::emit_op_put_by_id):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+
</ins><span class="cx"> 2015-09-14  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r189751, r189752, and r189754.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -346,6 +346,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\PolymorphicAccess.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\PreciseJumpTargets.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\PropertyCondition.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\bytecode\PutByIdFlags.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\PutByIdStatus.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\PutByIdVariant.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\ReduceWhitespace.cpp&quot; /&gt;
</span><span class="lines">@@ -1046,6 +1047,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\PolymorphicAccess.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\PreciseJumpTargets.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\PropertyCondition.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\bytecode\PutByIdFlags.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\PutByIdStatus.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\PutByIdVariant.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\PutKind.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -201,6 +201,9 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\PolymorphicAccess.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;bytecode&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\bytecode\PutByIdFlags.cpp&quot;&gt;
+      &lt;Filter&gt;bytecode&lt;/Filter&gt;
+    &lt;/ClCompile&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\bytecode\PutByIdStatus.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;bytecode&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><span class="lines">@@ -2094,6 +2097,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\PolymorphicAccess.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;bytecode&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\bytecode\PutByIdFlags.h&quot;&gt;
+      &lt;Filter&gt;bytecode&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\bytecode\PutByIdStatus.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;bytecode&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -105,6 +105,8 @@
</span><span class="cx">                 0F13912B16771C3A009CCB07 /* ProfilerProfiledBytecodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */; };
</span><span class="cx">                 0F13912C16771C3D009CCB07 /* ProfilerProfiledBytecodes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F13E04E16164A1F00DC8DE7 /* IndexingType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */; };
</span><ins>+                0F15CD221BA5F9860031FFD3 /* PutByIdFlags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F15CD201BA5F9860031FFD3 /* PutByIdFlags.cpp */; };
+                0F15CD231BA5F9860031FFD3 /* PutByIdFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15CD211BA5F9860031FFD3 /* PutByIdFlags.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F1725FF1B48719A00AC3A55 /* DFGMinifiedGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */; };
</span><span class="cx">                 0F18D3CF1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F18D3CD1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp */; };
</span><span class="lines">@@ -1932,6 +1934,8 @@
</span><span class="cx">                 0F13912616771C30009CCB07 /* ProfilerProfiledBytecodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerProfiledBytecodes.cpp; path = profiler/ProfilerProfiledBytecodes.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F13912716771C30009CCB07 /* ProfilerProfiledBytecodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerProfiledBytecodes.h; path = profiler/ProfilerProfiledBytecodes.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexingType.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F15CD201BA5F9860031FFD3 /* PutByIdFlags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdFlags.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F15CD211BA5F9860031FFD3 /* PutByIdFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdFlags.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F1725FE1B48719A00AC3A55 /* DFGMinifiedGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGMinifiedGraph.cpp; path = dfg/DFGMinifiedGraph.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F18D3CD1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAdaptiveStructureWatchpoint.cpp; path = dfg/DFGAdaptiveStructureWatchpoint.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5600,6 +5604,8 @@
</span><span class="cx">                                 0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */,
</span><span class="cx">                                 0FD3E4071B618B6600C80E1E /* PropertyCondition.cpp */,
</span><span class="cx">                                 0FD3E4081B618B6600C80E1E /* PropertyCondition.h */,
</span><ins>+                                0F15CD201BA5F9860031FFD3 /* PutByIdFlags.cpp */,
+                                0F15CD211BA5F9860031FFD3 /* PutByIdFlags.h */,
</ins><span class="cx">                                 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
</span><span class="cx">                                 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
</span><span class="cx">                                 0F93B4A718B92C4D00178A3F /* PutByIdVariant.cpp */,
</span><span class="lines">@@ -6740,6 +6746,7 @@
</span><span class="cx">                                 0F682FB319BCB36400FA3BAD /* DFGSSACalculator.h in Headers */,
</span><span class="cx">                                 0FB7F39D15ED8E4600F167B2 /* Reject.h in Headers */,
</span><span class="cx">                                 0F2D4DEA19832DAC007D4B19 /* TypeLocation.h in Headers */,
</span><ins>+                                0F15CD231BA5F9860031FFD3 /* PutByIdFlags.h in Headers */,
</ins><span class="cx">                                 A5BA15E8182340B300A82E69 /* RemoteInspector.h in Headers */,
</span><span class="cx">                                 A5BA15EA182340B400A82E69 /* RemoteInspectorConstants.h in Headers */,
</span><span class="cx">                                 A5BA15F0182345AF00A82E69 /* RemoteInspectorDebuggable.h in Headers */,
</span><span class="lines">@@ -7472,6 +7479,7 @@
</span><span class="cx">                                 0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
</span><span class="cx">                                 0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */,
</span><span class="cx">                                 0F8F2B99172F04FF007DBDA5 /* DFGDesiredIdentifiers.cpp in Sources */,
</span><ins>+                                0F15CD221BA5F9860031FFD3 /* PutByIdFlags.cpp in Sources */,
</ins><span class="cx">                                 C2C0F7CD17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp in Sources */,
</span><span class="cx">                                 0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */,
</span><span class="cx">                                 C2981FD817BAEE4B00A3BC98 /* DFGDesiredWeakReferences.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeListjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeList.json (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -57,14 +57,8 @@
</span><span class="cx">             { &quot;name&quot; : &quot;op_is_function&quot;, &quot;length&quot; : 3 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_in&quot;, &quot;length&quot; : 4 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_get_by_id&quot;, &quot;length&quot; : 9  },
</span><del>-            { &quot;name&quot; : &quot;op_get_by_id_out_of_line&quot;, &quot;length&quot; : 9  },
</del><span class="cx">             { &quot;name&quot; : &quot;op_get_array_length&quot;, &quot;length&quot; : 9 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_put_by_id&quot;, &quot;length&quot; : 9 },
</span><del>-            { &quot;name&quot; : &quot;op_put_by_id_out_of_line&quot;, &quot;length&quot; : 9 },
-            { &quot;name&quot; : &quot;op_put_by_id_transition_direct&quot;, &quot;length&quot; : 9 },
-            { &quot;name&quot; : &quot;op_put_by_id_transition_direct_out_of_line&quot;, &quot;length&quot; : 9 },
-            { &quot;name&quot; : &quot;op_put_by_id_transition_normal&quot;, &quot;length&quot; : 9 },
-            { &quot;name&quot; : &quot;op_put_by_id_transition_normal_out_of_line&quot;, &quot;length&quot; : 9 },
</del><span class="cx">             { &quot;name&quot; : &quot;op_del_by_id&quot;, &quot;length&quot; : 4 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_get_by_val&quot;, &quot;length&quot; : 6 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_put_by_val&quot;, &quot;length&quot; : 5 },
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -93,11 +93,6 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     case op_put_by_index:
</span><del>-    case op_put_by_id_transition_direct:
-    case op_put_by_id_transition_direct_out_of_line:
-    case op_put_by_id_transition_normal:
-    case op_put_by_id_transition_normal_out_of_line:
-    case op_put_by_id_out_of_line:
</del><span class="cx">     case op_put_by_id:
</span><span class="cx">     case op_put_to_scope:
</span><span class="cx">     case op_put_to_arguments: {
</span><span class="lines">@@ -134,7 +129,6 @@
</span><span class="cx">     case op_get_from_scope:
</span><span class="cx">     case op_to_primitive:
</span><span class="cx">     case op_get_by_id:
</span><del>-    case op_get_by_id_out_of_line:
</del><span class="cx">     case op_get_array_length:
</span><span class="cx">     case op_typeof:
</span><span class="cx">     case op_is_undefined:
</span><span class="lines">@@ -277,11 +271,6 @@
</span><span class="cx">     case op_switch_char:
</span><span class="cx">     case op_switch_string:
</span><span class="cx">     case op_put_by_id:
</span><del>-    case op_put_by_id_out_of_line:
-    case op_put_by_id_transition_direct:
-    case op_put_by_id_transition_direct_out_of_line:
-    case op_put_by_id_transition_normal:
-    case op_put_by_id_transition_normal_out_of_line:
</del><span class="cx">     case op_put_getter_by_id:
</span><span class="cx">     case op_put_setter_by_id:
</span><span class="cx">     case op_put_getter_setter:
</span><span class="lines">@@ -328,7 +317,6 @@
</span><span class="cx">     case op_call_eval:
</span><span class="cx">     case op_construct:
</span><span class="cx">     case op_get_by_id:
</span><del>-    case op_get_by_id_out_of_line:
</del><span class="cx">     case op_get_array_length:
</span><span class="cx">     case op_check_has_instance:
</span><span class="cx">     case op_instanceof:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -273,9 +273,6 @@
</span><span class="cx">     case op_get_by_id:
</span><span class="cx">         op = &quot;get_by_id&quot;;
</span><span class="cx">         break;
</span><del>-    case op_get_by_id_out_of_line:
-        op = &quot;get_by_id_out_of_line&quot;;
-        break;
</del><span class="cx">     case op_get_array_length:
</span><span class="cx">         op = &quot;array_length&quot;;
</span><span class="cx">         break;
</span><span class="lines">@@ -331,7 +328,8 @@
</span><span class="cx">     
</span><span class="cx">     if (exec-&gt;interpreter()-&gt;getOpcodeID(instruction[0].u.opcode) == op_get_array_length)
</span><span class="cx">         out.printf(&quot; llint(array_length)&quot;);
</span><del>-    else if (Structure* structure = instruction[4].u.structure.get()) {
</del><ins>+    else if (StructureID structureID = instruction[4].u.structureID) {
+        Structure* structure = m_vm-&gt;heap.structureIDTable().get(structureID);
</ins><span class="cx">         out.printf(&quot; llint(&quot;);
</span><span class="cx">         dumpStructure(out, &quot;struct&quot;, structure, ident);
</span><span class="cx">         out.printf(&quot;)&quot;);
</span><span class="lines">@@ -382,42 +380,31 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CodeBlock::printPutByIdCacheStatus(PrintStream&amp; out, ExecState* exec, int location, const StubInfoMap&amp; map)
</del><ins>+void CodeBlock::printPutByIdCacheStatus(PrintStream&amp; out, int location, const StubInfoMap&amp; map)
</ins><span class="cx"> {
</span><span class="cx">     Instruction* instruction = instructions().begin() + location;
</span><span class="cx"> 
</span><span class="cx">     const Identifier&amp; ident = identifier(instruction[2].u.operand);
</span><span class="cx">     
</span><span class="cx">     UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
</span><ins>+
+    out.print(&quot;, &quot;, instruction[8].u.putByIdFlags);
</ins><span class="cx">     
</span><del>-    if (Structure* structure = instruction[4].u.structure.get()) {
-        switch (exec-&gt;interpreter()-&gt;getOpcodeID(instruction[0].u.opcode)) {
-        case op_put_by_id:
-        case op_put_by_id_out_of_line:
-            out.print(&quot; llint(&quot;);
-            dumpStructure(out, &quot;struct&quot;, structure, ident);
-            out.print(&quot;)&quot;);
-            break;
-            
-        case op_put_by_id_transition_direct:
-        case op_put_by_id_transition_normal:
-        case op_put_by_id_transition_direct_out_of_line:
-        case op_put_by_id_transition_normal_out_of_line:
-            out.print(&quot; llint(&quot;);
</del><ins>+    if (StructureID structureID = instruction[4].u.structureID) {
+        Structure* structure = m_vm-&gt;heap.structureIDTable().get(structureID);
+        out.print(&quot; llint(&quot;);
+        if (StructureID newStructureID = instruction[6].u.structureID) {
+            Structure* newStructure = m_vm-&gt;heap.structureIDTable().get(newStructureID);
</ins><span class="cx">             dumpStructure(out, &quot;prev&quot;, structure, ident);
</span><span class="cx">             out.print(&quot;, &quot;);
</span><del>-            dumpStructure(out, &quot;next&quot;, instruction[6].u.structure.get(), ident);
</del><ins>+            dumpStructure(out, &quot;next&quot;, newStructure, ident);
</ins><span class="cx">             if (StructureChain* chain = instruction[7].u.structureChain.get()) {
</span><span class="cx">                 out.print(&quot;, &quot;);
</span><span class="cx">                 dumpChain(out, chain, ident);
</span><span class="cx">             }
</span><del>-            out.print(&quot;)&quot;);
-            break;
-            
-        default:
-            out.print(&quot; llint(unknown)&quot;);
-            break;
-        }
</del><ins>+        } else
+            dumpStructure(out, &quot;struct&quot;, structure, ident);
+        out.print(&quot;)&quot;);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="lines">@@ -1001,7 +988,6 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         case op_get_by_id:
</span><del>-        case op_get_by_id_out_of_line:
</del><span class="cx">         case op_get_array_length: {
</span><span class="cx">             printGetByIdOp(out, exec, location, it);
</span><span class="cx">             printGetByIdCacheStatus(out, exec, location, stubInfos);
</span><span class="lines">@@ -1010,34 +996,9 @@
</span><span class="cx">         }
</span><span class="cx">         case op_put_by_id: {
</span><span class="cx">             printPutByIdOp(out, exec, location, it, &quot;put_by_id&quot;);
</span><del>-            printPutByIdCacheStatus(out, exec, location, stubInfos);
</del><ins>+            printPutByIdCacheStatus(out, location, stubInfos);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><del>-        case op_put_by_id_out_of_line: {
-            printPutByIdOp(out, exec, location, it, &quot;put_by_id_out_of_line&quot;);
-            printPutByIdCacheStatus(out, exec, location, stubInfos);
-            break;
-        }
-        case op_put_by_id_transition_direct: {
-            printPutByIdOp(out, exec, location, it, &quot;put_by_id_transition_direct&quot;);
-            printPutByIdCacheStatus(out, exec, location, stubInfos);
-            break;
-        }
-        case op_put_by_id_transition_direct_out_of_line: {
-            printPutByIdOp(out, exec, location, it, &quot;put_by_id_transition_direct_out_of_line&quot;);
-            printPutByIdCacheStatus(out, exec, location, stubInfos);
-            break;
-        }
-        case op_put_by_id_transition_normal: {
-            printPutByIdOp(out, exec, location, it, &quot;put_by_id_transition_normal&quot;);
-            printPutByIdCacheStatus(out, exec, location, stubInfos);
-            break;
-        }
-        case op_put_by_id_transition_normal_out_of_line: {
-            printPutByIdOp(out, exec, location, it, &quot;put_by_id_transition_normal_out_of_line&quot;);
-            printPutByIdCacheStatus(out, exec, location, stubInfos);
-            break;
-        }
</del><span class="cx">         case op_put_getter_by_id: {
</span><span class="cx">             int r0 = (++it)-&gt;u.operand;
</span><span class="cx">             int id0 = (++it)-&gt;u.operand;
</span><span class="lines">@@ -1936,7 +1897,6 @@
</span><span class="cx">             instructions[i + opLength - 1] = profile;
</span><span class="cx">             break;
</span><span class="cx">         }
</span><del>-        case op_get_by_id_out_of_line:
</del><span class="cx">         case op_get_array_length:
</span><span class="cx">             CRASH();
</span><span class="cx"> 
</span><span class="lines">@@ -2417,12 +2377,17 @@
</span><span class="cx">         for (size_t i = 0; i &lt; propertyAccessInstructions.size(); ++i) {
</span><span class="cx">             Instruction* instruction = &amp;instructions()[propertyAccessInstructions[i]];
</span><span class="cx">             switch (interpreter-&gt;getOpcodeID(instruction[0].u.opcode)) {
</span><del>-            case op_put_by_id_transition_direct:
-            case op_put_by_id_transition_normal:
-            case op_put_by_id_transition_direct_out_of_line:
-            case op_put_by_id_transition_normal_out_of_line: {
-                if (Heap::isMarked(instruction[4].u.structure.get()))
-                    visitor.append(&amp;instruction[6].u.structure);
</del><ins>+            case op_put_by_id: {
+                StructureID oldStructureID = instruction[4].u.structureID;
+                StructureID newStructureID = instruction[6].u.structureID;
+                if (!oldStructureID || !newStructureID)
+                    break;
+                Structure* oldStructure =
+                    m_vm-&gt;heap.structureIDTable().get(oldStructureID);
+                Structure* newStructure =
+                    m_vm-&gt;heap.structureIDTable().get(newStructureID);
+                if (Heap::isMarked(oldStructure))
+                    visitor.appendUnbarrieredReadOnlyPointer(newStructure);
</ins><span class="cx">                 else
</span><span class="cx">                     allAreMarkedSoFar = false;
</span><span class="cx">                 break;
</span><span class="lines">@@ -2553,36 +2518,32 @@
</span><span class="cx">     for (size_t size = propertyAccessInstructions.size(), i = 0; i &lt; size; ++i) {
</span><span class="cx">         Instruction* curInstruction = &amp;instructions()[propertyAccessInstructions[i]];
</span><span class="cx">         switch (interpreter-&gt;getOpcodeID(curInstruction[0].u.opcode)) {
</span><del>-        case op_get_by_id:
-        case op_get_by_id_out_of_line:
-        case op_put_by_id:
-        case op_put_by_id_out_of_line:
-            if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get()))
</del><ins>+        case op_get_by_id: {
+            StructureID oldStructureID = curInstruction[4].u.structureID;
+            if (!oldStructureID || Heap::isMarked(m_vm-&gt;heap.structureIDTable().get(oldStructureID)))
</ins><span class="cx">                 break;
</span><span class="cx">             if (Options::verboseOSR())
</span><del>-                dataLogF(&quot;Clearing LLInt property access with structure %p.\n&quot;, curInstruction[4].u.structure.get());
-            curInstruction[4].u.structure.clear();
</del><ins>+                dataLogF(&quot;Clearing LLInt property access.\n&quot;);
+            curInstruction[4].u.structureID = 0;
</ins><span class="cx">             curInstruction[5].u.operand = 0;
</span><span class="cx">             break;
</span><del>-        case op_put_by_id_transition_direct:
-        case op_put_by_id_transition_normal:
-        case op_put_by_id_transition_direct_out_of_line:
-        case op_put_by_id_transition_normal_out_of_line:
-            if (Heap::isMarked(curInstruction[4].u.structure.get())
-                &amp;&amp; Heap::isMarked(curInstruction[6].u.structure.get())
-                &amp;&amp; Heap::isMarked(curInstruction[7].u.structureChain.get()))
</del><ins>+        }
+        case op_put_by_id: {
+            StructureID oldStructureID = curInstruction[4].u.structureID;
+            StructureID newStructureID = curInstruction[6].u.structureID;
+            StructureChain* chain = curInstruction[7].u.structureChain.get();
+            if ((!oldStructureID || Heap::isMarked(m_vm-&gt;heap.structureIDTable().get(oldStructureID))) &amp;&amp;
+                (!newStructureID || Heap::isMarked(m_vm-&gt;heap.structureIDTable().get(newStructureID))) &amp;&amp;
+                (!chain || Heap::isMarked(chain)))
</ins><span class="cx">                 break;
</span><del>-            if (Options::verboseOSR()) {
-                dataLogF(&quot;Clearing LLInt put transition with structures %p -&gt; %p, chain %p.\n&quot;,
-                    curInstruction[4].u.structure.get(),
-                    curInstruction[6].u.structure.get(),
-                    curInstruction[7].u.structureChain.get());
-            }
-            curInstruction[4].u.structure.clear();
-            curInstruction[6].u.structure.clear();
</del><ins>+            if (Options::verboseOSR())
+                dataLogF(&quot;Clearing LLInt put transition.\n&quot;);
+            curInstruction[4].u.structureID = 0;
+            curInstruction[5].u.operand = 0;
+            curInstruction[6].u.structureID = 0;
</ins><span class="cx">             curInstruction[7].u.structureChain.clear();
</span><del>-            curInstruction[0].u.opcode = interpreter-&gt;getOpcode(op_put_by_id);
</del><span class="cx">             break;
</span><ins>+        }
</ins><span class="cx">         case op_get_array_length:
</span><span class="cx">             break;
</span><span class="cx">         case op_to_this:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -969,7 +969,7 @@
</span><span class="cx">     enum CacheDumpMode { DumpCaches, DontDumpCaches };
</span><span class="cx">     void printCallOp(PrintStream&amp;, ExecState*, int location, const Instruction*&amp;, const char* op, CacheDumpMode, bool&amp; hasPrintedProfiling, const CallLinkInfoMap&amp;);
</span><span class="cx">     void printPutByIdOp(PrintStream&amp;, ExecState*, int location, const Instruction*&amp;, const char* op);
</span><del>-    void printPutByIdCacheStatus(PrintStream&amp;, ExecState*, int location, const StubInfoMap&amp;);
</del><ins>+    void printPutByIdCacheStatus(PrintStream&amp;, int location, const StubInfoMap&amp;);
</ins><span class="cx">     void printLocationAndOp(PrintStream&amp;, ExecState*, int location, const Instruction*&amp;, const char* op);
</span><span class="cx">     void printLocationOpAndRegisterOperand(PrintStream&amp;, ExecState*, int location, const Instruction*&amp; it, const char* op, int operand);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeGetByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -70,15 +70,20 @@
</span><span class="cx">     UNUSED_PARAM(profiledBlock);
</span><span class="cx">     UNUSED_PARAM(bytecodeIndex);
</span><span class="cx">     UNUSED_PARAM(uid);
</span><ins>+
+    VM&amp; vm = *profiledBlock-&gt;vm();
+    
</ins><span class="cx">     Instruction* instruction = profiledBlock-&gt;instructions().begin() + bytecodeIndex;
</span><span class="cx">     
</span><span class="cx">     if (instruction[0].u.opcode == LLInt::getOpcode(op_get_array_length))
</span><span class="cx">         return GetByIdStatus(NoInformation, false);
</span><span class="cx"> 
</span><del>-    Structure* structure = instruction[4].u.structure.get();
-    if (!structure)
</del><ins>+    StructureID structureID = instruction[4].u.structureID;
+    if (!structureID)
</ins><span class="cx">         return GetByIdStatus(NoInformation, false);
</span><span class="cx"> 
</span><ins>+    Structure* structure = vm.heap.structureIDTable().get(structureID);
+
</ins><span class="cx">     if (structure-&gt;takesSlowPathInDFGForImpureProperty())
</span><span class="cx">         return GetByIdStatus(NoInformation, false);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeInstructionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/Instruction.h (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/Instruction.h        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/bytecode/Instruction.h        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;BasicBlockLocation.h&quot;
</span><span class="cx"> #include &quot;MacroAssembler.h&quot;
</span><span class="cx"> #include &quot;Opcode.h&quot;
</span><ins>+#include &quot;PutByIdFlags.h&quot;
</ins><span class="cx"> #include &quot;SymbolTable.h&quot;
</span><span class="cx"> #include &quot;TypeLocation.h&quot;
</span><span class="cx"> #include &quot;PropertySlot.h&quot;
</span><span class="lines">@@ -75,6 +76,11 @@
</span><span class="cx">         u.operand = operand;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Instruction(PutByIdFlags flags)
+    {
+        u.putByIdFlags = flags;
+    }
+
</ins><span class="cx">     Instruction(VM&amp; vm, JSCell* owner, Structure* structure)
</span><span class="cx">     {
</span><span class="cx">         u.structure.clear();
</span><span class="lines">@@ -107,6 +113,7 @@
</span><span class="cx">         Opcode opcode;
</span><span class="cx">         int operand;
</span><span class="cx">         WriteBarrierBase&lt;Structure&gt; structure;
</span><ins>+        StructureID structureID;
</ins><span class="cx">         WriteBarrierBase&lt;SymbolTable&gt; symbolTable;
</span><span class="cx">         WriteBarrierBase&lt;StructureChain&gt; structureChain;
</span><span class="cx">         WriteBarrierBase&lt;JSCell&gt; jsCell;
</span><span class="lines">@@ -125,6 +132,7 @@
</span><span class="cx">         ToThisStatus toThisStatus;
</span><span class="cx">         TypeLocation* location;
</span><span class="cx">         BasicBlockLocation* basicBlockLocation;
</span><ins>+        PutByIdFlags putByIdFlags;
</ins><span class="cx">     } u;
</span><span class="cx">         
</span><span class="cx"> private:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePutByIdFlagscpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.cpp (0 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.cpp        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;PutByIdFlags.h&quot;
+
+#include &lt;wtf/CommaPrinter.h&gt;
+#include &lt;wtf/PrintStream.h&gt;
+#include &lt;wtf/StringPrintStream.h&gt;
+
+namespace WTF {
+
+using namespace JSC;
+
+void printInternal(PrintStream&amp; out, PutByIdFlags flags) {
+    StringPrintStream stringOut;
+    CommaPrinter comma(&quot;|&quot;);
+    if (flags &amp; PutByIdIsDirect)
+        stringOut.print(comma, &quot;IsDirect&quot;);
+
+    CString string = stringOut.toCString();
+    if (!string.length())
+        out.print(&quot;None&quot;);
+    else
+        out.print(string);
+}
+
+} // namespace WTF
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePutByIdFlagsh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.h (0 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.h        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -0,0 +1,47 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * 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. 
+ */
+
+#ifndef PutByIdFlags_h
+#define PutByIdFlags_h
+
+namespace JSC {
+
+enum PutByIdFlags {
+    PutByIdNone = 0,
+    PutByIdIsDirect = 1
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+class PrintStream;
+
+void printInternal(PrintStream&amp;, JSC::PutByIdFlags);
+
+} // namespace WTF
+
+#endif // PutByIdFlags_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePutByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -66,37 +66,36 @@
</span><span class="cx">     UNUSED_PARAM(profiledBlock);
</span><span class="cx">     UNUSED_PARAM(bytecodeIndex);
</span><span class="cx">     UNUSED_PARAM(uid);
</span><ins>+
+    VM&amp; vm = *profiledBlock-&gt;vm();
+    
</ins><span class="cx">     Instruction* instruction = profiledBlock-&gt;instructions().begin() + bytecodeIndex;
</span><span class="cx"> 
</span><del>-    Structure* structure = instruction[4].u.structure.get();
-    if (!structure)
</del><ins>+    StructureID structureID = instruction[4].u.structureID;
+    if (!structureID)
</ins><span class="cx">         return PutByIdStatus(NoInformation);
</span><span class="cx">     
</span><del>-    if (instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id)
-        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_out_of_line)) {
</del><ins>+    Structure* structure = vm.heap.structureIDTable().get(structureID);
+
+    StructureID newStructureID = instruction[6].u.structureID;
+    if (!newStructureID) {
</ins><span class="cx">         PropertyOffset offset = structure-&gt;getConcurrently(uid);
</span><span class="cx">         if (!isValidOffset(offset))
</span><span class="cx">             return PutByIdStatus(NoInformation);
</span><span class="cx">         
</span><span class="cx">         return PutByIdVariant::replace(structure, offset);
</span><span class="cx">     }
</span><ins>+
+    Structure* newStructure = vm.heap.structureIDTable().get(newStructureID);
</ins><span class="cx">     
</span><span class="cx">     ASSERT(structure-&gt;transitionWatchpointSetHasBeenInvalidated());
</span><span class="cx">     
</span><del>-    ASSERT(instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_direct)
-        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_normal)
-        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_direct_out_of_line)
-        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line));
-    
-    Structure* newStructure = instruction[6].u.structure.get();
-    
</del><span class="cx">     PropertyOffset offset = newStructure-&gt;getConcurrently(uid);
</span><span class="cx">     if (!isValidOffset(offset))
</span><span class="cx">         return PutByIdStatus(NoInformation);
</span><span class="cx">     
</span><span class="cx">     ObjectPropertyConditionSet conditionSet;
</span><del>-    if (instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_normal)
-        || instruction[0].u.opcode == LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line)) {
</del><ins>+    if (!(instruction[8].u.putByIdFlags &amp; PutByIdIsDirect)) {
</ins><span class="cx">         conditionSet =
</span><span class="cx">             generateConditionsForPropertySetterMissConcurrently(
</span><span class="cx">                 *profiledBlock-&gt;vm(), profiledBlock-&gt;globalObject(), structure, uid);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #include &quot;JSCell.h&quot;
</span><span class="cx"> #include &quot;JSString.h&quot;
</span><span class="cx"> #include &quot;ParserModes.h&quot;
</span><ins>+#include &quot;PutByIdFlags.h&quot;
</ins><span class="cx"> #include &quot;RegExp.h&quot;
</span><span class="cx"> #include &quot;SpecialPointer.h&quot;
</span><span class="cx"> #include &quot;UnlinkedFunctionExecutable.h&quot;
</span><span class="lines">@@ -97,10 +98,12 @@
</span><span class="cx">     UnlinkedInstruction() { u.operand = 0; }
</span><span class="cx">     UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
</span><span class="cx">     UnlinkedInstruction(int operand) { u.operand = operand; }
</span><ins>+    UnlinkedInstruction(PutByIdFlags flags) { u.putByIdFlags = flags; }
</ins><span class="cx">     union {
</span><span class="cx">         OpcodeID opcode;
</span><span class="cx">         int32_t operand;
</span><span class="cx">         unsigned index;
</span><ins>+        PutByIdFlags putByIdFlags;
</ins><span class="cx">     } u;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -2103,11 +2103,11 @@
</span><span class="cx">     instructions().append(base-&gt;index());
</span><span class="cx">     instructions().append(propertyIndex);
</span><span class="cx">     instructions().append(value-&gt;index());
</span><del>-    instructions().append(0);
-    instructions().append(0);
-    instructions().append(0);
-    instructions().append(0);
-    instructions().append(0);
</del><ins>+    instructions().append(0); // old structure
+    instructions().append(0); // offset
+    instructions().append(0); // new structure
+    instructions().append(0); // structure chain
+    instructions().append(PutByIdNone); // is not direct
</ins><span class="cx"> 
</span><span class="cx">     return value;
</span><span class="cx"> }
</span><span class="lines">@@ -2125,11 +2125,11 @@
</span><span class="cx">     instructions().append(base-&gt;index());
</span><span class="cx">     instructions().append(propertyIndex);
</span><span class="cx">     instructions().append(value-&gt;index());
</span><del>-    instructions().append(0);
-    instructions().append(0);
-    instructions().append(0);
-    instructions().append(0);
-    instructions().append(putType == PropertyNode::KnownDirect || property != m_vm-&gt;propertyNames-&gt;underscoreProto);
</del><ins>+    instructions().append(0); // old structure
+    instructions().append(0); // offset
+    instructions().append(0); // new structure
+    instructions().append(0); // structure chain (unused if direct)
+    instructions().append((putType == PropertyNode::KnownDirect || property != m_vm-&gt;propertyNames-&gt;underscoreProto) ? PutByIdIsDirect : PutByIdNone);
</ins><span class="cx">     return value;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;JSModuleEnvironment.h&quot;
</span><span class="cx"> #include &quot;PreciseJumpTargets.h&quot;
</span><ins>+#include &quot;PutByIdFlags.h&quot;
</ins><span class="cx"> #include &quot;PutByIdStatus.h&quot;
</span><span class="cx"> #include &quot;StackAlignment.h&quot;
</span><span class="cx"> #include &quot;StringConstructor.h&quot;
</span><span class="lines">@@ -3513,7 +3514,6 @@
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case op_get_by_id:
</span><del>-        case op_get_by_id_out_of_line:
</del><span class="cx">         case op_get_array_length: {
</span><span class="cx">             SpeculatedType prediction = getPrediction();
</span><span class="cx">             
</span><span class="lines">@@ -3531,16 +3531,11 @@
</span><span class="cx"> 
</span><span class="cx">             NEXT_OPCODE(op_get_by_id);
</span><span class="cx">         }
</span><del>-        case op_put_by_id:
-        case op_put_by_id_out_of_line:
-        case op_put_by_id_transition_direct:
-        case op_put_by_id_transition_normal:
-        case op_put_by_id_transition_direct_out_of_line:
-        case op_put_by_id_transition_normal_out_of_line: {
</del><ins>+        case op_put_by_id: {
</ins><span class="cx">             Node* value = get(VirtualRegister(currentInstruction[3].u.operand));
</span><span class="cx">             Node* base = get(VirtualRegister(currentInstruction[1].u.operand));
</span><span class="cx">             unsigned identifierNumber = m_inlineStackTop-&gt;m_identifierRemap[currentInstruction[2].u.operand];
</span><del>-            bool direct = currentInstruction[8].u.operand;
</del><ins>+            bool direct = currentInstruction[8].u.putByIdFlags &amp; PutByIdIsDirect;
</ins><span class="cx"> 
</span><span class="cx">             PutByIdStatus putByIdStatus = PutByIdStatus::computeFor(
</span><span class="cx">                 m_inlineStackTop-&gt;m_profiledBlock, m_dfgCodeBlock,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -152,14 +152,8 @@
</span><span class="cx">     case op_put_by_val:
</span><span class="cx">     case op_put_by_val_direct:
</span><span class="cx">     case op_get_by_id:
</span><del>-    case op_get_by_id_out_of_line:
</del><span class="cx">     case op_get_array_length:
</span><span class="cx">     case op_put_by_id:
</span><del>-    case op_put_by_id_out_of_line:
-    case op_put_by_id_transition_direct:
-    case op_put_by_id_transition_direct_out_of_line:
-    case op_put_by_id_transition_normal:
-    case op_put_by_id_transition_normal_out_of_line:
</del><span class="cx">     case op_jmp:
</span><span class="cx">     case op_jtrue:
</span><span class="cx">     case op_jfalse:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -217,7 +217,6 @@
</span><span class="cx">         DEFINE_OP(op_load_arrowfunction_this)
</span><span class="cx">         DEFINE_OP(op_eq)
</span><span class="cx">         DEFINE_OP(op_eq_null)
</span><del>-        case op_get_by_id_out_of_line:
</del><span class="cx">         case op_get_array_length:
</span><span class="cx">         DEFINE_OP(op_get_by_id)
</span><span class="cx">         DEFINE_OP(op_get_by_val)
</span><span class="lines">@@ -269,11 +268,6 @@
</span><span class="cx">         DEFINE_OP(op_push_with_scope)
</span><span class="cx">         DEFINE_OP(op_create_lexical_environment)
</span><span class="cx">         DEFINE_OP(op_get_parent_scope)
</span><del>-        case op_put_by_id_out_of_line:
-        case op_put_by_id_transition_direct:
-        case op_put_by_id_transition_normal:
-        case op_put_by_id_transition_direct_out_of_line:
-        case op_put_by_id_transition_normal_out_of_line:
</del><span class="cx">         DEFINE_OP(op_put_by_id)
</span><span class="cx">         DEFINE_OP(op_put_by_index)
</span><span class="cx">         case op_put_by_val_direct:
</span><span class="lines">@@ -386,7 +380,6 @@
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_create_this)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_div)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_eq)
</span><del>-        case op_get_by_id_out_of_line:
</del><span class="cx">         case op_get_array_length:
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_get_by_id)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_get_by_val)
</span><span class="lines">@@ -413,11 +406,6 @@
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_nstricteq)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_dec)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_inc)
</span><del>-        case op_put_by_id_out_of_line:
-        case op_put_by_id_transition_direct:
-        case op_put_by_id_transition_normal:
-        case op_put_by_id_transition_direct_out_of_line:
-        case op_put_by_id_transition_normal_out_of_line:
</del><span class="cx">         DEFINE_SLOWCASE_OP(op_put_by_id)
</span><span class="cx">         case op_put_by_val_direct:
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_put_by_val)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -607,7 +607,7 @@
</span><span class="cx"> {
</span><span class="cx">     int baseVReg = currentInstruction[1].u.operand;
</span><span class="cx">     int valueVReg = currentInstruction[3].u.operand;
</span><del>-    unsigned direct = currentInstruction[8].u.operand;
</del><ins>+    unsigned direct = currentInstruction[8].u.putByIdFlags &amp; PutByIdIsDirect;
</ins><span class="cx"> 
</span><span class="cx">     emitWriteBarrier(baseVReg, valueVReg, ShouldFilterBase);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccess32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -623,7 +623,7 @@
</span><span class="cx">     
</span><span class="cx">     int base = currentInstruction[1].u.operand;
</span><span class="cx">     int value = currentInstruction[3].u.operand;
</span><del>-    int direct = currentInstruction[8].u.operand;
</del><ins>+    int direct = currentInstruction[8].u.putByIdFlags &amp; PutByIdIsDirect;
</ins><span class="cx">     
</span><span class="cx">     emitWriteBarrier(base, value, ShouldFilterBase);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -570,20 +570,20 @@
</span><span class="cx">         JSCell* baseCell = baseValue.asCell();
</span><span class="cx">         Structure* structure = baseCell-&gt;structure();
</span><span class="cx">         
</span><ins>+        // Start out by clearing out the old cache.
+        pc[0].u.opcode = LLInt::getOpcode(op_get_by_id);
+        pc[4].u.pointer = nullptr; // old structure
+        pc[5].u.pointer = nullptr; // offset
+        
</ins><span class="cx">         if (!structure-&gt;isUncacheableDictionary()
</span><span class="cx">             &amp;&amp; !structure-&gt;typeInfo().prohibitsPropertyCaching()
</span><span class="cx">             &amp;&amp; !structure-&gt;typeInfo().newImpurePropertyFiresWatchpoints()) {
</span><ins>+            vm.heap.writeBarrier(codeBlock-&gt;ownerExecutable());
+            
</ins><span class="cx">             ConcurrentJITLocker locker(codeBlock-&gt;m_lock);
</span><span class="cx"> 
</span><del>-            pc[4].u.structure.set(
-                vm, codeBlock-&gt;ownerExecutable(), structure);
-            if (isInlineOffset(slot.cachedOffset())) {
-                pc[0].u.opcode = LLInt::getOpcode(op_get_by_id);
-                pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
-            } else {
-                pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_out_of_line);
-                pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
-            }
</del><ins>+            pc[4].u.structureID = structure-&gt;id();
+            pc[5].u.operand = slot.cachedOffset();
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -618,7 +618,7 @@
</span><span class="cx">     
</span><span class="cx">     JSValue baseValue = LLINT_OP_C(1).jsValue();
</span><span class="cx">     PutPropertySlot slot(baseValue, codeBlock-&gt;isStrictMode(), codeBlock-&gt;putByIdContext());
</span><del>-    if (pc[8].u.operand)
</del><ins>+    if (pc[8].u.putByIdFlags &amp; PutByIdIsDirect)
</ins><span class="cx">         asObject(baseValue)-&gt;putDirect(vm, ident, LLINT_OP_C(3).jsValue(), slot);
</span><span class="cx">     else
</span><span class="cx">         baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot);
</span><span class="lines">@@ -627,6 +627,12 @@
</span><span class="cx">     if (!LLINT_ALWAYS_ACCESS_SLOW
</span><span class="cx">         &amp;&amp; baseValue.isCell()
</span><span class="cx">         &amp;&amp; slot.isCacheablePut()) {
</span><ins>+
+        // Start out by clearing out the old cache.
+        pc[4].u.pointer = nullptr; // old structure
+        pc[5].u.pointer = nullptr; // offset
+        pc[6].u.pointer = nullptr; // new structure
+        pc[7].u.pointer = nullptr; // structure chain
</ins><span class="cx">         
</span><span class="cx">         JSCell* baseCell = baseValue.asCell();
</span><span class="cx">         Structure* structure = baseCell-&gt;structure();
</span><span class="lines">@@ -634,56 +640,32 @@
</span><span class="cx">         if (!structure-&gt;isUncacheableDictionary()
</span><span class="cx">             &amp;&amp; !structure-&gt;typeInfo().prohibitsPropertyCaching()
</span><span class="cx">             &amp;&amp; baseCell == slot.base()) {
</span><ins>+
+            vm.heap.writeBarrier(codeBlock-&gt;ownerExecutable());
</ins><span class="cx">             
</span><span class="cx">             if (slot.type() == PutPropertySlot::NewProperty) {
</span><span class="cx">                 GCSafeConcurrentJITLocker locker(codeBlock-&gt;m_lock, vm.heap);
</span><span class="cx">             
</span><span class="cx">                 if (!structure-&gt;isDictionary() &amp;&amp; structure-&gt;previousID()-&gt;outOfLineCapacity() == structure-&gt;outOfLineCapacity()) {
</span><span class="cx">                     ASSERT(structure-&gt;previousID()-&gt;transitionWatchpointSetHasBeenInvalidated());
</span><del>-                    
-                    // This is needed because some of the methods we call
-                    // below may GC.
-                    pc[0].u.opcode = LLInt::getOpcode(op_put_by_id);
</del><span class="cx"> 
</span><span class="cx">                     if (normalizePrototypeChain(exec, structure) != InvalidPrototypeChain) {
</span><span class="cx">                         ASSERT(structure-&gt;previousID()-&gt;isObject());
</span><del>-                        pc[4].u.structure.set(
-                            vm, codeBlock-&gt;ownerExecutable(), structure-&gt;previousID());
-                        if (isInlineOffset(slot.cachedOffset()))
-                            pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
-                        else
-                            pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
-                        pc[6].u.structure.set(
-                            vm, codeBlock-&gt;ownerExecutable(), structure);
-                        StructureChain* chain = structure-&gt;prototypeChain(exec);
-                        ASSERT(chain);
-                        pc[7].u.structureChain.set(
-                            vm, codeBlock-&gt;ownerExecutable(), chain);
-                    
-                        if (pc[8].u.operand) {
-                            if (isInlineOffset(slot.cachedOffset()))
-                                pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_direct);
-                            else
-                                pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_direct_out_of_line);
-                        } else {
-                            if (isInlineOffset(slot.cachedOffset()))
-                                pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_normal);
-                            else
-                                pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line);
</del><ins>+                        pc[4].u.structureID = structure-&gt;previousID()-&gt;id();
+                        pc[5].u.operand = slot.cachedOffset();
+                        pc[6].u.structureID = structure-&gt;id();
+                        if (!(pc[8].u.putByIdFlags &amp; PutByIdIsDirect)) {
+                            StructureChain* chain = structure-&gt;prototypeChain(exec);
+                            ASSERT(chain);
+                            pc[7].u.structureChain.set(
+                                vm, codeBlock-&gt;ownerExecutable(), chain);
</ins><span class="cx">                         }
</span><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="cx">             } else {
</span><span class="cx">                 structure-&gt;didCachePropertyReplacement(vm, slot.cachedOffset());
</span><del>-                pc[4].u.structure.set(
-                    vm, codeBlock-&gt;ownerExecutable(), structure);
-                if (isInlineOffset(slot.cachedOffset())) {
-                    pc[0].u.opcode = LLInt::getOpcode(op_put_by_id);
-                    pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
-                } else {
-                    pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_out_of_line);
-                    pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
-                }
</del><ins>+                pc[4].u.structureID = structure-&gt;id();
+                pc[5].u.operand = slot.cachedOffset();
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -1323,39 +1323,25 @@
</span><span class="cx"> # to take fast path on the new cache. At worst we take slow path, which is what
</span><span class="cx"> # we would have been doing anyway.
</span><span class="cx"> 
</span><del>-macro getById(getPropertyStorage)
</del><ins>+_llint_op_get_by_id:
</ins><span class="cx">     traceExecution()
</span><span class="cx">     loadi 8[PC], t0
</span><span class="cx">     loadi 16[PC], t1
</span><span class="cx">     loadConstantOrVariablePayload(t0, CellTag, t3, .opGetByIdSlow)
</span><span class="cx">     loadi 20[PC], t2
</span><del>-    getPropertyStorage(
-        t3,
-        t0,
-        macro (propertyStorage, scratch)
-            bpneq JSCell::m_structureID[t3], t1, .opGetByIdSlow
-            loadi 4[PC], t1
-            loadi TagOffset[propertyStorage, t2], scratch
-            loadi PayloadOffset[propertyStorage, t2], t2
-            storei scratch, TagOffset[cfr, t1, 8]
-            storei t2, PayloadOffset[cfr, t1, 8]
-            valueProfile(scratch, t2, 32, t1)
-            dispatch(9)
-        end)
</del><ins>+    bineq JSCell::m_structureID[t3], t1, .opGetByIdSlow
+    loadPropertyAtVariableOffset(t2, t3, t0, t1)
+    loadi 4[PC], t2
+    storei t0, TagOffset[cfr, t2, 8]
+    storei t1, PayloadOffset[cfr, t2, 8]
+    valueProfile(t0, t1, 32, t2)
+    dispatch(9)
</ins><span class="cx"> 
</span><del>-    .opGetByIdSlow:
-        callSlowPath(_llint_slow_path_get_by_id)
-        dispatch(9)
-end
</del><ins>+.opGetByIdSlow:
+    callSlowPath(_llint_slow_path_get_by_id)
+    dispatch(9)
</ins><span class="cx"> 
</span><del>-_llint_op_get_by_id:
-    getById(withInlineStorage)
</del><span class="cx"> 
</span><del>-
-_llint_op_get_by_id_out_of_line:
-    getById(withOutOfLineStorage)
-
-
</del><span class="cx"> _llint_op_get_array_length:
</span><span class="cx">     traceExecution()
</span><span class="cx">     loadi 8[PC], t0
</span><span class="lines">@@ -1379,102 +1365,59 @@
</span><span class="cx">     dispatch(9)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-macro putById(getPropertyStorage)
</del><ins>+_llint_op_put_by_id:
</ins><span class="cx">     traceExecution()
</span><span class="cx">     writeBarrierOnOperands(1, 3)
</span><span class="cx">     loadi 4[PC], t3
</span><del>-    loadi 16[PC], t1
</del><span class="cx">     loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
</span><del>-    loadi 12[PC], t2
-    getPropertyStorage(
-        t0,
-        t3,
-        macro (propertyStorage, scratch)
-            bpneq JSCell::m_structureID[t0], t1, .opPutByIdSlow
-            loadi 20[PC], t1
-            loadConstantOrVariable2Reg(t2, scratch, t2)
-            storei scratch, TagOffset[propertyStorage, t1]
-            storei t2, PayloadOffset[propertyStorage, t1]
-            dispatch(9)
-        end)
</del><ins>+    loadi JSCell::m_structureID[t0], t2
+    bineq t2, 16[PC], .opPutByIdSlow
</ins><span class="cx"> 
</span><del>-    .opPutByIdSlow:
-        callSlowPath(_llint_slow_path_put_by_id)
-        dispatch(9)
-end
</del><ins>+    # At this point, we have:
+    # t2 -&gt; currentStructureID
+    # t0 -&gt; object base
</ins><span class="cx"> 
</span><del>-_llint_op_put_by_id:
-    putById(withInlineStorage)
</del><ins>+    loadi 24[PC], t1
</ins><span class="cx"> 
</span><ins>+    btiz t1, .opPutByIdNotTransition
</ins><span class="cx"> 
</span><del>-_llint_op_put_by_id_out_of_line:
-    putById(withOutOfLineStorage)
</del><ins>+    # This is the transition case. t1 holds the new Structure*. t2 holds the old Structure*.
+    # If we have a chain, we need to check it. t0 is the base. We may clobber t1 to use it as
+    # scratch.
+    loadp 28[PC], t3
+    btpz t3, .opPutByIdTransitionDirect
</ins><span class="cx"> 
</span><ins>+    loadp StructureChain::m_vector[t3], t3
+    assert(macro (ok) btpnz t3, ok end)
</ins><span class="cx"> 
</span><del>-macro putByIdTransition(additionalChecks, getPropertyStorage)
-    traceExecution()
-    writeBarrierOnOperand(1)
-    loadi 4[PC], t3
-    loadi 16[PC], t1
-    loadConstantOrVariablePayload(t3, CellTag, t0, .opPutByIdSlow)
-    loadi 12[PC], t2
-    bpneq JSCell::m_structureID[t0], t1, .opPutByIdSlow
-    additionalChecks(t1, t3, .opPutByIdSlow)
-    loadi 20[PC], t1
-    getPropertyStorage(
-        t0,
-        t3,
-        macro (propertyStorage, scratch)
-            addp t1, propertyStorage, t3
-            loadConstantOrVariable2Reg(t2, t1, t2)
-            storei t1, TagOffset[t3]
-            loadi 24[PC], t1
-            storei t2, PayloadOffset[t3]
-            storep t1, JSCell::m_structureID[t0]
-            dispatch(9)
-        end)
</del><ins>+    loadp Structure::m_prototype[t2], t2
+    btpz t2, .opPutByIdTransitionChainDone
+.opPutByIdTransitionChainLoop:
+    loadp [t3], t1
+    bpneq t1, JSCell::m_structureID[t2], .opPutByIdSlow
+    addp 4, t3
+    loadp Structure::m_prototype[t1], t2
+    btpnz t2, .opPutByIdTransitionChainLoop
</ins><span class="cx"> 
</span><del>-    .opPutByIdSlow:
-        callSlowPath(_llint_slow_path_put_by_id)
-        dispatch(9)
-end
</del><ins>+.opPutByIdTransitionChainDone:
+    loadi 24[PC], t1
</ins><span class="cx"> 
</span><del>-macro noAdditionalChecks(oldStructure, scratch, slowPath)
-end
</del><ins>+.opPutByIdTransitionDirect:
+    storei t1, JSCell::m_structureID[t0]
</ins><span class="cx"> 
</span><del>-macro structureChainChecks(oldStructure, scratch, slowPath)
-    const protoCell = oldStructure   # Reusing the oldStructure register for the proto
</del><ins>+.opPutByIdNotTransition:
+    # The only thing live right now is t0, which holds the base.
+    loadi 12[PC], t1
+    loadConstantOrVariable(t1, t2, t3)
+    loadi 20[PC], t1
+    storePropertyAtVariableOffset(t1, t0, t2, t3)
+    dispatch(9)
</ins><span class="cx"> 
</span><del>-    loadp 28[PC], scratch
-    assert(macro (ok) btpnz scratch, ok end)
-    loadp StructureChain::m_vector[scratch], scratch
-    assert(macro (ok) btpnz scratch, ok end)
-    bieq Structure::m_prototype + TagOffset[oldStructure], NullTag, .done
-.loop:
-    loadi Structure::m_prototype + PayloadOffset[oldStructure], protoCell
-    loadp JSCell::m_structureID[protoCell], oldStructure
-    bpneq oldStructure, [scratch], slowPath
-    addp 4, scratch
-    bineq Structure::m_prototype + TagOffset[oldStructure], NullTag, .loop
-.done:
-end
</del><ins>+.opPutByIdSlow:
+    callSlowPath(_llint_slow_path_put_by_id)
+    dispatch(9)
</ins><span class="cx"> 
</span><del>-_llint_op_put_by_id_transition_direct:
-    putByIdTransition(noAdditionalChecks, withInlineStorage)
</del><span class="cx"> 
</span><del>-
-_llint_op_put_by_id_transition_direct_out_of_line:
-    putByIdTransition(noAdditionalChecks, withOutOfLineStorage)
-
-
-_llint_op_put_by_id_transition_normal:
-    putByIdTransition(structureChainChecks, withInlineStorage)
-
-
-_llint_op_put_by_id_transition_normal_out_of_line:
-    putByIdTransition(structureChainChecks, withOutOfLineStorage)
-
-
</del><span class="cx"> _llint_op_get_by_val:
</span><span class="cx">     traceExecution()
</span><span class="cx">     loadi 8[PC], t2
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (189765 => 189766)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-09-15 00:30:03 UTC (rev 189765)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-09-15 00:55:17 UTC (rev 189766)
</span><span class="lines">@@ -468,15 +468,16 @@
</span><span class="cx">     storeq value, ValueProfile::m_buckets[scratch]
</span><span class="cx"> end
</span><span class="cx"> 
</span><del>-macro loadStructure(cell, structure)
-end
-
-macro loadStructureWithScratch(cell, structure, scratch)
</del><ins>+macro structureIDToStructureWithScratch(structureIDThenStructure, scratch)
</ins><span class="cx">     loadp CodeBlock[cfr], scratch
</span><span class="cx">     loadp CodeBlock::m_vm[scratch], scratch
</span><span class="cx">     loadp VM::heap + Heap::m_structureIDTable + StructureIDTable::m_table[scratch], scratch
</span><ins>+    loadp [scratch, structureIDThenStructure, 8], structureIDThenStructure
+end
+
+macro loadStructureWithScratch(cell, structure, scratch)
</ins><span class="cx">     loadi JSCell::m_structureID[cell], structure
</span><del>-    loadp [scratch, structure, 8], structure
</del><ins>+    structureIDToStructureWithScratch(structure, scratch)
</ins><span class="cx"> end
</span><span class="cx"> 
</span><span class="cx"> macro loadStructureAndClobberFirstArg(cell, structure)
</span><span class="lines">@@ -1204,43 +1205,25 @@
</span><span class="cx">     storeq value, (firstOutOfLineOffset - 2) * 8[objectAndStorage, propertyOffsetAsInt, 8]
</span><span class="cx"> end
</span><span class="cx"> 
</span><del>-macro getById(getPropertyStorage)
</del><ins>+_llint_op_get_by_id:
</ins><span class="cx">     traceExecution()
</span><del>-    # We only do monomorphic get_by_id caching for now, and we do not modify the
-    # opcode. We do, however, allow for the cache to change anytime if fails, since
-    # ping-ponging is free. At best we get lucky and the get_by_id will continue
-    # to take fast path on the new cache. At worst we take slow path, which is what
-    # we would have been doing anyway.
</del><span class="cx">     loadisFromInstruction(2, t0)
</span><span class="cx">     loadConstantOrVariableCell(t0, t3, .opGetByIdSlow)
</span><del>-    loadStructureWithScratch(t3, t2, t1)
-    loadpFromInstruction(4, t1)
-    bpneq t2, t1, .opGetByIdSlow
-    getPropertyStorage(
-        t3,
-        t0,
-        macro (propertyStorage, scratch)
-            loadisFromInstruction(5, t2)
-            loadisFromInstruction(1, t1)
-            loadq [propertyStorage, t2], scratch
-            storeq scratch, [cfr, t1, 8]
-            valueProfile(scratch, 8, t1)
-            dispatch(9)
-        end)
-            
-    .opGetByIdSlow:
-        callSlowPath(_llint_slow_path_get_by_id)
-        dispatch(9)
-end
</del><ins>+    loadi JSCell::m_structureID[t3], t1
+    loadisFromInstruction(4, t2)
+    bineq t2, t1, .opGetByIdSlow
+    loadisFromInstruction(5, t1)
+    loadisFromInstruction(1, t2)
+    loadPropertyAtVariableOffset(t1, t3, t0)
+    storeq t0, [cfr, t2, 8]
+    valueProfile(t0, 8, t1)
+    dispatch(9)
</ins><span class="cx"> 
</span><del>-_llint_op_get_by_id:
-    getById(withInlineStorage)
</del><ins>+.opGetByIdSlow:
+    callSlowPath(_llint_slow_path_get_by_id)
+    dispatch(9)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><del>-_llint_op_get_by_id_out_of_line:
-    getById(withOutOfLineStorage)
-
-
</del><span class="cx"> _llint_op_get_array_length:
</span><span class="cx">     traceExecution()
</span><span class="cx">     loadisFromInstruction(2, t0)
</span><span class="lines">@@ -1264,99 +1247,67 @@
</span><span class="cx">     dispatch(9)
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-macro putById(getPropertyStorage)
</del><ins>+_llint_op_put_by_id:
</ins><span class="cx">     traceExecution()
</span><span class="cx">     writeBarrierOnOperands(1, 3)
</span><span class="cx">     loadisFromInstruction(1, t3)
</span><span class="cx">     loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
</span><del>-    loadStructureWithScratch(t0, t2, t1)
-    loadpFromInstruction(4, t1)
-    bpneq t2, t1, .opPutByIdSlow
-    getPropertyStorage(
-        t0,
-        t3,
-        macro (propertyStorage, scratch)
-            loadisFromInstruction(5, t1)
-            loadisFromInstruction(3, t2)
-            loadConstantOrVariable(t2, scratch)
-            storeq scratch, [propertyStorage, t1]
-            dispatch(9)
-        end)
-end
</del><ins>+    loadi JSCell::m_structureID[t0], t2
+    loadisFromInstruction(4, t1)
+    bineq t2, t1, .opPutByIdSlow
</ins><span class="cx"> 
</span><del>-_llint_op_put_by_id:
-    putById(withInlineStorage)
</del><ins>+    # At this point, we have:
+    # t1, t2 -&gt; current structure ID
+    # t0 -&gt; object base
</ins><span class="cx"> 
</span><del>-.opPutByIdSlow:
-    callSlowPath(_llint_slow_path_put_by_id)
-    dispatch(9)
</del><ins>+    loadisFromInstruction(6, t1)
+    
+    btiz t1, .opPutByIdNotTransition
</ins><span class="cx"> 
</span><ins>+    # This is the transition case. t1 holds the new structureID. t2 holds the old structure ID.
+    # If we have a chain, we need to check it. t0 is the base. We may clobber t1 to use it as
+    # scratch.
+    loadpFromInstruction(7, t3)
+    btpz t3, .opPutByIdTransitionDirect
</ins><span class="cx"> 
</span><del>-_llint_op_put_by_id_out_of_line:
-    putById(withOutOfLineStorage)
</del><ins>+    loadp StructureChain::m_vector[t3], t3
+    assert(macro (ok) btpnz t3, ok end)
</ins><span class="cx"> 
</span><ins>+    structureIDToStructureWithScratch(t2, t1)
+    loadq Structure::m_prototype[t2], t2
+    bqeq t2, ValueNull, .opPutByIdTransitionChainDone
+.opPutByIdTransitionChainLoop:
+    # At this point, t2 contains a prototye, and [t3] contains the Structure* that we want that
+    # prototype to have. We don't want to have to load the Structure* for t2. Instead, we load
+    # the Structure* from [t3], and then we compare its id to the id in the header of t2.
+    loadp [t3], t1
+    loadi JSCell::m_structureID[t2], t2
+    # Now, t1 has the Structure* and t2 has the StructureID that we want that Structure* to have.
+    bineq t2, Structure::m_blob + StructureIDBlob::u.fields.structureID[t1], .opPutByIdSlow
+    addp 8, t3
+    loadq Structure::m_prototype[t1], t2
+    bqneq t2, ValueNull, .opPutByIdTransitionChainLoop
</ins><span class="cx"> 
</span><del>-macro putByIdTransition(additionalChecks, getPropertyStorage)
-    traceExecution()
-    writeBarrierOnOperand(1)
-    loadisFromInstruction(1, t3)
-    loadpFromInstruction(4, t1)
-    loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
-    loadStructureWithScratch(t0, t2, t3)
-    bpneq t2, t1, .opPutByIdSlow
-    additionalChecks(t1, t3, t2)
-    loadisFromInstruction(3, t2)
-    loadisFromInstruction(5, t1)
-    getPropertyStorage(
-        t0,
-        t3,
-        macro (propertyStorage, scratch)
-            addp t1, propertyStorage, t3
-            loadConstantOrVariable(t2, t1)
-            storeq t1, [t3]
-            loadpFromInstruction(6, t1)
-            loadi Structure::m_blob + StructureIDBlob::u.words.word1[t1], t1
-            storei t1, JSCell::m_structureID[t0]
-            dispatch(9)
-        end)
-end
</del><ins>+.opPutByIdTransitionChainDone:
+    # Reload the new structure, since we clobbered it above.
+    loadisFromInstruction(6, t1)
</ins><span class="cx"> 
</span><del>-macro noAdditionalChecks(oldStructure, scratch, scratch2)
-end
</del><ins>+.opPutByIdTransitionDirect:
+    storei t1, JSCell::m_structureID[t0]
</ins><span class="cx"> 
</span><del>-macro structureChainChecks(oldStructure, scratch, scratch2)
-    const protoCell = oldStructure    # Reusing the oldStructure register for the proto
-    loadpFromInstruction(7, scratch)
-    assert(macro (ok) btpnz scratch, ok end)
-    loadp StructureChain::m_vector[scratch], scratch
-    assert(macro (ok) btpnz scratch, ok end)
-    bqeq Structure::m_prototype[oldStructure], ValueNull, .done
-.loop:
-    loadq Structure::m_prototype[oldStructure], protoCell
-    loadStructureAndClobberFirstArg(protoCell, scratch2)
-    move scratch2, oldStructure
-    bpneq oldStructure, [scratch], .opPutByIdSlow
-    addp 8, scratch
-    bqneq Structure::m_prototype[oldStructure], ValueNull, .loop
-.done:
-end
</del><ins>+.opPutByIdNotTransition:
+    # The only thing live right now is t0, which holds the base.
+    loadisFromInstruction(3, t1)
+    loadConstantOrVariable(t1, t2)
+    loadisFromInstruction(5, t1)
+    storePropertyAtVariableOffset(t1, t0, t2)
+    dispatch(9)
</ins><span class="cx"> 
</span><del>-_llint_op_put_by_id_transition_direct:
-    putByIdTransition(noAdditionalChecks, withInlineStorage)
</del><ins>+.opPutByIdSlow:
+    callSlowPath(_llint_slow_path_put_by_id)
+    dispatch(9)
</ins><span class="cx"> 
</span><span class="cx"> 
</span><del>-_llint_op_put_by_id_transition_direct_out_of_line:
-    putByIdTransition(noAdditionalChecks, withOutOfLineStorage)
-
-
-_llint_op_put_by_id_transition_normal:
-    putByIdTransition(structureChainChecks, withInlineStorage)
-
-
-_llint_op_put_by_id_transition_normal_out_of_line:
-    putByIdTransition(structureChainChecks, withOutOfLineStorage)
-
-
</del><span class="cx"> _llint_op_get_by_val:
</span><span class="cx">     traceExecution()
</span><span class="cx">     loadisFromInstruction(2, t2)
</span></span></pre>
</div>
</div>

</body>
</html>