Title: [133546] trunk
Revision
133546
Author
[email protected]
Date
2012-11-05 17:53:09 -0800 (Mon, 05 Nov 2012)

Log Message

Prototype chain caching should check that the path from the base object to the slot base involves prototype hops only
https://bugs.webkit.org/show_bug.cgi?id=101276

Reviewed by Gavin Barraclough.

Source/_javascript_Core: 

Changed normalizePrototypeChain() to report an invalid prototype chain if any object is a proxy.
This catches cases where our prototype chain checks would have been insufficient to guard against
newly introduced properties, despecialized properties, or deleted properties in the chain of
objects involved in the access.

* dfg/DFGRepatch.cpp:
(JSC::DFG::tryCacheGetByID):
(JSC::DFG::tryBuildGetByIDProtoList):
(JSC::DFG::tryCachePutByID):
(JSC::DFG::tryBuildPutByIdList):
* jit/JITStubs.cpp:
(JSC::JITThunks::tryCachePutByID):
(JSC::JITThunks::tryCacheGetByID):
(JSC::DEFINE_STUB_FUNCTION):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/Operations.h:
(JSC):
(JSC::normalizePrototypeChain):

LayoutTests: 

This test already covered this case, but only for method_check. Modified it to
also cover the get_by_id case.

* fast/js/toString-and-valueOf-override-expected.txt:
* fast/js/toString-and-valueOf-override.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (133545 => 133546)


--- trunk/LayoutTests/ChangeLog	2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/LayoutTests/ChangeLog	2012-11-06 01:53:09 UTC (rev 133546)
@@ -1,3 +1,16 @@
+2012-11-05  Filip Pizlo  <[email protected]>
+
+        Prototype chain caching should check that the path from the base object to the slot base involves prototype hops only
+        https://bugs.webkit.org/show_bug.cgi?id=101276
+
+        Reviewed by Gavin Barraclough.
+
+        This test already covered this case, but only for method_check. Modified it to
+        also cover the get_by_id case.
+
+        * fast/js/toString-and-valueOf-override-expected.txt:
+        * fast/js/toString-and-valueOf-override.html:
+
 2012-11-05  Mark Lam  <[email protected]>
 
         Fixed flaky fast/xmlhttprequest/xmlhttprequest-recursive-sync-event.html.

Modified: trunk/LayoutTests/fast/js/toString-and-valueOf-override-expected.txt (133545 => 133546)


--- trunk/LayoutTests/fast/js/toString-and-valueOf-override-expected.txt	2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/LayoutTests/fast/js/toString-and-valueOf-override-expected.txt	2012-11-06 01:53:09 UTC (rev 133546)
@@ -3,6 +3,8 @@
 [span] : [object HTMLSpanElement]
 String(span) : [object HTMLSpanElement]
 String([span]) : [object HTMLSpanElement]
+span.toString : function toString() { [native code] }
+span.toString() (cached in variable) : [object Undefined]
 span.toString() : [object HTMLSpanElement]
 [span].toString() : [object HTMLSpanElement]
 span.valueOf() : [object HTMLSpanElement]
@@ -13,6 +15,8 @@
 [span] : toString
 String(span) : toString
 String([span]) : toString
+span.toString : function () { return "toString"; }
+span.toString() (cached in variable) : toString
 span.toString() : toString
 [span].toString() : toString
 span.valueOf() : valueOf
@@ -23,6 +27,8 @@
 [span] : valueOf
 String(span) : valueOf
 String([span]) : valueOf
+span.toString : function () { return new Object(); }
+span.toString() (cached in variable) : [object Object]
 span.toString() : [object Object]
 [span].toString() : valueOf
 span.valueOf() : valueOf
@@ -33,6 +39,8 @@
 [span] : toString
 String(span) : toString
 String([span]) : toString
+span.toString : function () { return 'toString'; }
+span.toString() (cached in variable) : toString
 span.toString() : toString
 [span].toString() : toString
 span.valueOf() : [object Object]
@@ -43,6 +51,8 @@
 TypeError: No default value
 TypeError: No default value
 TypeError: No default value
+span.toString : function () { return new Object(); }
+span.toString() (cached in variable) : [object Object]
 span.toString() : [object Object]
 TypeError: No default value
 span.valueOf() : [object Object]
@@ -53,8 +63,10 @@
 Exception
 Exception
 Exception
+span.toString : function () { throw "Exception"; }
 Exception
 Exception
+Exception
 span.valueOf() : valueOf
 Exception
 
@@ -63,6 +75,8 @@
 [span] : toString
 String(span) : toString
 String([span]) : toString
+span.toString : function () { return 'toString'; }
+span.toString() (cached in variable) : toString
 span.toString() : toString
 [span].toString() : toString
 Exception
@@ -73,10 +87,12 @@
 Exception
 Exception
 Exception
+span.toString : function () { throw "Exception"; }
 Exception
 Exception
 Exception
 Exception
+Exception
 
 
 Unmodified window
@@ -84,6 +100,8 @@
 [window] : [object Window]
 String(window) : [object Window]
 String([window]) : [object Window]
+window.toString : function toString() { [native code] }
+window.toString() (cached in variable) : [object Undefined]
 window.toString() : [object Window]
 [window].toString() : [object Window]
 window.valueOf() : [object Window]
@@ -94,6 +112,8 @@
 [window] : toString
 String(window) : toString
 String([window]) : toString
+window.toString : function () { return "toString"; }
+window.toString() (cached in variable) : toString
 window.toString() : toString
 [window].toString() : toString
 window.valueOf() : valueOf
@@ -104,6 +124,8 @@
 [window] : valueOf
 String(window) : valueOf
 String([window]) : valueOf
+window.toString : function () { return new Object(); }
+window.toString() (cached in variable) : [object Object]
 window.toString() : [object Object]
 [window].toString() : valueOf
 window.valueOf() : valueOf
@@ -114,6 +136,8 @@
 [window] : toString
 String(window) : toString
 String([window]) : toString
+window.toString : function () { return 'toString'; }
+window.toString() (cached in variable) : toString
 window.toString() : toString
 [window].toString() : toString
 window.valueOf() : [object Object]
@@ -124,6 +148,8 @@
 TypeError: No default value
 TypeError: No default value
 TypeError: No default value
+window.toString : function () { return new Object(); }
+window.toString() (cached in variable) : [object Object]
 window.toString() : [object Object]
 TypeError: No default value
 window.valueOf() : [object Object]
@@ -134,8 +160,10 @@
 Exception
 Exception
 Exception
+window.toString : function () { throw "Exception"; }
 Exception
 Exception
+Exception
 window.valueOf() : valueOf
 Exception
 
@@ -144,6 +172,8 @@
 [window] : toString
 String(window) : toString
 String([window]) : toString
+window.toString : function () { return 'toString'; }
+window.toString() (cached in variable) : toString
 window.toString() : toString
 [window].toString() : toString
 Exception
@@ -154,10 +184,12 @@
 Exception
 Exception
 Exception
+window.toString : function () { throw "Exception"; }
 Exception
 Exception
 Exception
 Exception
+Exception
 
 
 Unmodified Navigator
@@ -165,6 +197,8 @@
 [Navigator] : [object Navigator]
 String(Navigator) : [object Navigator]
 String([Navigator]) : [object Navigator]
+Navigator.toString : function toString() { [native code] }
+Navigator.toString() (cached in variable) : [object Undefined]
 Navigator.toString() : [object Navigator]
 [Navigator].toString() : [object Navigator]
 Navigator.valueOf() : [object Navigator]
@@ -175,6 +209,8 @@
 [Navigator] : toString
 String(Navigator) : toString
 String([Navigator]) : toString
+Navigator.toString : function () { return "toString"; }
+Navigator.toString() (cached in variable) : toString
 Navigator.toString() : toString
 [Navigator].toString() : toString
 Navigator.valueOf() : valueOf
@@ -185,6 +221,8 @@
 [Navigator] : valueOf
 String(Navigator) : valueOf
 String([Navigator]) : valueOf
+Navigator.toString : function () { return new Object(); }
+Navigator.toString() (cached in variable) : [object Object]
 Navigator.toString() : [object Object]
 [Navigator].toString() : valueOf
 Navigator.valueOf() : valueOf
@@ -195,6 +233,8 @@
 [Navigator] : toString
 String(Navigator) : toString
 String([Navigator]) : toString
+Navigator.toString : function () { return 'toString'; }
+Navigator.toString() (cached in variable) : toString
 Navigator.toString() : toString
 [Navigator].toString() : toString
 Navigator.valueOf() : [object Object]
@@ -205,6 +245,8 @@
 TypeError: No default value
 TypeError: No default value
 TypeError: No default value
+Navigator.toString : function () { return new Object(); }
+Navigator.toString() (cached in variable) : [object Object]
 Navigator.toString() : [object Object]
 TypeError: No default value
 Navigator.valueOf() : [object Object]
@@ -215,8 +257,10 @@
 Exception
 Exception
 Exception
+Navigator.toString : function () { throw "Exception"; }
 Exception
 Exception
+Exception
 Navigator.valueOf() : valueOf
 Exception
 
@@ -225,6 +269,8 @@
 [Navigator] : toString
 String(Navigator) : toString
 String([Navigator]) : toString
+Navigator.toString : function () { return 'toString'; }
+Navigator.toString() (cached in variable) : toString
 Navigator.toString() : toString
 [Navigator].toString() : toString
 Exception
@@ -235,10 +281,12 @@
 Exception
 Exception
 Exception
+Navigator.toString : function () { throw "Exception"; }
 Exception
 Exception
 Exception
 Exception
+Exception
 
 
 Unmodified History
@@ -246,6 +294,8 @@
 [History] : [object History]
 String(History) : [object History]
 String([History]) : [object History]
+History.toString : function toString() { [native code] }
+History.toString() (cached in variable) : [object Undefined]
 History.toString() : [object History]
 [History].toString() : [object History]
 History.valueOf() : [object History]
@@ -256,6 +306,8 @@
 [History] : toString
 String(History) : toString
 String([History]) : toString
+History.toString : function () { return "toString"; }
+History.toString() (cached in variable) : toString
 History.toString() : toString
 [History].toString() : toString
 History.valueOf() : valueOf
@@ -266,6 +318,8 @@
 [History] : valueOf
 String(History) : valueOf
 String([History]) : valueOf
+History.toString : function () { return new Object(); }
+History.toString() (cached in variable) : [object Object]
 History.toString() : [object Object]
 [History].toString() : valueOf
 History.valueOf() : valueOf
@@ -276,6 +330,8 @@
 [History] : toString
 String(History) : toString
 String([History]) : toString
+History.toString : function () { return 'toString'; }
+History.toString() (cached in variable) : toString
 History.toString() : toString
 [History].toString() : toString
 History.valueOf() : [object Object]
@@ -286,6 +342,8 @@
 TypeError: No default value
 TypeError: No default value
 TypeError: No default value
+History.toString : function () { return new Object(); }
+History.toString() (cached in variable) : [object Object]
 History.toString() : [object Object]
 TypeError: No default value
 History.valueOf() : [object Object]
@@ -296,8 +354,10 @@
 Exception
 Exception
 Exception
+History.toString : function () { throw "Exception"; }
 Exception
 Exception
+Exception
 History.valueOf() : valueOf
 Exception
 
@@ -306,6 +366,8 @@
 [History] : toString
 String(History) : toString
 String([History]) : toString
+History.toString : function () { return 'toString'; }
+History.toString() (cached in variable) : toString
 History.toString() : toString
 [History].toString() : toString
 Exception
@@ -316,10 +378,12 @@
 Exception
 Exception
 Exception
+History.toString : function () { throw "Exception"; }
 Exception
 Exception
 Exception
 Exception
+Exception
 
 
 Unmodified Selection
@@ -327,6 +391,8 @@
 [Selection] : 
 String(Selection) : 
 String([Selection]) : 
+Selection.toString : function toString() { [native code] }
+TypeError: Type error
 Selection.toString() : 
 [Selection].toString() : 
 Selection.valueOf() : 
@@ -337,6 +403,8 @@
 [Selection] : toString
 String(Selection) : toString
 String([Selection]) : toString
+Selection.toString : function () { return "toString"; }
+Selection.toString() (cached in variable) : toString
 Selection.toString() : toString
 [Selection].toString() : toString
 Selection.valueOf() : valueOf
@@ -347,6 +415,8 @@
 [Selection] : valueOf
 String(Selection) : valueOf
 String([Selection]) : valueOf
+Selection.toString : function () { return new Object(); }
+Selection.toString() (cached in variable) : [object Object]
 Selection.toString() : [object Object]
 [Selection].toString() : valueOf
 Selection.valueOf() : valueOf
@@ -357,6 +427,8 @@
 [Selection] : toString
 String(Selection) : toString
 String([Selection]) : toString
+Selection.toString : function () { return 'toString'; }
+Selection.toString() (cached in variable) : toString
 Selection.toString() : toString
 [Selection].toString() : toString
 Selection.valueOf() : [object Object]
@@ -367,6 +439,8 @@
 TypeError: No default value
 TypeError: No default value
 TypeError: No default value
+Selection.toString : function () { return new Object(); }
+Selection.toString() (cached in variable) : [object Object]
 Selection.toString() : [object Object]
 TypeError: No default value
 Selection.valueOf() : [object Object]
@@ -377,8 +451,10 @@
 Exception
 Exception
 Exception
+Selection.toString : function () { throw "Exception"; }
 Exception
 Exception
+Exception
 Selection.valueOf() : valueOf
 Exception
 
@@ -387,6 +463,8 @@
 [Selection] : toString
 String(Selection) : toString
 String([Selection]) : toString
+Selection.toString : function () { return 'toString'; }
+Selection.toString() (cached in variable) : toString
 Selection.toString() : toString
 [Selection].toString() : toString
 Exception
@@ -397,10 +475,12 @@
 Exception
 Exception
 Exception
+Selection.toString : function () { throw "Exception"; }
 Exception
 Exception
 Exception
 Exception
+Exception
 
 
 

Modified: trunk/LayoutTests/fast/js/toString-and-valueOf-override.html (133545 => 133546)


--- trunk/LayoutTests/fast/js/toString-and-valueOf-override.html	2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/LayoutTests/fast/js/toString-and-valueOf-override.html	2012-11-06 01:53:09 UTC (rev 133546)
@@ -12,6 +12,8 @@
             try { print('[' + type + '] : ' + [object]); } catch(e) { print(e); }
             try { print('String(' + type + ') : ' + String(object)); } catch(e) { print(e); }
             try { print('String([' + type + ']) : ' + String([object])); } catch(e) { print(e); }
+            try { print(type + '.toString : ' + object.toString); } catch(e) { print(e); }
+            try { var toString = object.toString; print(type + '.toString() (cached in variable) : ' + toString()); } catch(e) { print(e); }
             try { print(type + '.toString() : ' + object.toString()); } catch(e) { print(e); }
             try { print('[' + type + '].toString() : ' + [object].toString()); } catch(e) { print(e); }
             try { print(type + '.valueOf() : ' + object.valueOf()); } catch(e) { print(e); }

Modified: trunk/Source/_javascript_Core/ChangeLog (133545 => 133546)


--- trunk/Source/_javascript_Core/ChangeLog	2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-11-06 01:53:09 UTC (rev 133546)
@@ -1,3 +1,30 @@
+2012-11-05  Filip Pizlo  <[email protected]>
+
+        Prototype chain caching should check that the path from the base object to the slot base involves prototype hops only
+        https://bugs.webkit.org/show_bug.cgi?id=101276
+
+        Reviewed by Gavin Barraclough.
+
+        Changed normalizePrototypeChain() to report an invalid prototype chain if any object is a proxy.
+        This catches cases where our prototype chain checks would have been insufficient to guard against
+        newly introduced properties, despecialized properties, or deleted properties in the chain of
+        objects involved in the access.
+
+        * dfg/DFGRepatch.cpp:
+        (JSC::DFG::tryCacheGetByID):
+        (JSC::DFG::tryBuildGetByIDProtoList):
+        (JSC::DFG::tryCachePutByID):
+        (JSC::DFG::tryBuildPutByIdList):
+        * jit/JITStubs.cpp:
+        (JSC::JITThunks::tryCachePutByID):
+        (JSC::JITThunks::tryCacheGetByID):
+        (JSC::DEFINE_STUB_FUNCTION):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/Operations.h:
+        (JSC):
+        (JSC::normalizePrototypeChain):
+
 2012-11-05  Dima Gorbik  <[email protected]>
 
         Back out controversial changes from Bug 98665.

Modified: trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp (133545 => 133546)


--- trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2012-11-06 01:53:09 UTC (rev 133546)
@@ -324,7 +324,7 @@
     
     PropertyOffset offset = slot.cachedOffset();
     size_t count = normalizePrototypeChain(exec, baseValue, slot.slotBase(), propertyName, offset);
-    if (!count)
+    if (count == InvalidPrototypeChain)
         return false;
 
     StructureChain* prototypeChain = structure->prototypeChain(exec);
@@ -550,7 +550,7 @@
     
     PropertyOffset offset = slot.cachedOffset();
     size_t count = normalizePrototypeChain(exec, baseValue, slot.slotBase(), propertyName, offset);
-    if (!count)
+    if (count == InvalidPrototypeChain)
         return false;
 
     Structure* structure = baseValue.asCell()->structure();
@@ -964,7 +964,8 @@
             if (hasIndexingHeader(oldStructure->indexingType()))
                 return false;
             
-            normalizePrototypeChain(exec, baseCell);
+            if (normalizePrototypeChain(exec, baseCell) == InvalidPrototypeChain)
+                return false;
             
             StructureChain* prototypeChain = structure->prototypeChain(exec);
             
@@ -1035,7 +1036,8 @@
             if (hasIndexingHeader(oldStructure->indexingType()))
                 return false;
             
-            normalizePrototypeChain(exec, baseCell);
+            if (normalizePrototypeChain(exec, baseCell) == InvalidPrototypeChain)
+                return false;
             
             StructureChain* prototypeChain = structure->prototypeChain(exec);
             

Modified: trunk/Source/_javascript_Core/jit/JITStubs.cpp (133545 => 133546)


--- trunk/Source/_javascript_Core/jit/JITStubs.cpp	2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/jit/JITStubs.cpp	2012-11-06 01:53:09 UTC (rev 133546)
@@ -864,7 +864,10 @@
         }
 
         // put_by_id_transition checks the prototype chain for setters.
-        normalizePrototypeChain(callFrame, baseCell);
+        if (normalizePrototypeChain(callFrame, baseCell) == InvalidPrototypeChain) {
+            ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(direct ? cti_op_put_by_id_direct_generic : cti_op_put_by_id_generic));
+            return;
+        }
 
         StructureChain* prototypeChain = structure->prototypeChain(callFrame);
         ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
@@ -937,7 +940,7 @@
 
     if (slot.slotBase() == structure->prototypeForLookup(callFrame)) {
         ASSERT(slot.slotBase().isObject());
-
+        
         JSObject* slotBaseObject = asObject(slot.slotBase());
         size_t offset = slot.cachedOffset();
         
@@ -958,7 +961,7 @@
 
     PropertyOffset offset = slot.cachedOffset();
     size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
-    if (!count) {
+    if (count == InvalidPrototypeChain) {
         stubInfo->accessType = access_get_by_id_generic;
         return;
     }
@@ -1873,7 +1876,13 @@
             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
         }
-    } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) {
+    } else {
+        size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
+        if (count == InvalidPrototypeChain) {
+            ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
+            return JSValue::encode(result);
+        }
+        
         ASSERT(!baseValue.asCell()->structure()->isDictionary());
         int listIndex;
         PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(callFrame->globalData(), codeBlock->ownerExecutable(), stubInfo, listIndex);
@@ -1885,8 +1894,7 @@
             if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
         }
-    } else
-        ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
+    }
 
     return JSValue::encode(result);
 }

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (133545 => 133546)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2012-11-06 01:53:09 UTC (rev 133546)
@@ -1001,32 +1001,32 @@
                     // below may GC.
                     pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id);
 
-                    normalizePrototypeChain(exec, baseCell);
-                    
-                    ASSERT(structure->previousID()->isObject());
-                    pc[4].u.structure.set(
-                        globalData, codeBlock->ownerExecutable(), structure->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(
-                        globalData, codeBlock->ownerExecutable(), structure);
-                    StructureChain* chain = structure->prototypeChain(exec);
-                    ASSERT(chain);
-                    pc[7].u.structureChain.set(
-                        globalData, codeBlock->ownerExecutable(), chain);
-                    
-                    if (pc[8].u.operand) {
+                    if (normalizePrototypeChain(exec, baseCell) != InvalidPrototypeChain) {
+                        ASSERT(structure->previousID()->isObject());
+                        pc[4].u.structure.set(
+                            globalData, codeBlock->ownerExecutable(), structure->previousID());
                         if (isInlineOffset(slot.cachedOffset()))
-                            pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_direct);
+                            pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage();
                         else
-                            pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_direct_out_of_line);
-                    } else {
-                        if (isInlineOffset(slot.cachedOffset()))
-                            pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_normal);
-                        else
-                            pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_normal_out_of_line);
+                            pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue);
+                        pc[6].u.structure.set(
+                            globalData, codeBlock->ownerExecutable(), structure);
+                        StructureChain* chain = structure->prototypeChain(exec);
+                        ASSERT(chain);
+                        pc[7].u.structureChain.set(
+                            globalData, codeBlock->ownerExecutable(), chain);
+                    
+                        if (pc[8].u.operand) {
+                            if (isInlineOffset(slot.cachedOffset()))
+                                pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_direct);
+                            else
+                                pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_direct_out_of_line);
+                        } else {
+                            if (isInlineOffset(slot.cachedOffset()))
+                                pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_normal);
+                            else
+                                pc[0].u.opcode = LLInt::getOpcode(llint_op_put_by_id_transition_normal_out_of_line);
+                        }
                     }
                 }
             } else {

Modified: trunk/Source/_javascript_Core/runtime/JSCell.h (133545 => 133546)


--- trunk/Source/_javascript_Core/runtime/JSCell.h	2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/runtime/JSCell.h	2012-11-06 01:53:09 UTC (rev 133546)
@@ -75,6 +75,7 @@
         bool isString() const;
         bool isObject() const;
         bool isGetterSetter() const;
+        bool isProxy() const;
         bool inherits(const ClassInfo*) const;
         bool isAPIValueWrapper() const;
 

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (133545 => 133546)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2012-11-06 01:53:09 UTC (rev 133546)
@@ -525,7 +525,6 @@
         bool isNameScopeObject() const;
         bool isActivationObject() const;
         bool isErrorInstance() const;
-        bool isProxy() const;
 
         void seal(JSGlobalData&);
         void freeze(JSGlobalData&);
@@ -934,11 +933,6 @@
     return structure()->typeInfo().type() == ErrorInstanceType;
 }
 
-inline bool JSObject::isProxy() const
-{
-    return structure()->typeInfo().type() == ProxyType;
-}
-
 inline void JSObject::setButterfly(JSGlobalData& globalData, Butterfly* butterfly, Structure* structure)
 {
     ASSERT(structure);

Modified: trunk/Source/_javascript_Core/runtime/Operations.h (133545 => 133546)


--- trunk/Source/_javascript_Core/runtime/Operations.h	2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/runtime/Operations.h	2012-11-06 01:53:09 UTC (rev 133546)
@@ -24,6 +24,7 @@
 
 #include "ExceptionHelpers.h"
 #include "Interpreter.h"
+#include "JSProxy.h"
 #include "JSString.h"
 #include "JSValueInlineMethods.h"
 
@@ -297,19 +298,24 @@
         return jsAddSlowCase(callFrame, v1, v2);
     }
 
+#define InvalidPrototypeChain (std::numeric_limits<size_t>::max())
+
     inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, PropertyOffset& slotOffset)
     {
         JSCell* cell = base.asCell();
         size_t count = 0;
 
         while (slotBase != cell) {
+            if (cell->isProxy())
+                return InvalidPrototypeChain;
+            
             JSValue v = cell->structure()->prototypeForLookup(callFrame);
 
             // If we didn't find slotBase in base's prototype chain, then base
             // must be a proxy for another object.
 
             if (v.isNull())
-                return 0;
+                return InvalidPrototypeChain;
 
             cell = v.asCell();
 
@@ -332,6 +338,9 @@
     {
         size_t count = 0;
         while (1) {
+            if (base->isProxy())
+                return InvalidPrototypeChain;
+            
             JSValue v = base->structure()->prototypeForLookup(callFrame);
             if (v.isNull())
                 return count;

Modified: trunk/Source/_javascript_Core/runtime/Structure.h (133545 => 133546)


--- trunk/Source/_javascript_Core/runtime/Structure.h	2012-11-06 01:48:19 UTC (rev 133545)
+++ trunk/Source/_javascript_Core/runtime/Structure.h	2012-11-06 01:53:09 UTC (rev 133546)
@@ -521,6 +521,11 @@
         return m_structure->typeInfo().type() == GetterSetterType;
     }
 
+    inline bool JSCell::isProxy() const
+    {
+        return structure()->typeInfo().type() == ProxyType;
+    }
+
     inline bool JSCell::isAPIValueWrapper() const
     {
         return m_structure->typeInfo().type() == APIValueWrapperType;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to