Title: [234417] releases/WebKitGTK/webkit-2.20
Revision
234417
Author
[email protected]
Date
2018-07-31 02:25:12 -0700 (Tue, 31 Jul 2018)

Log Message

Merge r232313 - LLInt get_by_id prototype caching doesn't properly handle changes
https://bugs.webkit.org/show_bug.cgi?id=186112

Reviewed by Filip Pizlo.

JSTests:

* stress/llint-proto-get-by-id-cache-change-prototype.js: Added.
(foo):
* stress/llint-proto-get-by-id-cache-intercept-value.js: Added.
(foo):

Source/_javascript_Core:

The caching would sometimes fail to track that a prototype had changed
and wouldn't update its set of watchpoints.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finalizeLLIntInlineCaches):
* bytecode/CodeBlock.h:
* bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h:
(JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::key const):
* bytecode/ObjectPropertyConditionSet.h:
(JSC::ObjectPropertyConditionSet::size const):
* bytecode/Watchpoint.h:
(JSC::Watchpoint::Watchpoint): Deleted.
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::setupGetByIdPrototypeCache):

Source/WTF:

Mark some methods const.

* wtf/Bag.h:
(WTF::Bag::begin const):
(WTF::Bag::end const):
(WTF::Bag::unwrappedHead const):
(WTF::Bag::end): Deleted.
(WTF::Bag::unwrappedHead): Deleted.

Modified Paths

Added Paths

Diff

Modified: releases/WebKitGTK/webkit-2.20/JSTests/ChangeLog (234416 => 234417)


--- releases/WebKitGTK/webkit-2.20/JSTests/ChangeLog	2018-07-31 09:25:02 UTC (rev 234416)
+++ releases/WebKitGTK/webkit-2.20/JSTests/ChangeLog	2018-07-31 09:25:12 UTC (rev 234417)
@@ -1,3 +1,15 @@
+2018-05-30  Keith Miller  <[email protected]>
+
+        LLInt get_by_id prototype caching doesn't properly handle changes
+        https://bugs.webkit.org/show_bug.cgi?id=186112
+
+        Reviewed by Filip Pizlo.
+
+        * stress/llint-proto-get-by-id-cache-change-prototype.js: Added.
+        (foo):
+        * stress/llint-proto-get-by-id-cache-intercept-value.js: Added.
+        (foo):
+
 2018-05-25  Mark Lam  <[email protected]>
 
         for-in loops should preserve and restore the TDZ stack for each of its internal loops.

Added: releases/WebKitGTK/webkit-2.20/JSTests/stress/llint-proto-get-by-id-cache-change-prototype.js (0 => 234417)


--- releases/WebKitGTK/webkit-2.20/JSTests/stress/llint-proto-get-by-id-cache-change-prototype.js	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.20/JSTests/stress/llint-proto-get-by-id-cache-change-prototype.js	2018-07-31 09:25:12 UTC (rev 234417)
@@ -0,0 +1,19 @@
+let p = Object.create({ foo: 1 });
+let o = Object.create(p);
+
+let other = { foo: 10 };
+
+function foo() {
+    return o.foo
+}
+
+for (let i = 0; i < 10; i++)
+    foo();
+
+p.__proto__ = null;
+gc();
+
+Object.defineProperty(other, "foo", { get() { } });
+
+if (foo() !== undefined)
+    throw new Error("bad get by id access");

Added: releases/WebKitGTK/webkit-2.20/JSTests/stress/llint-proto-get-by-id-cache-intercept-value.js (0 => 234417)


--- releases/WebKitGTK/webkit-2.20/JSTests/stress/llint-proto-get-by-id-cache-intercept-value.js	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.20/JSTests/stress/llint-proto-get-by-id-cache-intercept-value.js	2018-07-31 09:25:12 UTC (rev 234417)
@@ -0,0 +1,17 @@
+let p = Object.create({ foo: 1 });
+let o = Object.create(p);
+
+let other = { foo: 10 };
+
+function foo() {
+    return o.foo
+}
+
+for (let i = 0; i < 10; i++)
+    foo();
+
+p.foo = null;
+gc();
+
+if (foo() !== null)
+    throw new Error("bad get by id access");

Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ChangeLog (234416 => 234417)


--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ChangeLog	2018-07-31 09:25:02 UTC (rev 234416)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ChangeLog	2018-07-31 09:25:12 UTC (rev 234417)
@@ -1,3 +1,25 @@
+2018-05-30  Keith Miller  <[email protected]>
+
+        LLInt get_by_id prototype caching doesn't properly handle changes
+        https://bugs.webkit.org/show_bug.cgi?id=186112
+
+        Reviewed by Filip Pizlo.
+
+        The caching would sometimes fail to track that a prototype had changed
+        and wouldn't update its set of watchpoints.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finalizeLLIntInlineCaches):
+        * bytecode/CodeBlock.h:
+        * bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h:
+        (JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::key const):
+        * bytecode/ObjectPropertyConditionSet.h:
+        (JSC::ObjectPropertyConditionSet::size const):
+        * bytecode/Watchpoint.h:
+        (JSC::Watchpoint::Watchpoint): Deleted.
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::setupGetByIdPrototypeCache):
+
 2018-05-25  Mark Lam  <[email protected]>
 
         for-in loops should preserve and restore the TDZ stack for each of its internal loops.

Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/CodeBlock.cpp (234416 => 234417)


--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/CodeBlock.cpp	2018-07-31 09:25:02 UTC (rev 234416)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/CodeBlock.cpp	2018-07-31 09:25:12 UTC (rev 234417)
@@ -1241,9 +1241,7 @@
     for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) {
         Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]];
         switch (Interpreter::getOpcodeID(curInstruction[0])) {
-        case op_get_by_id:
-        case op_get_by_id_proto_load:
-        case op_get_by_id_unset: {
+        case op_get_by_id: {
             StructureID oldStructureID = curInstruction[4].u.structureID;
             if (!oldStructureID || Heap::isMarked(vm.heap.structureIDTable().get(oldStructureID)))
                 break;
@@ -1282,6 +1280,8 @@
         // We need to add optimizations for op_resolve_scope_for_hoisting_func_decl_in_eval to do link time scope resolution.
         case op_resolve_scope_for_hoisting_func_decl_in_eval:
             break;
+        case op_get_by_id_proto_load:
+        case op_get_by_id_unset:
         case op_get_array_length:
             break;
         case op_to_this:
@@ -1339,8 +1339,27 @@
 
     // We can't just remove all the sets when we clear the caches since we might have created a watchpoint set
     // then cleared the cache without GCing in between.
-    m_llintGetByIdWatchpointMap.removeIf([](const StructureWatchpointMap::KeyValuePairType& pair) -> bool {
-        return !Heap::isMarked(pair.key);
+    m_llintGetByIdWatchpointMap.removeIf([&] (const StructureWatchpointMap::KeyValuePairType& pair) -> bool {
+        auto clear = [&] () {
+            Instruction* instruction = std::get<1>(pair.key);
+            OpcodeID opcode = Interpreter::getOpcodeID(*instruction);
+            if (opcode == op_get_by_id_proto_load || opcode == op_get_by_id_unset) {
+                if (Options::verboseOSR())
+                    dataLogF("Clearing LLInt property access.\n");
+                clearLLIntGetByIdCache(instruction);
+            }
+            return true;
+        };
+
+        if (!Heap::isMarked(std::get<0>(pair.key)))
+            return clear();
+
+        for (const LLIntPrototypeLoadAdaptiveStructureWatchpoint* watchpoint : pair.value) {
+            if (!watchpoint->key().isStillLive())
+                return clear();
+        }
+
+        return false;
     });
 
     for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {

Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/CodeBlock.h (234416 => 234417)


--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/CodeBlock.h	2018-07-31 09:25:02 UTC (rev 234416)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/CodeBlock.h	2018-07-31 09:25:12 UTC (rev 234417)
@@ -625,7 +625,7 @@
         return m_llintExecuteCounter;
     }
 
-    typedef HashMap<Structure*, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>> StructureWatchpointMap;
+    typedef HashMap<std::tuple<Structure*, Instruction*>, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>> StructureWatchpointMap;
     StructureWatchpointMap& llintGetByIdWatchpointMap() { return m_llintGetByIdWatchpointMap; }
 
     // Functions for controlling when tiered compilation kicks in. This

Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h (234416 => 234417)


--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h	2018-07-31 09:25:02 UTC (rev 234416)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h	2018-07-31 09:25:12 UTC (rev 234417)
@@ -33,16 +33,19 @@
 
 class LLIntPrototypeLoadAdaptiveStructureWatchpoint : public Watchpoint {
 public:
+    LLIntPrototypeLoadAdaptiveStructureWatchpoint() = default;
     LLIntPrototypeLoadAdaptiveStructureWatchpoint(const ObjectPropertyCondition&, Instruction*);
 
     void install();
 
+    const ObjectPropertyCondition& key() const { return m_key; }
+
 protected:
     void fireInternal(const FireDetail&) override;
 
 private:
     ObjectPropertyCondition m_key;
-    Instruction* m_getByIdInstruction;
+    Instruction* m_getByIdInstruction { nullptr };
 };
 
 } // namespace JSC

Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.h (234416 => 234417)


--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.h	2018-07-31 09:25:02 UTC (rev 234416)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/ObjectPropertyConditionSet.h	2018-07-31 09:25:12 UTC (rev 234417)
@@ -67,7 +67,8 @@
     }
 
     bool isValidAndWatchable() const;
-    
+
+    size_t size() const { return m_data ? m_data->vector.size() : 0; }
     bool isEmpty() const
     {
         return !m_data;

Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/Watchpoint.h (234416 => 234417)


--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/Watchpoint.h	2018-07-31 09:25:02 UTC (rev 234416)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/bytecode/Watchpoint.h	2018-07-31 09:25:12 UTC (rev 234417)
@@ -68,9 +68,7 @@
     WTF_MAKE_NONCOPYABLE(Watchpoint);
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    Watchpoint()
-    {
-    }
+    Watchpoint() = default;
     
     virtual ~Watchpoint();
 

Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (234416 => 234417)


--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2018-07-31 09:25:02 UTC (rev 234416)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2018-07-31 09:25:12 UTC (rev 234417)
@@ -671,15 +671,18 @@
 
     PropertyOffset offset = invalidOffset;
     CodeBlock::StructureWatchpointMap& watchpointMap = codeBlock->llintGetByIdWatchpointMap();
-    auto result = watchpointMap.add(structure, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>());
+    Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint> watchpoints;
     for (ObjectPropertyCondition condition : conditions) {
         if (!condition.isWatchable())
             return;
         if (condition.condition().kind() == PropertyCondition::Presence)
             offset = condition.condition().offset();
-        result.iterator->value.add(condition, pc)->install();
+        watchpoints.add(condition, pc)->install();
     }
+
     ASSERT((offset == invalidOffset) == slot.isUnset());
+    auto result = watchpointMap.add(std::make_tuple(structure, pc), WTFMove(watchpoints));
+    ASSERT_UNUSED(result, result.isNewEntry);
 
     ConcurrentJSLocker locker(codeBlock->m_lock);
 

Modified: releases/WebKitGTK/webkit-2.20/Source/WTF/ChangeLog (234416 => 234417)


--- releases/WebKitGTK/webkit-2.20/Source/WTF/ChangeLog	2018-07-31 09:25:02 UTC (rev 234416)
+++ releases/WebKitGTK/webkit-2.20/Source/WTF/ChangeLog	2018-07-31 09:25:12 UTC (rev 234417)
@@ -1,3 +1,19 @@
+2018-05-30  Keith Miller  <[email protected]>
+
+        LLInt get_by_id prototype caching doesn't properly handle changes
+        https://bugs.webkit.org/show_bug.cgi?id=186112
+
+        Reviewed by Filip Pizlo.
+
+        Mark some methods const.
+
+        * wtf/Bag.h:
+        (WTF::Bag::begin const):
+        (WTF::Bag::end const):
+        (WTF::Bag::unwrappedHead const):
+        (WTF::Bag::end): Deleted.
+        (WTF::Bag::unwrappedHead): Deleted.
+
 2018-04-20  JF Bastien  <[email protected]>
 
         Handle more JSON stringify OOM

Modified: releases/WebKitGTK/webkit-2.20/Source/WTF/wtf/Bag.h (234416 => 234417)


--- releases/WebKitGTK/webkit-2.20/Source/WTF/wtf/Bag.h	2018-07-31 09:25:02 UTC (rev 234416)
+++ releases/WebKitGTK/webkit-2.20/Source/WTF/wtf/Bag.h	2018-07-31 09:25:12 UTC (rev 234417)
@@ -138,13 +138,21 @@
         result.m_node = unwrappedHead();
         return result;
     }
+
+    const iterator begin() const
+    {
+        iterator result;
+        result.m_node = unwrappedHead();
+        return result;
+    }
+
+
+    iterator end() const { return iterator(); }
     
-    iterator end() { return iterator(); }
-    
     bool isEmpty() const { return !m_head; }
     
 private:
-    Node* unwrappedHead() { return PtrTraits::unwrap(m_head); }
+    Node* unwrappedHead() const { return PtrTraits::unwrap(m_head); }
 
     typename PtrTraits::StorageType m_head { nullptr };
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to