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");