<!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>[178441] 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/178441">178441</a></dd>
<dt>Author</dt> <dd>mmirman@apple.com</dd>
<dt>Date</dt> <dd>2015-01-14 13:00:52 -0800 (Wed, 14 Jan 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Fixes operationPutByIdOptimizes such that they check that the put didn't
change the structure of the object who's property access is being
cached.  Also removes uses of the new base value from the cache generation code.
https://bugs.webkit.org/show_bug.cgi?id=139500

Reviewed by Filip Pizlo.

* jit/JITOperations.cpp:
(JSC::operationPutByIdStrictOptimize): saved the structure before the put.
(JSC::operationPutByIdNonStrictOptimize): ditto.
(JSC::operationPutByIdDirectStrictOptimize): ditto.
(JSC::operationPutByIdDirectNonStrictOptimize): ditto.
* jit/Repatch.cpp:
(JSC::generateByIdStub):
(JSC::tryCacheGetByID):
(JSC::tryBuildGetByIDList):
(JSC::emitPutReplaceStub):
(JSC::emitPutTransitionStubAndGetOldStructure): Added.
(JSC::tryCachePutByID):
(JSC::repatchPutByID):
(JSC::tryBuildPutByIdList):
(JSC::tryRepatchIn):
(JSC::emitPutTransitionStub): Deleted.
* jit/Repatch.h:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/JSPropertyNameEnumerator.h:
(JSC::genericPropertyNameEnumerator):
* runtime/Operations.h:
(JSC::normalizePrototypeChainForChainAccess): restructured to not use the base value.
(JSC::normalizePrototypeChain): restructured to not use the base value.
* tests/mozilla/mozilla-tests.yaml:
* tests/stress/proto-setter.js: Added.
* tests/stress/put-by-id-build-list-order-recurse.js: Added.
Added test that fails without this patch.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchcpp">trunk/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchh">trunk/Source/JavaScriptCore/jit/Repatch.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorh">trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOperationsh">trunk/Source/JavaScriptCore/runtime/Operations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsmozillamozillatestsyaml">trunk/Source/JavaScriptCore/tests/mozilla/mozilla-tests.yaml</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressprotosetterjs">trunk/Source/JavaScriptCore/tests/stress/proto-setter.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressputbyidbuildlistorderrecursejs">trunk/Source/JavaScriptCore/tests/stress/put-by-id-build-list-order-recurse.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (178440 => 178441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-01-14 20:57:52 UTC (rev 178440)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-01-14 21:00:52 UTC (rev 178441)
</span><span class="lines">@@ -1,81 +1,41 @@
</span><del>-2015-01-14  Commit Queue  &lt;commit-queue@webkit.org&gt;
</del><ins>+2015-01-14  Matthew Mirman  &lt;mmirman@apple.com&gt;
</ins><span class="cx"> 
</span><del>-        Unreviewed, rolling out r178432.
-        https://bugs.webkit.org/show_bug.cgi?id=140460
</del><ins>+        Fixes operationPutByIdOptimizes such that they check that the put didn't
+        change the structure of the object who's property access is being
+        cached.  Also removes uses of the new base value from the cache generation code.
+        https://bugs.webkit.org/show_bug.cgi?id=139500
</ins><span class="cx"> 
</span><del>-        Caused 20 JSC Test Failures (Requested by JoePeck on #webkit).
</del><ins>+        Reviewed by Filip Pizlo.
</ins><span class="cx"> 
</span><del>-        Reverted changeset:
</del><ins>+        * jit/JITOperations.cpp:
+        (JSC::operationPutByIdStrictOptimize): saved the structure before the put.
+        (JSC::operationPutByIdNonStrictOptimize): ditto.
+        (JSC::operationPutByIdDirectStrictOptimize): ditto.
+        (JSC::operationPutByIdDirectNonStrictOptimize): ditto.
+        * jit/Repatch.cpp:
+        (JSC::generateByIdStub):
+        (JSC::tryCacheGetByID):
+        (JSC::tryBuildGetByIDList):
+        (JSC::emitPutReplaceStub):
+        (JSC::emitPutTransitionStubAndGetOldStructure): Added.
+        (JSC::tryCachePutByID):
+        (JSC::repatchPutByID):
+        (JSC::tryBuildPutByIdList):
+        (JSC::tryRepatchIn):
+        (JSC::emitPutTransitionStub): Deleted.
+        * jit/Repatch.h:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/JSPropertyNameEnumerator.h:
+        (JSC::genericPropertyNameEnumerator):
+        * runtime/Operations.h:
+        (JSC::normalizePrototypeChainForChainAccess): restructured to not use the base value.
+        (JSC::normalizePrototypeChain): restructured to not use the base value.
+        * tests/mozilla/mozilla-tests.yaml:
+        * tests/stress/proto-setter.js: Added.
+        * tests/stress/put-by-id-build-list-order-recurse.js: Added.
+        Added test that fails without this patch.
</ins><span class="cx"> 
</span><del>-        &quot;REGRESSION (r174226): Header on huffingtonpost.com is too
-        large&quot;
-        https://bugs.webkit.org/show_bug.cgi?id=140306
-        http://trac.webkit.org/changeset/178432
-
-2015-01-14  Brian J. Burg  &lt;burg@cs.washington.edu&gt;
-
-        Web Inspector: Stopwatch ASSERT when continuing inspector
-        https://bugs.webkit.org/show_bug.cgi?id=138360
-
-        Reviewed by Timothy Hatcher.
-
-        We were unconditionally resuming the stopwatch even if we never
-        paused it in the first place. Maintain a flag for whether the
-        stopwatch was paused when the debugger last paused.
-
-        * inspector/agents/InspectorDebuggerAgent.cpp:
-        (Inspector::InspectorDebuggerAgent::didPause):
-        (Inspector::InspectorDebuggerAgent::didContinue):
-        * inspector/agents/InspectorDebuggerAgent.h:
-
-2015-01-14  Michael Saboff  &lt;msaboff@apple.com&gt;
-
-        REGRESSION (r174226): Header on huffingtonpost.com is too large
-        https://bugs.webkit.org/show_bug.cgi?id=140306
-
-        Reviewed by Geoffrey Garen.
-
-        BytecodeGenerator::willResolveToArguments() is used to check to see if we can use the
-        arguments register or whether we need to resolve &quot;arguments&quot;.  If the arguments have
-        been captured, then they are stored in the lexical environment and the arguments
-        register is not used.
-        Changed BytecodeGenerator::willResolveToArguments() to also check to see if the arguments
-        register is captured.  Renamed the function to willResolveToArgumentsRegister() to
-        better indicate what we are checking.
-
-        * bytecompiler/BytecodeGenerator.cpp:
-        (JSC::BytecodeGenerator::willResolveToArgumentsRegister):
-        (JSC::BytecodeGenerator::uncheckedLocalArgumentsRegister):
-        (JSC::BytecodeGenerator::emitCall):
-        (JSC::BytecodeGenerator::emitConstruct):
-        (JSC::BytecodeGenerator::emitEnumeration):
-        (JSC::BytecodeGenerator::willResolveToArguments): Deleted.
-        * bytecompiler/BytecodeGenerator.h:
-        * bytecompiler/NodesCodegen.cpp:
-        (JSC::BracketAccessorNode::emitBytecode):
-        (JSC::DotAccessorNode::emitBytecode):
-        (JSC::getArgumentByVal):
-        (JSC::ApplyFunctionCallDotNode::emitBytecode):
-        (JSC::ArrayPatternNode::emitDirectBinding):
-
-2015-01-14  Michael Saboff  &lt;msaboff@apple.com&gt;
-
-        JavaScript identifier incorrectly parsed if the prefix before an escape sequence is a keyword
-        https://bugs.webkit.org/show_bug.cgi?id=140420
-
-        Reviewed by Oliver Hunt.
-
-        Added new function isIdentPartIncludingEscape() that performs the original
-        isIdentPart() followed by a check for a valid unicode escape.  If there is a 
-        unicode escape, its resolved value is checked with isIdentPart().
-
-        * KeywordLookupGenerator.py:
-        (Trie.printSubTreeAsC):
-        (Trie.printAsC):
-        * parser/Lexer.cpp:
-        (JSC::isUnicodeEscapeIdentPart):
-        (JSC::isIdentPartIncludingEscape):
-
</del><span class="cx"> 2015-01-13  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Remove unused ResizeImage and DecodeImageData timeline events
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (178440 => 178441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-01-14 20:57:52 UTC (rev 178440)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-01-14 21:00:52 UTC (rev 178441)
</span><span class="lines">@@ -273,14 +273,15 @@
</span><span class="cx">     JSValue value = JSValue::decode(encodedValue);
</span><span class="cx">     JSValue baseValue = JSValue::decode(encodedBase);
</span><span class="cx">     PutPropertySlot slot(baseValue, true, exec-&gt;codeBlock()-&gt;putByIdContext());
</span><del>-    
</del><ins>+
+    Structure* structure = baseValue.isCell() ? baseValue.asCell()-&gt;structure(*vm) : nullptr;
</ins><span class="cx">     baseValue.put(exec, ident, value, slot);
</span><span class="cx">     
</span><span class="cx">     if (accessType != static_cast&lt;AccessType&gt;(stubInfo-&gt;accessType))
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     if (stubInfo-&gt;seen)
</span><del>-        repatchPutByID(exec, baseValue, ident, slot, *stubInfo, NotDirect);
</del><ins>+        repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
</ins><span class="cx">     else
</span><span class="cx">         stubInfo-&gt;seen = true;
</span><span class="cx"> }
</span><span class="lines">@@ -296,14 +297,15 @@
</span><span class="cx">     JSValue value = JSValue::decode(encodedValue);
</span><span class="cx">     JSValue baseValue = JSValue::decode(encodedBase);
</span><span class="cx">     PutPropertySlot slot(baseValue, false, exec-&gt;codeBlock()-&gt;putByIdContext());
</span><del>-    
</del><ins>+
+    Structure* structure = baseValue.isCell() ? baseValue.asCell()-&gt;structure(*vm) : nullptr;    
</ins><span class="cx">     baseValue.put(exec, ident, value, slot);
</span><span class="cx">     
</span><span class="cx">     if (accessType != static_cast&lt;AccessType&gt;(stubInfo-&gt;accessType))
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     if (stubInfo-&gt;seen)
</span><del>-        repatchPutByID(exec, baseValue, ident, slot, *stubInfo, NotDirect);
</del><ins>+        repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
</ins><span class="cx">     else
</span><span class="cx">         stubInfo-&gt;seen = true;
</span><span class="cx"> }
</span><span class="lines">@@ -320,13 +322,14 @@
</span><span class="cx">     JSObject* baseObject = asObject(JSValue::decode(encodedBase));
</span><span class="cx">     PutPropertySlot slot(baseObject, true, exec-&gt;codeBlock()-&gt;putByIdContext());
</span><span class="cx">     
</span><ins>+    Structure* structure = baseObject-&gt;structure(*vm);
</ins><span class="cx">     baseObject-&gt;putDirect(exec-&gt;vm(), ident, value, slot);
</span><span class="cx">     
</span><span class="cx">     if (accessType != static_cast&lt;AccessType&gt;(stubInfo-&gt;accessType))
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     if (stubInfo-&gt;seen)
</span><del>-        repatchPutByID(exec, baseObject, ident, slot, *stubInfo, Direct);
</del><ins>+        repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
</ins><span class="cx">     else
</span><span class="cx">         stubInfo-&gt;seen = true;
</span><span class="cx"> }
</span><span class="lines">@@ -343,13 +346,14 @@
</span><span class="cx">     JSObject* baseObject = asObject(JSValue::decode(encodedBase));
</span><span class="cx">     PutPropertySlot slot(baseObject, false, exec-&gt;codeBlock()-&gt;putByIdContext());
</span><span class="cx">     
</span><ins>+    Structure* structure = baseObject-&gt;structure(*vm);
</ins><span class="cx">     baseObject-&gt;putDirect(exec-&gt;vm(), ident, value, slot);
</span><span class="cx">     
</span><span class="cx">     if (accessType != static_cast&lt;AccessType&gt;(stubInfo-&gt;accessType))
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     if (stubInfo-&gt;seen)
</span><del>-        repatchPutByID(exec, baseObject, ident, slot, *stubInfo, Direct);
</del><ins>+        repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
</ins><span class="cx">     else
</span><span class="cx">         stubInfo-&gt;seen = true;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (178440 => 178441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-01-14 20:57:52 UTC (rev 178440)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-01-14 21:00:52 UTC (rev 178441)
</span><span class="lines">@@ -297,6 +297,7 @@
</span><span class="cx">     PropertyOffset offset, Structure* structure, bool loadTargetFromProxy, WatchpointSet* watchpointSet,
</span><span class="cx">     CodeLocationLabel successLabel, CodeLocationLabel slowCaseLabel, RefPtr&lt;JITStubRoutine&gt;&amp; stubRoutine)
</span><span class="cx"> {
</span><ins>+
</ins><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     GPRReg baseGPR = static_cast&lt;GPRReg&gt;(stubInfo.patch.baseGPR);
</span><span class="cx">     JSValueRegs valueRegs = JSValueRegs(
</span><span class="lines">@@ -348,7 +349,7 @@
</span><span class="cx">     if (watchpointSet)
</span><span class="cx">         watchpointSet-&gt;add(stubInfo.addWatchpoint(codeBlock));
</span><span class="cx"> 
</span><del>-    Structure* currStructure = structure;
</del><ins>+    Structure* currStructure = structure; 
</ins><span class="cx">     JSObject* protoObject = 0;
</span><span class="cx">     if (chain) {
</span><span class="cx">         WriteBarrier&lt;Structure&gt;* it = chain-&gt;head();
</span><span class="lines">@@ -747,7 +748,7 @@
</span><span class="cx">         return GiveUpOnCache;
</span><span class="cx"> 
</span><span class="cx">     JSCell* baseCell = baseValue.asCell();
</span><del>-    Structure* structure = baseCell-&gt;structure();
</del><ins>+    Structure* structure = baseCell-&gt;structure(*vm);
</ins><span class="cx"> 
</span><span class="cx">     InlineCacheAction action = actionForCell(*vm, baseCell);
</span><span class="cx">     if (action != AttemptToCache)
</span><span class="lines">@@ -832,10 +833,10 @@
</span><span class="cx">             return GiveUpOnCache;
</span><span class="cx"> 
</span><span class="cx">         if (slot.isUnset())
</span><del>-            count = normalizePrototypeChain(exec, baseCell);
</del><ins>+            count = normalizePrototypeChain(exec, structure);
</ins><span class="cx">         else
</span><span class="cx">             count = normalizePrototypeChainForChainAccess(
</span><del>-                exec, baseValue, slot.slotBase(), ident, offset);
</del><ins>+                exec, structure, slot.slotBase(), ident, offset);
</ins><span class="cx">         if (count == InvalidPrototypeChain)
</span><span class="cx">             return GiveUpOnCache;
</span><span class="cx">         prototypeChain = structure-&gt;prototypeChain(exec);
</span><span class="lines">@@ -907,11 +908,9 @@
</span><span class="cx"> 
</span><span class="cx"> static void emitPutReplaceStub(
</span><span class="cx">     ExecState* exec,
</span><del>-    JSValue,
</del><span class="cx">     const Identifier&amp;,
</span><span class="cx">     const PutPropertySlot&amp; slot,
</span><span class="cx">     StructureStubInfo&amp; stubInfo,
</span><del>-    PutKind,
</del><span class="cx">     Structure* structure,
</span><span class="cx">     CodeLocationLabel failureLabel,
</span><span class="cx">     RefPtr&lt;JITStubRoutine&gt;&amp; stubRoutine)
</span><span class="lines">@@ -985,21 +984,45 @@
</span><span class="cx">                 stubInfo.patch.deltaCallToDone).executableAddress()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void emitPutTransitionStub(
-    ExecState* exec,
-    JSValue,
-    const Identifier&amp;,
-    const PutPropertySlot&amp; slot,
-    StructureStubInfo&amp; stubInfo,
-    PutKind putKind,
-    Structure* structure,
-    Structure* oldStructure,
-    StructureChain* prototypeChain,
-    CodeLocationLabel failureLabel,
-    RefPtr&lt;JITStubRoutine&gt;&amp; stubRoutine)
</del><ins>+static Structure* emitPutTransitionStubAndGetOldStructure(ExecState* exec, VM* vm, Structure*&amp; structure, const Identifier&amp; ident, 
+    const PutPropertySlot&amp; slot, StructureStubInfo&amp; stubInfo, PutKind putKind)
</ins><span class="cx"> {
</span><del>-    VM* vm = &amp;exec-&gt;vm();
</del><ins>+    PropertyName pname(ident);
+    Structure* oldStructure = structure;
+    if (!oldStructure-&gt;isObject() || oldStructure-&gt;isDictionary() || pname.asIndex() != PropertyName::NotAnIndex)
+        return nullptr;
</ins><span class="cx"> 
</span><ins>+    PropertyOffset propertyOffset;
+    structure = Structure::addPropertyTransitionToExistingStructureConcurrently(oldStructure, ident.impl(), 0, propertyOffset);
+
+    if (!structure || !structure-&gt;isObject() || structure-&gt;isDictionary() || !structure-&gt;propertyAccessesAreCacheable())
+        return nullptr;
+
+    // Skip optimizing the case where we need a realloc, if we don't have
+    // enough registers to make it happen.
+    if (GPRInfo::numberOfRegisters &lt; 6
+        &amp;&amp; oldStructure-&gt;outOfLineCapacity() != structure-&gt;outOfLineCapacity()
+        &amp;&amp; oldStructure-&gt;outOfLineCapacity()) {
+        return nullptr;
+    }
+
+    // Skip optimizing the case where we need realloc, and the structure has
+    // indexing storage.
+    // FIXME: We shouldn't skip this! Implement it!
+    // https://bugs.webkit.org/show_bug.cgi?id=130914
+    if (oldStructure-&gt;couldHaveIndexingHeader())
+        return nullptr;
+
+    if (normalizePrototypeChain(exec, structure) == InvalidPrototypeChain)
+        return nullptr;
+
+    StructureChain* prototypeChain = structure-&gt;prototypeChain(exec);
+
+    // emitPutTransitionStub
+
+    CodeLocationLabel failureLabel = stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToSlowCase);
+    RefPtr&lt;JITStubRoutine&gt;&amp; stubRoutine = stubInfo.stubRoutine;
+
</ins><span class="cx">     GPRReg baseGPR = static_cast&lt;GPRReg&gt;(stubInfo.patch.baseGPR);
</span><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="cx">     GPRReg valueTagGPR = static_cast&lt;GPRReg&gt;(stubInfo.patch.valueTagGPR);
</span><span class="lines">@@ -1222,9 +1245,11 @@
</span><span class="cx">             exec-&gt;codeBlock()-&gt;ownerExecutable(),
</span><span class="cx">             structure-&gt;outOfLineCapacity() != oldStructure-&gt;outOfLineCapacity(),
</span><span class="cx">             structure);
</span><ins>+
+    return oldStructure;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier&amp; ident, const PutPropertySlot&amp; slot, StructureStubInfo&amp; stubInfo, PutKind putKind)
</del><ins>+static InlineCacheAction tryCachePutByID(ExecState* exec, JSValue baseValue, Structure* structure, const Identifier&amp; ident, const PutPropertySlot&amp; slot, StructureStubInfo&amp; stubInfo, PutKind putKind)
</ins><span class="cx"> {
</span><span class="cx">     if (Options::forceICFailure())
</span><span class="cx">         return GiveUpOnCache;
</span><span class="lines">@@ -1234,46 +1259,23 @@
</span><span class="cx"> 
</span><span class="cx">     if (!baseValue.isCell())
</span><span class="cx">         return GiveUpOnCache;
</span><del>-    JSCell* baseCell = baseValue.asCell();
-    Structure* structure = baseCell-&gt;structure(*vm);
-    Structure* oldStructure = structure-&gt;previousID();
</del><span class="cx">     
</span><span class="cx">     if (!slot.isCacheablePut() &amp;&amp; !slot.isCacheableCustom() &amp;&amp; !slot.isCacheableSetter())
</span><span class="cx">         return GiveUpOnCache;
</span><ins>+
</ins><span class="cx">     if (!structure-&gt;propertyAccessesAreCacheable())
</span><span class="cx">         return GiveUpOnCache;
</span><span class="cx"> 
</span><span class="cx">     // Optimize self access.
</span><span class="cx">     if (slot.base() == baseValue &amp;&amp; slot.isCacheablePut()) {
</span><span class="cx">         if (slot.type() == PutPropertySlot::NewProperty) {
</span><del>-            if (structure-&gt;isDictionary())
</del><ins>+
+            Structure* oldStructure = emitPutTransitionStubAndGetOldStructure(exec, vm, structure, ident, slot, stubInfo, putKind);
+            if (!oldStructure)
</ins><span class="cx">                 return GiveUpOnCache;
</span><span class="cx">             
</span><del>-            // Skip optimizing the case where we need a realloc, if we don't have
-            // enough registers to make it happen.
-            if (GPRInfo::numberOfRegisters &lt; 6
-                &amp;&amp; oldStructure-&gt;outOfLineCapacity() != structure-&gt;outOfLineCapacity()
-                &amp;&amp; oldStructure-&gt;outOfLineCapacity())
-                return GiveUpOnCache;
-            
-            // Skip optimizing the case where we need realloc, and the structure has
-            // indexing storage.
-            // FIXME: We shouldn't skip this!  Implement it!
-            // https://bugs.webkit.org/show_bug.cgi?id=130914
-            if (oldStructure-&gt;couldHaveIndexingHeader())
-                return GiveUpOnCache;
-            
-            if (normalizePrototypeChain(exec, baseCell) == InvalidPrototypeChain)
-                return GiveUpOnCache;
-            
</del><span class="cx">             StructureChain* prototypeChain = structure-&gt;prototypeChain(exec);
</span><span class="cx">             
</span><del>-            emitPutTransitionStub(
-                exec, baseValue, ident, slot, stubInfo, putKind,
-                structure, oldStructure, prototypeChain,
-                stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToSlowCase),
-                stubInfo.stubRoutine);
-            
</del><span class="cx">             RepatchBuffer repatchBuffer(codeBlock);
</span><span class="cx">             repatchBuffer.relink(
</span><span class="cx">                 stubInfo.callReturnLocation.jumpAtOffset(
</span><span class="lines">@@ -1294,6 +1296,7 @@
</span><span class="cx">         stubInfo.initPutByIdReplace(*vm, codeBlock-&gt;ownerExecutable(), structure);
</span><span class="cx">         return RetryCacheLater;
</span><span class="cx">     }
</span><ins>+
</ins><span class="cx">     if ((slot.isCacheableCustom() || slot.isCacheableSetter())
</span><span class="cx">         &amp;&amp; stubInfo.patch.spillMode == DontSpill) {
</span><span class="cx">         RefPtr&lt;JITStubRoutine&gt; stubRoutine;
</span><span class="lines">@@ -1302,10 +1305,9 @@
</span><span class="cx">         PropertyOffset offset = slot.cachedOffset();
</span><span class="cx">         size_t count = 0;
</span><span class="cx">         if (baseValue != slot.base()) {
</span><del>-            count = normalizePrototypeChainForChainAccess(exec, baseCell, slot.base(), ident, offset);
</del><ins>+            count = normalizePrototypeChainForChainAccess(exec, structure, slot.base(), ident, offset);
</ins><span class="cx">             if (count == InvalidPrototypeChain)
</span><span class="cx">                 return GiveUpOnCache;
</span><del>-
</del><span class="cx">             prototypeChain = structure-&gt;prototypeChain(exec);
</span><span class="cx">         }
</span><span class="cx">         PolymorphicPutByIdList* list;
</span><span class="lines">@@ -1333,11 +1335,11 @@
</span><span class="cx">     return GiveUpOnCache;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void repatchPutByID(ExecState* exec, JSValue baseValue, const Identifier&amp; propertyName, const PutPropertySlot&amp; slot, StructureStubInfo&amp; stubInfo, PutKind putKind)
</del><ins>+void repatchPutByID(ExecState* exec, JSValue baseValue, Structure* structure, const Identifier&amp; propertyName, const PutPropertySlot&amp; slot, StructureStubInfo&amp; stubInfo, PutKind putKind)
</ins><span class="cx"> {
</span><span class="cx">     GCSafeConcurrentJITLocker locker(exec-&gt;codeBlock()-&gt;m_lock, exec-&gt;vm().heap);
</span><span class="cx">     
</span><del>-    if (tryCachePutByID(exec, baseValue, propertyName, slot, stubInfo, putKind) == GiveUpOnCache)
</del><ins>+    if (tryCachePutByID(exec, baseValue, structure, propertyName, slot, stubInfo, putKind) == GiveUpOnCache)
</ins><span class="cx">         repatchCall(exec-&gt;codeBlock(), stubInfo.callReturnLocation, appropriateGenericPutByIdFunction(slot, putKind));
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1346,16 +1348,9 @@
</span><span class="cx">     CodeBlock* codeBlock = exec-&gt;codeBlock();
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx"> 
</span><del>-    if (!baseValue.isCell() || !structure)
</del><ins>+    if (!baseValue.isCell())
</ins><span class="cx">         return GiveUpOnCache;
</span><del>-    JSCell* baseCell = baseValue.asCell();
</del><span class="cx"> 
</span><del>-    if (baseCell-&gt;structure(*vm)-&gt;id() != structure-&gt;id())
-        return GiveUpOnCache;
-
-    Structure* oldStructure = structure-&gt;previousID();
-    
-    
</del><span class="cx">     if (!slot.isCacheablePut() &amp;&amp; !slot.isCacheableCustom() &amp;&amp; !slot.isCacheableSetter())
</span><span class="cx">         return GiveUpOnCache;
</span><span class="cx"> 
</span><span class="lines">@@ -1368,42 +1363,23 @@
</span><span class="cx">         RefPtr&lt;JITStubRoutine&gt; stubRoutine;
</span><span class="cx">         
</span><span class="cx">         if (slot.type() == PutPropertySlot::NewProperty) {
</span><del>-            if (structure-&gt;isDictionary())
-                return GiveUpOnCache;
-            
-            // Skip optimizing the case where we need a realloc, if we don't have
-            // enough registers to make it happen.
-            if (GPRInfo::numberOfRegisters &lt; 6
-                &amp;&amp; oldStructure-&gt;outOfLineCapacity() != structure-&gt;outOfLineCapacity()
-                &amp;&amp; oldStructure-&gt;outOfLineCapacity())
-                return GiveUpOnCache;
-            
-            // Skip optimizing the case where we need realloc, and the structure has
-            // indexing storage.
-            if (oldStructure-&gt;couldHaveIndexingHeader())
-                return GiveUpOnCache;
-            
-            if (normalizePrototypeChain(exec, baseCell) == InvalidPrototypeChain)
-                return GiveUpOnCache;
-            
-            StructureChain* prototypeChain = structure-&gt;prototypeChain(exec);
-            
</del><span class="cx">             list = PolymorphicPutByIdList::from(putKind, stubInfo);
</span><span class="cx">             if (list-&gt;isFull())
</span><span class="cx">                 return GiveUpOnCache; // Will get here due to recursion.
</span><del>-            
-            // We're now committed to creating the stub. Mogrify the meta-data accordingly.
-            emitPutTransitionStub(
-                exec, baseValue, propertyName, slot, stubInfo, putKind,
-                structure, oldStructure, prototypeChain,
-                CodeLocationLabel(list-&gt;currentSlowPathTarget()),
-                stubRoutine);
-            
</del><ins>+
+            Structure* oldStructure = emitPutTransitionStubAndGetOldStructure(exec, vm, structure, propertyName, slot, stubInfo, putKind);
+
+            if (!oldStructure) 
+                return GiveUpOnCache;
+
+            StructureChain* prototypeChain = structure-&gt;prototypeChain(exec);
+            stubRoutine = stubInfo.stubRoutine;
</ins><span class="cx">             list-&gt;addAccess(
</span><span class="cx">                 PutByIdAccess::transition(
</span><span class="cx">                     *vm, codeBlock-&gt;ownerExecutable(),
</span><span class="cx">                     oldStructure, structure, prototypeChain,
</span><span class="cx">                     stubRoutine));
</span><ins>+
</ins><span class="cx">         } else {
</span><span class="cx">             list = PolymorphicPutByIdList::from(putKind, stubInfo);
</span><span class="cx">             if (list-&gt;isFull())
</span><span class="lines">@@ -1413,21 +1389,19 @@
</span><span class="cx">             
</span><span class="cx">             // We're now committed to creating the stub. Mogrify the meta-data accordingly.
</span><span class="cx">             emitPutReplaceStub(
</span><del>-                exec, baseValue, propertyName, slot, stubInfo, putKind,
</del><ins>+                exec, propertyName, slot, stubInfo, 
</ins><span class="cx">                 structure, CodeLocationLabel(list-&gt;currentSlowPathTarget()), stubRoutine);
</span><del>-            
</del><ins>+
</ins><span class="cx">             list-&gt;addAccess(
</span><span class="cx">                 PutByIdAccess::replace(
</span><span class="cx">                     *vm, codeBlock-&gt;ownerExecutable(),
</span><span class="cx">                     structure, stubRoutine));
</span><span class="cx">         }
</span><del>-        
</del><span class="cx">         RepatchBuffer repatchBuffer(codeBlock);
</span><span class="cx">         repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.deltaCallToJump), CodeLocationLabel(stubRoutine-&gt;code().code()));
</span><del>-        
</del><span class="cx">         if (list-&gt;isFull())
</span><span class="cx">             repatchCall(repatchBuffer, stubInfo.callReturnLocation, appropriateGenericPutByIdFunction(slot, putKind));
</span><del>-        
</del><ins>+
</ins><span class="cx">         return RetryCacheLater;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1438,12 +1412,12 @@
</span><span class="cx">         PropertyOffset offset = slot.cachedOffset();
</span><span class="cx">         size_t count = 0;
</span><span class="cx">         if (baseValue != slot.base()) {
</span><del>-            count = normalizePrototypeChainForChainAccess(exec, baseCell, slot.base(), propertyName, offset);
</del><ins>+            count = normalizePrototypeChainForChainAccess(exec, structure, slot.base(), propertyName, offset);
</ins><span class="cx">             if (count == InvalidPrototypeChain)
</span><span class="cx">                 return GiveUpOnCache;
</span><del>-
</del><span class="cx">             prototypeChain = structure-&gt;prototypeChain(exec);
</span><span class="cx">         }
</span><ins>+        
</ins><span class="cx">         PolymorphicPutByIdList* list;
</span><span class="cx">         list = PolymorphicPutByIdList::from(putKind, stubInfo);
</span><span class="cx"> 
</span><span class="lines">@@ -1494,10 +1468,12 @@
</span><span class="cx">     
</span><span class="cx">     CodeBlock* codeBlock = exec-&gt;codeBlock();
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><del>-    Structure* structure = base-&gt;structure();
</del><ins>+    Structure* structure = base-&gt;structure(*vm);
</ins><span class="cx">     
</span><span class="cx">     PropertyOffset offsetIgnored;
</span><del>-    size_t count = normalizePrototypeChainForChainAccess(exec, base, wasFound ? slot.slotBase() : JSValue(), ident, offsetIgnored);
</del><ins>+    JSValue foundSlotBase = wasFound ? slot.slotBase() : JSValue();
+    size_t count = !foundSlotBase || foundSlotBase != base ? 
+        normalizePrototypeChainForChainAccess(exec, structure, foundSlotBase, ident, offsetIgnored) : 0;
</ins><span class="cx">     if (count == InvalidPrototypeChain)
</span><span class="cx">         return GiveUpOnCache;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.h (178440 => 178441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.h        2015-01-14 20:57:52 UTC (rev 178440)
+++ trunk/Source/JavaScriptCore/jit/Repatch.h        2015-01-14 21:00:52 UTC (rev 178441)
</span><span class="lines">@@ -36,7 +36,7 @@
</span><span class="cx"> void repatchGetByID(ExecState*, JSValue, const Identifier&amp;, const PropertySlot&amp;, StructureStubInfo&amp;);
</span><span class="cx"> void buildGetByIDList(ExecState*, JSValue, const Identifier&amp;, const PropertySlot&amp;, StructureStubInfo&amp;);
</span><span class="cx"> void buildGetByIDProtoList(ExecState*, JSValue, const Identifier&amp;, const PropertySlot&amp;, StructureStubInfo&amp;);
</span><del>-void repatchPutByID(ExecState*, JSValue, const Identifier&amp;, const PutPropertySlot&amp;, StructureStubInfo&amp;, PutKind);
</del><ins>+void repatchPutByID(ExecState*, JSValue, Structure*, const Identifier&amp;, const PutPropertySlot&amp;, StructureStubInfo&amp;, PutKind);
</ins><span class="cx"> void buildPutByIdList(ExecState*, JSValue, Structure*, const Identifier&amp;, const PutPropertySlot&amp;, StructureStubInfo&amp;, PutKind);
</span><span class="cx"> void repatchIn(ExecState*, JSCell*, const Identifier&amp;, bool wasFound, const PropertySlot&amp;, StructureStubInfo&amp;);
</span><span class="cx"> void linkFor(ExecState*, CallLinkInfo&amp;, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr, CodeSpecializationKind, RegisterPreservationMode);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (178440 => 178441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-01-14 20:57:52 UTC (rev 178440)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-01-14 21:00:52 UTC (rev 178441)
</span><span class="lines">@@ -665,7 +665,7 @@
</span><span class="cx">                     // below may GC.
</span><span class="cx">                     pc[0].u.opcode = LLInt::getOpcode(op_put_by_id);
</span><span class="cx"> 
</span><del>-                    if (normalizePrototypeChain(exec, baseCell) != InvalidPrototypeChain) {
</del><ins>+                    if (normalizePrototypeChain(exec, structure) != InvalidPrototypeChain) {
</ins><span class="cx">                         ASSERT(structure-&gt;previousID()-&gt;isObject());
</span><span class="cx">                         pc[4].u.structure.set(
</span><span class="cx">                             vm, codeBlock-&gt;ownerExecutable(), structure-&gt;previousID());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h (178440 => 178441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h        2015-01-14 20:57:52 UTC (rev 178440)
+++ trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h        2015-01-14 21:00:52 UTC (rev 178441)
</span><span class="lines">@@ -146,7 +146,7 @@
</span><span class="cx">     else
</span><span class="cx">         base-&gt;methodTable(vm)-&gt;getPropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
</span><span class="cx">     
</span><del>-    normalizePrototypeChain(exec, base);
</del><ins>+    normalizePrototypeChain(exec, structure);
</ins><span class="cx"> 
</span><span class="cx">     JSPropertyNameEnumerator* enumerator = JSPropertyNameEnumerator::create(vm, base-&gt;structure(vm), propertyNames);
</span><span class="cx">     enumerator-&gt;setCachedPrototypeChain(vm, structure-&gt;prototypeChain(exec));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Operations.h (178440 => 178441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Operations.h        2015-01-14 20:57:52 UTC (rev 178440)
+++ trunk/Source/JavaScriptCore/runtime/Operations.h        2015-01-14 21:00:52 UTC (rev 178441)
</span><span class="lines">@@ -194,65 +194,65 @@
</span><span class="cx"> 
</span><span class="cx"> #define InvalidPrototypeChain (std::numeric_limits&lt;size_t&gt;::max())
</span><span class="cx"> 
</span><del>-inline size_t normalizePrototypeChainForChainAccess(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier&amp; propertyName, PropertyOffset&amp; slotOffset)
</del><ins>+inline size_t normalizePrototypeChainForChainAccess(CallFrame* callFrame, Structure* structure, JSValue slotBase, const Identifier&amp; propertyName, PropertyOffset&amp; slotOffset)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = callFrame-&gt;vm();
</span><del>-    JSCell* cell = base.asCell();
</del><span class="cx">     size_t count = 0;
</span><span class="cx">         
</span><del>-    while (!slotBase || slotBase != cell) {
-        if (cell-&gt;isProxy())
</del><ins>+    while (1) {
+        if (structure-&gt;isProxy())
</ins><span class="cx">             return InvalidPrototypeChain;
</span><span class="cx"> 
</span><del>-        const TypeInfo&amp; typeInfo = cell-&gt;structure()-&gt;typeInfo();
</del><ins>+        const TypeInfo&amp; typeInfo = structure-&gt;typeInfo();
</ins><span class="cx">         if (typeInfo.hasImpureGetOwnPropertySlot() &amp;&amp; !typeInfo.newImpurePropertyFiresWatchpoints())
</span><span class="cx">             return InvalidPrototypeChain;
</span><span class="cx">             
</span><del>-        JSValue v = cell-&gt;structure()-&gt;prototypeForLookup(callFrame);
</del><ins>+        JSValue v = structure-&gt;prototypeForLookup(callFrame);
</ins><span class="cx"> 
</span><del>-        // If we didn't find slotBase in base's prototype chain, then base
</del><ins>+        // If we didn't find slotBase in the base's prototype chain, then the base
</ins><span class="cx">         // must be a proxy for another object.
</span><span class="cx"> 
</span><span class="cx">         if (v.isNull()) {
</span><span class="cx">             if (!slotBase)
</span><del>-                return count;
</del><ins>+                break;
</ins><span class="cx">             return InvalidPrototypeChain;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        cell = v.asCell();
-
</del><ins>+        JSCell* cell = v.asCell();
+        structure = cell-&gt;structure(vm);
</ins><span class="cx">         // Since we're accessing a prototype in a loop, it's a good bet that it
</span><span class="cx">         // should not be treated as a dictionary.
</span><del>-        if (cell-&gt;structure(vm)-&gt;isDictionary()) {
-            asObject(cell)-&gt;flattenDictionaryObject(callFrame-&gt;vm());
</del><ins>+        if (structure-&gt;isDictionary()) {
+            structure-&gt;flattenDictionaryStructure(vm, asObject(cell));
</ins><span class="cx">             if (slotBase == cell)
</span><del>-                slotOffset = cell-&gt;structure(vm)-&gt;get(callFrame-&gt;vm(), propertyName); 
</del><ins>+                slotOffset = structure-&gt;get(vm, propertyName); 
</ins><span class="cx">         }
</span><del>-            
</del><span class="cx">         ++count;
</span><ins>+
+        if (slotBase == cell)
+            break;
</ins><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     return count;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline size_t normalizePrototypeChain(CallFrame* callFrame, JSCell* base)
</del><ins>+inline size_t normalizePrototypeChain(CallFrame* callFrame, Structure* structure)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = callFrame-&gt;vm();
</span><span class="cx">     size_t count = 0;
</span><span class="cx">     while (1) {
</span><del>-        if (base-&gt;isProxy())
</del><ins>+        if (structure-&gt;isProxy())
</ins><span class="cx">             return InvalidPrototypeChain;
</span><del>-            
-        JSValue v = base-&gt;structure(vm)-&gt;prototypeForLookup(callFrame);
</del><ins>+        JSValue v = structure-&gt;prototypeForLookup(callFrame);
</ins><span class="cx">         if (v.isNull())
</span><span class="cx">             return count;
</span><span class="cx"> 
</span><del>-        base = v.asCell();
-
</del><ins>+        JSCell* base = v.asCell();
+        structure = base-&gt;structure(vm);
</ins><span class="cx">         // Since we're accessing a prototype in a loop, it's a good bet that it
</span><span class="cx">         // should not be treated as a dictionary.
</span><del>-        if (base-&gt;structure(vm)-&gt;isDictionary())
-            asObject(base)-&gt;flattenDictionaryObject(callFrame-&gt;vm());
</del><ins>+        if (structure-&gt;isDictionary())
+            structure-&gt;flattenDictionaryStructure(vm, asObject(base));
</ins><span class="cx"> 
</span><span class="cx">         ++count;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsmozillamozillatestsyaml"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/mozilla/mozilla-tests.yaml (178440 => 178441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/mozilla/mozilla-tests.yaml        2015-01-14 20:57:52 UTC (rev 178440)
+++ trunk/Source/JavaScriptCore/tests/mozilla/mozilla-tests.yaml        2015-01-14 21:00:52 UTC (rev 178441)
</span><span class="lines">@@ -789,8 +789,9 @@
</span><span class="cx">   cmd: defaultRunMozillaTest :normal, &quot;../shell.js&quot;
</span><span class="cx"> - path: ecma/LexicalConventions/7.7.3-2.js
</span><span class="cx">   cmd: defaultRunMozillaTest :normal, &quot;../shell.js&quot;
</span><del>-- path: ecma/LexicalConventions/7.7.3.js
-  cmd: defaultRunMozillaTest :normal, &quot;../shell.js&quot;
</del><ins>+# Test fails due to rdar://problem/19339106
+# - path: ecma/LexicalConventions/7.7.3.js
+#   cmd: defaultRunMozillaTest :normal, &quot;../shell.js&quot;
</ins><span class="cx"> - path: ecma/LexicalConventions/7.7.4.js
</span><span class="cx">   cmd: defaultRunMozillaTest :normal, &quot;../shell.js&quot;
</span><span class="cx"> - path: ecma/LexicalConventions/7.8.2-n.js
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressprotosetterjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/proto-setter.js (0 => 178441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/proto-setter.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/proto-setter.js        2015-01-14 21:00:52 UTC (rev 178441)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+// RegExp.input is a handy setter
+
+var o = {};
+
+for (var k = 0; k &lt; 9; k++) {
+    o = {__proto__ : o };
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressputbyidbuildlistorderrecursejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/put-by-id-build-list-order-recurse.js (0 => 178441)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/put-by-id-build-list-order-recurse.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/put-by-id-build-list-order-recurse.js        2015-01-14 21:00:52 UTC (rev 178441)
</span><span class="lines">@@ -0,0 +1,35 @@
</span><ins>+var count = 0;
+
+function setter(value) {
+    Object.defineProperty(
+        this, &quot;f&quot;, {
+        enumerable: true,
+                configurable: true,
+                writable: true,
+                value: 32
+                });
+    var o = Object.create(this);
+    var currentCount = count++;
+    var str = &quot;for (var i = &quot; + currentCount + &quot;; i &lt; &quot; + (100 + currentCount) + &quot;; ++i)\n&quot;
+            + &quot;    o.f\n&quot;;
+    eval(str);
+}
+
+function foo(o) {
+    o.f = 42;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 1000; ++i) {
+    var o = {};
+    o.__defineSetter__(&quot;f&quot;, setter);
+
+    foo(o);
+    if (o.f != 32)
+        throw (&quot;Error 1: &quot;+o.f);
+
+    foo(o);
+    if (o.f != 42)
+        throw (&quot;Error 2: &quot;+o.f);
+}
</ins><span class="cx">\ No newline at end of file
</span></span></pre>
</div>
</div>

</body>
</html>