<!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>[178286] releases/WebKitGTK/webkit-2.6/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/178286">178286</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2015-01-12 10:47:26 -0800 (Mon, 12 Jan 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/176676">r176676</a> - Fixes inline cache fast path accessing nonexistant getters.
&lt;rdar://problem/18416918&gt;
https://bugs.webkit.org/show_bug.cgi?id=136961

Reviewed by Filip Pizlo.

Fixes a bug in inline caching where getters would have been able to
modify the property they are getting during
building the inline cache and then accessing that
property through the inline cache site causing a recursive
inline cache building and allowing the fast path of the cache to
try to load a getter for the property that no longer exists.

* jit/JITOperations.cpp: Switched use of get to getPropertySlot.
* runtime/JSCJSValue.h:
added getPropertySlot for when you don't want to perform the get quite yet but want
to fill out the slot.
* runtime/JSCJSValueInlines.h: Added implementation for getPropertySlot
(JSC::JSValue::get): changed to simply call getPropertySlot
(JSC::JSValue::getPropertySlot): added.
* tests/stress/recursive_property_redefine_during_inline_caching.js: Added test case for bug.
(test):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit26SourceJavaScriptCoreChangeLog">releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#releasesWebKitGTKwebkit26SourceJavaScriptCorejitJITOperationscpp">releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#releasesWebKitGTKwebkit26SourceJavaScriptCoreruntimeJSCJSValueh">releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/runtime/JSCJSValue.h</a></li>
<li><a href="#releasesWebKitGTKwebkit26SourceJavaScriptCoreruntimeJSCJSValueInlinesh">releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/runtime/JSCJSValueInlines.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#releasesWebKitGTKwebkit26SourceJavaScriptCoretestsstressrecursive_property_redefine_during_inline_cachingjs">releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/tests/stress/recursive_property_redefine_during_inline_caching.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="releasesWebKitGTKwebkit26SourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/ChangeLog (178285 => 178286)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/ChangeLog        2015-01-12 18:41:38 UTC (rev 178285)
+++ releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/ChangeLog        2015-01-12 18:47:26 UTC (rev 178286)
</span><span class="lines">@@ -1,3 +1,28 @@
</span><ins>+2014-12-02  Matthew Mirman  &lt;mmirman@apple.com&gt;
+
+        Fixes inline cache fast path accessing nonexistant getters.
+        &lt;rdar://problem/18416918&gt;
+        https://bugs.webkit.org/show_bug.cgi?id=136961
+
+        Reviewed by Filip Pizlo.
+
+        Fixes a bug in inline caching where getters would have been able to 
+        modify the property they are getting during 
+        building the inline cache and then accessing that 
+        property through the inline cache site causing a recursive 
+        inline cache building and allowing the fast path of the cache to 
+        try to load a getter for the property that no longer exists.
+                
+        * jit/JITOperations.cpp: Switched use of get to getPropertySlot.
+        * runtime/JSCJSValue.h: 
+        added getPropertySlot for when you don't want to perform the get quite yet but want 
+        to fill out the slot.
+        * runtime/JSCJSValueInlines.h: Added implementation for getPropertySlot
+        (JSC::JSValue::get): changed to simply call getPropertySlot
+        (JSC::JSValue::getPropertySlot): added.
+        * tests/stress/recursive_property_redefine_during_inline_caching.js: Added test case for bug.
+        (test):
+        
</ins><span class="cx"> 2014-12-01  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Crash (integer overflow) beneath ByteCodeParser::handleGetById typing in search field on weather.com
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit26SourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/jit/JITOperations.cpp (178285 => 178286)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/jit/JITOperations.cpp        2015-01-12 18:41:38 UTC (rev 178285)
+++ releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/jit/JITOperations.cpp        2015-01-12 18:47:26 UTC (rev 178286)
</span><span class="lines">@@ -147,12 +147,12 @@
</span><span class="cx"> 
</span><span class="cx">     JSValue baseValue = JSValue::decode(base);
</span><span class="cx">     PropertySlot slot(baseValue);
</span><del>-    JSValue result = baseValue.get(exec, ident, slot);
-
</del><ins>+    bool hasResult = baseValue.getPropertySlot(exec, ident, slot);
+    
</ins><span class="cx">     if (accessType == static_cast&lt;AccessType&gt;(stubInfo-&gt;accessType))
</span><span class="cx">         buildGetByIDList(exec, baseValue, ident, slot, *stubInfo);
</span><span class="cx"> 
</span><del>-    return JSValue::encode(result);
</del><ins>+    return JSValue::encode(hasResult? slot.getValue(exec, ident) : jsUndefined());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, StringImpl* uid)
</span><span class="lines">@@ -160,18 +160,15 @@
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="cx">     Identifier ident = uid-&gt;isEmptyUnique() ? Identifier::from(PrivateName(uid)) : Identifier(vm, uid);
</span><del>-    AccessType accessType = static_cast&lt;AccessType&gt;(stubInfo-&gt;accessType);
</del><span class="cx"> 
</span><span class="cx">     JSValue baseValue = JSValue::decode(base);
</span><span class="cx">     PropertySlot slot(baseValue);
</span><span class="cx">     JSValue result = baseValue.get(exec, ident, slot);
</span><span class="cx">     
</span><del>-    if (accessType == static_cast&lt;AccessType&gt;(stubInfo-&gt;accessType)) {
-        if (stubInfo-&gt;seen)
-            repatchGetByID(exec, baseValue, ident, slot, *stubInfo);
-        else
-            stubInfo-&gt;seen = true;
-    }
</del><ins>+    if (stubInfo-&gt;seen)
+        repatchGetByID(exec, baseValue, ident, slot, *stubInfo);
+    else
+        stubInfo-&gt;seen = true;
</ins><span class="cx"> 
</span><span class="cx">     return JSValue::encode(result);
</span><span class="cx"> }
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit26SourceJavaScriptCoreruntimeJSCJSValueh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/runtime/JSCJSValue.h (178285 => 178286)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/runtime/JSCJSValue.h        2015-01-12 18:41:38 UTC (rev 178285)
+++ releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/runtime/JSCJSValue.h        2015-01-12 18:47:26 UTC (rev 178286)
</span><span class="lines">@@ -262,6 +262,9 @@
</span><span class="cx">     JSValue get(ExecState*, PropertyName, PropertySlot&amp;) const;
</span><span class="cx">     JSValue get(ExecState*, unsigned propertyName) const;
</span><span class="cx">     JSValue get(ExecState*, unsigned propertyName, PropertySlot&amp;) const;
</span><ins>+
+    bool getPropertySlot(ExecState*, PropertyName, PropertySlot&amp;) const;
+
</ins><span class="cx">     void put(ExecState*, PropertyName, JSValue, PutPropertySlot&amp;);
</span><span class="cx">     JS_EXPORT_PRIVATE void putToPrimitive(ExecState*, PropertyName, JSValue, PutPropertySlot&amp;);
</span><span class="cx">     JS_EXPORT_PRIVATE void putToPrimitiveByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit26SourceJavaScriptCoreruntimeJSCJSValueInlinesh"></a>
<div class="modfile"><h4>Modified: releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/runtime/JSCJSValueInlines.h (178285 => 178286)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/runtime/JSCJSValueInlines.h        2015-01-12 18:41:38 UTC (rev 178285)
+++ releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/runtime/JSCJSValueInlines.h        2015-01-12 18:47:26 UTC (rev 178286)
</span><span class="lines">@@ -682,19 +682,23 @@
</span><span class="cx"> 
</span><span class="cx"> ALWAYS_INLINE JSValue JSValue::get(ExecState* exec, PropertyName propertyName, PropertySlot&amp; slot) const
</span><span class="cx"> {
</span><ins>+    return getPropertySlot(exec, propertyName, slot) ? 
+        slot.getValue(exec, propertyName) : jsUndefined();
+}
+
+ALWAYS_INLINE bool JSValue::getPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot&amp; slot) const
+{
</ins><span class="cx">     // If this is a primitive, we'll need to synthesize the prototype -
</span><span class="cx">     // and if it's a string there are special properties to check first.
</span><span class="cx">     JSObject* object;
</span><span class="cx">     if (UNLIKELY(!isObject())) {
</span><span class="cx">         if (isCell() &amp;&amp; asString(*this)-&gt;getStringPropertySlot(exec, propertyName, slot))
</span><del>-            return slot.getValue(exec, propertyName);
</del><ins>+            return true;
</ins><span class="cx">         object = synthesizePrototype(exec);
</span><span class="cx">     } else
</span><span class="cx">         object = asObject(asCell());
</span><span class="cx">     
</span><del>-    if (object-&gt;getPropertySlot(exec, propertyName, slot))
-        return slot.getValue(exec, propertyName);
-    return jsUndefined();
</del><ins>+    return object-&gt;getPropertySlot(exec, propertyName, slot);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ALWAYS_INLINE JSValue JSValue::get(ExecState* exec, unsigned propertyName) const
</span></span></pre></div>
<a id="releasesWebKitGTKwebkit26SourceJavaScriptCoretestsstressrecursive_property_redefine_during_inline_cachingjs"></a>
<div class="addfile"><h4>Added: releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/tests/stress/recursive_property_redefine_during_inline_caching.js (0 => 178286)</h4>
<pre class="diff"><span>
<span class="info">--- releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/tests/stress/recursive_property_redefine_during_inline_caching.js                                (rev 0)
+++ releases/WebKitGTK/webkit-2.6/Source/JavaScriptCore/tests/stress/recursive_property_redefine_during_inline_caching.js        2015-01-12 18:47:26 UTC (rev 178286)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+// to be run with useLLInt = false
+var o = {};
+
+function getSomeProperty(){
+    return o.someProperty;
+}
+
+var count = 0;
+function test(){
+    count++;
+    if (count == 3) {
+        Object.defineProperty(this, 'someProperty', { value : &quot;okay&quot; });
+        return getSomeProperty();
+    }
+    return &quot;okay&quot;;
+}
+
+o.__defineGetter__('someProperty', test)
+
+for (var i = 0; i &lt; 4; i++) {
+    if (getSomeProperty() != &quot;okay&quot;)
+        throw (&quot;Error: &quot; + i);
+}
</ins></span></pre>
</div>
</div>

</body>
</html>