Title: [176676] trunk/Source/_javascript_Core
Revision
176676
Author
mmir...@apple.com
Date
2014-12-02 11:27:23 -0800 (Tue, 02 Dec 2014)

Log Message

Fixes inline cache fast path accessing nonexistant getters.
<rdar://problem/18416918>
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):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (176675 => 176676)


--- trunk/Source/_javascript_Core/ChangeLog	2014-12-02 19:26:48 UTC (rev 176675)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-12-02 19:27:23 UTC (rev 176676)
@@ -1,3 +1,28 @@
+2014-12-02  Matthew Mirman  <mmir...@apple.com>
+
+        Fixes inline cache fast path accessing nonexistant getters.
+        <rdar://problem/18416918>
+        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):
+        
 2014-12-01  Michael Saboff  <msab...@apple.com>
 
         Remove GetMyScope node from DFG

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (176675 => 176676)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2014-12-02 19:26:48 UTC (rev 176675)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2014-12-02 19:27:23 UTC (rev 176676)
@@ -147,12 +147,12 @@
 
     JSValue baseValue = JSValue::decode(base);
     PropertySlot slot(baseValue);
-    JSValue result = baseValue.get(exec, ident, slot);
-
+    bool hasResult = baseValue.getPropertySlot(exec, ident, slot);
+    
     if (accessType == static_cast<AccessType>(stubInfo->accessType))
         buildGetByIDList(exec, baseValue, ident, slot, *stubInfo);
 
-    return JSValue::encode(result);
+    return JSValue::encode(hasResult? slot.getValue(exec, ident) : jsUndefined());
 }
 
 EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, StringImpl* uid)
@@ -160,18 +160,15 @@
     VM* vm = &exec->vm();
     NativeCallFrameTracer tracer(vm, exec);
     Identifier ident = uid->isEmptyUnique() ? Identifier::from(PrivateName(uid)) : Identifier(vm, uid);
-    AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
 
     JSValue baseValue = JSValue::decode(base);
     PropertySlot slot(baseValue);
     JSValue result = baseValue.get(exec, ident, slot);
     
-    if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
-        if (stubInfo->seen)
-            repatchGetByID(exec, baseValue, ident, slot, *stubInfo);
-        else
-            stubInfo->seen = true;
-    }
+    if (stubInfo->seen)
+        repatchGetByID(exec, baseValue, ident, slot, *stubInfo);
+    else
+        stubInfo->seen = true;
 
     return JSValue::encode(result);
 }

Modified: trunk/Source/_javascript_Core/runtime/JSCJSValue.h (176675 => 176676)


--- trunk/Source/_javascript_Core/runtime/JSCJSValue.h	2014-12-02 19:26:48 UTC (rev 176675)
+++ trunk/Source/_javascript_Core/runtime/JSCJSValue.h	2014-12-02 19:27:23 UTC (rev 176676)
@@ -262,6 +262,9 @@
     JSValue get(ExecState*, PropertyName, PropertySlot&) const;
     JSValue get(ExecState*, unsigned propertyName) const;
     JSValue get(ExecState*, unsigned propertyName, PropertySlot&) const;
+
+    bool getPropertySlot(ExecState*, PropertyName, PropertySlot&) const;
+
     void put(ExecState*, PropertyName, JSValue, PutPropertySlot&);
     JS_EXPORT_PRIVATE void putToPrimitive(ExecState*, PropertyName, JSValue, PutPropertySlot&);
     JS_EXPORT_PRIVATE void putToPrimitiveByIndex(ExecState*, unsigned propertyName, JSValue, bool shouldThrow);

Modified: trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h (176675 => 176676)


--- trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h	2014-12-02 19:26:48 UTC (rev 176675)
+++ trunk/Source/_javascript_Core/runtime/JSCJSValueInlines.h	2014-12-02 19:27:23 UTC (rev 176676)
@@ -682,19 +682,23 @@
 
 ALWAYS_INLINE JSValue JSValue::get(ExecState* exec, PropertyName propertyName, PropertySlot& slot) const
 {
+    return getPropertySlot(exec, propertyName, slot) ? 
+        slot.getValue(exec, propertyName) : jsUndefined();
+}
+
+ALWAYS_INLINE bool JSValue::getPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot) const
+{
     // If this is a primitive, we'll need to synthesize the prototype -
     // and if it's a string there are special properties to check first.
     JSObject* object;
     if (UNLIKELY(!isObject())) {
         if (isCell() && asString(*this)->getStringPropertySlot(exec, propertyName, slot))
-            return slot.getValue(exec, propertyName);
+            return true;
         object = synthesizePrototype(exec);
     } else
         object = asObject(asCell());
     
-    if (object->getPropertySlot(exec, propertyName, slot))
-        return slot.getValue(exec, propertyName);
-    return jsUndefined();
+    return object->getPropertySlot(exec, propertyName, slot);
 }
 
 ALWAYS_INLINE JSValue JSValue::get(ExecState* exec, unsigned propertyName) const

Added: trunk/Source/_javascript_Core/tests/stress/recursive_property_redefine_during_inline_caching.js (0 => 176676)


--- trunk/Source/_javascript_Core/tests/stress/recursive_property_redefine_during_inline_caching.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/recursive_property_redefine_during_inline_caching.js	2014-12-02 19:27:23 UTC (rev 176676)
@@ -0,0 +1,23 @@
+// 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 : "okay" });
+        return getSomeProperty();
+    }
+    return "okay";
+}
+
+o.__defineGetter__('someProperty', test)
+
+for (var i = 0; i < 4; i++) {
+    if (getSomeProperty() != "okay")
+        throw ("Error: " + i);
+}
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to