Title: [137700] trunk
Revision
137700
Author
[email protected]
Date
2012-12-13 19:24:28 -0800 (Thu, 13 Dec 2012)

Log Message

Named lookups on HTML documents produce inconsistent results in _javascript_Core bindings
https://bugs.webkit.org/show_bug.cgi?id=104623

Reviewed by Geoffrey Garen.

Source/_javascript_Core: 

Add the notion of objects that HasImpureGetOwnPropertySlot, and use that to inhibit prototype chain caching
in some cases. This appears to be perf-neutral on benchmarks that we track.

* dfg/DFGRepatch.cpp:
(JSC::DFG::tryCacheGetByID):
(JSC::DFG::tryBuildGetByIDProtoList):
* jit/JITStubs.cpp:
(JSC::JITThunks::tryCacheGetByID):
(JSC::DEFINE_STUB_FUNCTION):
* runtime/JSTypeInfo.h:
(JSC):
(JSC::TypeInfo::hasImpureGetOwnPropertySlot):
* runtime/Operations.h:
(JSC::normalizePrototypeChainForChainAccess):

Source/WebCore: 

All DOM objects that have named getters or directly override getOwnPropertySlot are now marked as
HasImpureGetOwnPropertySlot.

Tests: fast/js/prototype-chain-caching-with-impure-get-own-property-slot-traps
       fast/js/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateHeader):

LayoutTests: 

* fast/js/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps-expected.txt: Added.
* fast/js/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps.html: Added.
* fast/js/prototype-chain-caching-with-impure-get-own-property-slot-traps-expected.txt: Added.
* fast/js/prototype-chain-caching-with-impure-get-own-property-slot-traps.html: Added.
* fast/js/script-tests/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps.js: Added.
(f):
* fast/js/script-tests/prototype-chain-caching-with-impure-get-own-property-slot-traps.js: Added.
(f):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (137699 => 137700)


--- trunk/LayoutTests/ChangeLog	2012-12-14 03:16:43 UTC (rev 137699)
+++ trunk/LayoutTests/ChangeLog	2012-12-14 03:24:28 UTC (rev 137700)
@@ -1,3 +1,19 @@
+2012-12-13  Filip Pizlo  <[email protected]>
+
+        Named lookups on HTML documents produce inconsistent results in _javascript_Core bindings
+        https://bugs.webkit.org/show_bug.cgi?id=104623
+
+        Reviewed by Geoffrey Garen.
+
+        * fast/js/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps-expected.txt: Added.
+        * fast/js/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps.html: Added.
+        * fast/js/prototype-chain-caching-with-impure-get-own-property-slot-traps-expected.txt: Added.
+        * fast/js/prototype-chain-caching-with-impure-get-own-property-slot-traps.html: Added.
+        * fast/js/script-tests/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps.js: Added.
+        (f):
+        * fast/js/script-tests/prototype-chain-caching-with-impure-get-own-property-slot-traps.js: Added.
+        (f):
+
 2012-12-13  Noel Gordon  <[email protected]>
 
         [chromium] Unreviewed gardening.

Added: trunk/LayoutTests/fast/js/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps-expected.txt (0 => 137700)


--- trunk/LayoutTests/fast/js/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps-expected.txt	2012-12-14 03:24:28 UTC (rev 137700)
@@ -0,0 +1,409 @@
+Tests what happens when you make prototype chain accesses with impure GetOwnPropertySlot traps in the way.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps.html (0 => 137700)


--- trunk/LayoutTests/fast/js/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps.html	2012-12-14 03:24:28 UTC (rev 137700)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/js/prototype-chain-caching-with-impure-get-own-property-slot-traps-expected.txt (0 => 137700)


--- trunk/LayoutTests/fast/js/prototype-chain-caching-with-impure-get-own-property-slot-traps-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/prototype-chain-caching-with-impure-get-own-property-slot-traps-expected.txt	2012-12-14 03:24:28 UTC (rev 137700)
@@ -0,0 +1,49 @@
+Tests what happens when you make prototype chain accesses with impure GetOwnPropertySlot traps in the way.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "function"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS typeof f() is "object"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/prototype-chain-caching-with-impure-get-own-property-slot-traps.html (0 => 137700)


--- trunk/LayoutTests/fast/js/prototype-chain-caching-with-impure-get-own-property-slot-traps.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/prototype-chain-caching-with-impure-get-own-property-slot-traps.html	2012-12-14 03:24:28 UTC (rev 137700)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/js/script-tests/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps.js (0 => 137700)


--- trunk/LayoutTests/fast/js/script-tests/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps.js	                        (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps.js	2012-12-14 03:24:28 UTC (rev 137700)
@@ -0,0 +1,21 @@
+description(
+"Tests what happens when you make prototype chain accesses with impure GetOwnPropertySlot traps in the way."
+);
+
+var doc = document;
+
+function f() {
+    return doc.getElementsByTagName;
+}
+
+var expected = "\"function\"";
+for (var i = 0; i < 400; ++i) {
+    if (i == 350) {
+        var img = new Image();
+        img.name = "getElementsByTagName";
+        document.body.appendChild(img);
+        expected = "\"object\"";
+    }
+    shouldBe("typeof f()", expected);
+}
+

Added: trunk/LayoutTests/fast/js/script-tests/prototype-chain-caching-with-impure-get-own-property-slot-traps.js (0 => 137700)


--- trunk/LayoutTests/fast/js/script-tests/prototype-chain-caching-with-impure-get-own-property-slot-traps.js	                        (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/prototype-chain-caching-with-impure-get-own-property-slot-traps.js	2012-12-14 03:24:28 UTC (rev 137700)
@@ -0,0 +1,21 @@
+description(
+"Tests what happens when you make prototype chain accesses with impure GetOwnPropertySlot traps in the way."
+);
+
+var doc = document;
+
+function f() {
+    return doc.getElementsByTagName;
+}
+
+var expected = "\"function\"";
+for (var i = 0; i < 40; ++i) {
+    if (i == 35) {
+        var img = new Image();
+        img.name = "getElementsByTagName";
+        document.body.appendChild(img);
+        expected = "\"object\"";
+    }
+    shouldBe("typeof f()", expected);
+}
+

Modified: trunk/Source/_javascript_Core/ChangeLog (137699 => 137700)


--- trunk/Source/_javascript_Core/ChangeLog	2012-12-14 03:16:43 UTC (rev 137699)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-12-14 03:24:28 UTC (rev 137700)
@@ -1,5 +1,27 @@
 2012-12-13  Filip Pizlo  <[email protected]>
 
+        Named lookups on HTML documents produce inconsistent results in _javascript_Core bindings
+        https://bugs.webkit.org/show_bug.cgi?id=104623
+
+        Reviewed by Geoffrey Garen.
+
+        Add the notion of objects that HasImpureGetOwnPropertySlot, and use that to inhibit prototype chain caching
+        in some cases. This appears to be perf-neutral on benchmarks that we track.
+
+        * dfg/DFGRepatch.cpp:
+        (JSC::DFG::tryCacheGetByID):
+        (JSC::DFG::tryBuildGetByIDProtoList):
+        * jit/JITStubs.cpp:
+        (JSC::JITThunks::tryCacheGetByID):
+        (JSC::DEFINE_STUB_FUNCTION):
+        * runtime/JSTypeInfo.h:
+        (JSC):
+        (JSC::TypeInfo::hasImpureGetOwnPropertySlot):
+        * runtime/Operations.h:
+        (JSC::normalizePrototypeChainForChainAccess):
+
+2012-12-13  Filip Pizlo  <[email protected]>
+
         Unreviewed, roll out http://trac.webkit.org/changeset/137683.
         It broke gmail.
 

Modified: trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp (137699 => 137700)


--- trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2012-12-14 03:16:43 UTC (rev 137699)
+++ trunk/Source/_javascript_Core/dfg/DFGRepatch.cpp	2012-12-14 03:24:28 UTC (rev 137700)
@@ -341,7 +341,7 @@
         return false;
     
     PropertyOffset offset = slot.cachedOffset();
-    size_t count = normalizePrototypeChain(exec, baseValue, slot.slotBase(), propertyName, offset);
+    size_t count = normalizePrototypeChainForChainAccess(exec, baseValue, slot.slotBase(), propertyName, offset);
     if (count == InvalidPrototypeChain)
         return false;
 
@@ -569,7 +569,7 @@
     ASSERT(slot.slotBase().isObject());
     
     PropertyOffset offset = slot.cachedOffset();
-    size_t count = normalizePrototypeChain(exec, baseValue, slot.slotBase(), propertyName, offset);
+    size_t count = normalizePrototypeChainForChainAccess(exec, baseValue, slot.slotBase(), propertyName, offset);
     if (count == InvalidPrototypeChain)
         return false;
 

Modified: trunk/Source/_javascript_Core/jit/JITStubs.cpp (137699 => 137700)


--- trunk/Source/_javascript_Core/jit/JITStubs.cpp	2012-12-14 03:16:43 UTC (rev 137699)
+++ trunk/Source/_javascript_Core/jit/JITStubs.cpp	2012-12-14 03:24:28 UTC (rev 137700)
@@ -908,6 +908,7 @@
 
     // Uncacheable: give up.
     if (!slot.isCacheable()) {
+        stubInfo->accessType = access_get_by_id_generic;
         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
         return;
     }
@@ -916,6 +917,7 @@
     Structure* structure = baseCell->structure();
 
     if (structure->isUncacheableDictionary() || structure->typeInfo().prohibitsPropertyCaching()) {
+        stubInfo->accessType = access_get_by_id_generic;
         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
         return;
     }
@@ -934,6 +936,7 @@
     }
 
     if (structure->isDictionary()) {
+        stubInfo->accessType = access_get_by_id_generic;
         ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
         return;
     }
@@ -943,6 +946,12 @@
         
         JSObject* slotBaseObject = asObject(slot.slotBase());
         size_t offset = slot.cachedOffset();
+
+        if (structure->typeInfo().hasImpureGetOwnPropertySlot()) {
+            stubInfo->accessType = access_get_by_id_generic;
+            ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
+            return;
+        }
         
         // Since we're accessing a prototype in a loop, it's a good bet that it
         // should not be treated as a dictionary.
@@ -960,9 +969,10 @@
     }
 
     PropertyOffset offset = slot.cachedOffset();
-    size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
+    size_t count = normalizePrototypeChainForChainAccess(callFrame, baseValue, slot.slotBase(), propertyName, offset);
     if (count == InvalidPrototypeChain) {
         stubInfo->accessType = access_get_by_id_generic;
+        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
         return;
     }
 
@@ -1689,6 +1699,12 @@
         ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
     else if (slot.slotBase() == baseValue.asCell()->structure()->prototypeForLookup(callFrame)) {
         ASSERT(!baseValue.asCell()->structure()->isDictionary());
+        
+        if (baseValue.asCell()->structure()->typeInfo().hasImpureGetOwnPropertySlot()) {
+            ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
+            return JSValue::encode(result);
+        }
+        
         // Since we're accessing a prototype in a loop, it's a good bet that it
         // should not be treated as a dictionary.
         if (slotBaseObject->structure()->isDictionary()) {
@@ -1705,7 +1721,7 @@
                 ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full));
         }
     } else {
-        size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset);
+        size_t count = normalizePrototypeChainForChainAccess(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);

Modified: trunk/Source/_javascript_Core/runtime/JSTypeInfo.h (137699 => 137700)


--- trunk/Source/_javascript_Core/runtime/JSTypeInfo.h	2012-12-14 03:16:43 UTC (rev 137699)
+++ trunk/Source/_javascript_Core/runtime/JSTypeInfo.h	2012-12-14 03:24:28 UTC (rev 137700)
@@ -46,6 +46,7 @@
     static const unsigned OverridesVisitChildren = 1 << 7;
     static const unsigned OverridesGetPropertyNames = 1 << 8;
     static const unsigned ProhibitsPropertyCaching = 1 << 9;
+    static const unsigned HasImpureGetOwnPropertySlot = 1 << 10;
 
     class TypeInfo {
     public:
@@ -80,6 +81,7 @@
         bool overridesVisitChildren() const { return isSetOnFlags1(OverridesVisitChildren); }
         bool overridesGetPropertyNames() const { return isSetOnFlags2(OverridesGetPropertyNames); }
         bool prohibitsPropertyCaching() const { return isSetOnFlags2(ProhibitsPropertyCaching); }
+        bool hasImpureGetOwnPropertySlot() const { return isSetOnFlags2(HasImpureGetOwnPropertySlot); }
 
         static ptrdiff_t flagsOffset()
         {

Modified: trunk/Source/_javascript_Core/runtime/Operations.h (137699 => 137700)


--- trunk/Source/_javascript_Core/runtime/Operations.h	2012-12-14 03:16:43 UTC (rev 137699)
+++ trunk/Source/_javascript_Core/runtime/Operations.h	2012-12-14 03:24:28 UTC (rev 137700)
@@ -302,15 +302,18 @@
 
 #define InvalidPrototypeChain (std::numeric_limits<size_t>::max())
 
-    inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, PropertyOffset& slotOffset)
+    inline size_t normalizePrototypeChainForChainAccess(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;
             
+            if (cell->structure()->typeInfo().hasImpureGetOwnPropertySlot())
+                return InvalidPrototypeChain;
+            
             JSValue v = cell->structure()->prototypeForLookup(callFrame);
 
             // If we didn't find slotBase in base's prototype chain, then base
@@ -328,7 +331,7 @@
                 if (slotBase == cell)
                     slotOffset = cell->structure()->get(callFrame->globalData(), propertyName); 
             }
-
+            
             ++count;
         }
         

Modified: trunk/Source/WebCore/ChangeLog (137699 => 137700)


--- trunk/Source/WebCore/ChangeLog	2012-12-14 03:16:43 UTC (rev 137699)
+++ trunk/Source/WebCore/ChangeLog	2012-12-14 03:24:28 UTC (rev 137700)
@@ -1,3 +1,19 @@
+2012-12-13  Filip Pizlo  <[email protected]>
+
+        Named lookups on HTML documents produce inconsistent results in _javascript_Core bindings
+        https://bugs.webkit.org/show_bug.cgi?id=104623
+
+        Reviewed by Geoffrey Garen.
+
+        All DOM objects that have named getters or directly override getOwnPropertySlot are now marked as
+        HasImpureGetOwnPropertySlot.
+
+        Tests: fast/js/prototype-chain-caching-with-impure-get-own-property-slot-traps
+               fast/js/dfg-prototype-chain-caching-with-impure-get-own-property-slot-traps
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateHeader):
+
 2012-12-13  Xianzhu Wang  <[email protected]>
 
         Out-of-view check of fixed position element in frame is incorrect when page is scaled

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (137699 => 137700)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2012-12-14 03:16:43 UTC (rev 137699)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2012-12-14 03:24:28 UTC (rev 137700)
@@ -784,16 +784,23 @@
 
     $implIncludes{"${className}Custom.h"} = 1 if !$interface->extendedAttributes->{"JSCustomHeader"} && ($interface->extendedAttributes->{"CustomPutFunction"} || $interface->extendedAttributes->{"CustomNamedSetter"});
 
+    my $hasImpureNamedGetter =
+        $interface->extendedAttributes->{"NamedGetter"}
+        || $interface->extendedAttributes->{"CustomNamedGetter"}
+        || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"};
+
     my $hasComplexGetter =
         $interface->extendedAttributes->{"IndexedGetter"}
         || $interface->extendedAttributes->{"NumericIndexedGetter"}
-        || $interface->extendedAttributes->{"CustomGetOwnPropertySlot"}
         || $interface->extendedAttributes->{"JSCustomGetOwnPropertySlotAndDescriptor"}
-        || $interface->extendedAttributes->{"NamedGetter"}
-        || $interface->extendedAttributes->{"CustomNamedGetter"};
+        || $hasImpureNamedGetter;
     
     my $hasGetter = $numAttributes > 0 || !$interface->extendedAttributes->{"OmitConstructor"} || $hasComplexGetter;
 
+    if ($hasImpureNamedGetter) {
+        $structureFlags{"JSC::HasImpureGetOwnPropertySlot"} = 1;
+    }
+
     # Getters
     if ($hasGetter) {
         push(@headerContent, "    static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);\n");
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to