Changeset 232313 in webkit


Ignore:
Timestamp:
May 30, 2018 4:07:16 PM (6 years ago)
Author:
keith_miller@apple.com
Message:

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/JavaScriptCore:

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.

Location:
trunk
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r232295 r232313  
     12018-05-30  Keith Miller  <keith_miller@apple.com>
     2
     3        LLInt get_by_id prototype caching doesn't properly handle changes
     4        https://bugs.webkit.org/show_bug.cgi?id=186112
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * stress/llint-proto-get-by-id-cache-change-prototype.js: Added.
     9        (foo):
     10        * stress/llint-proto-get-by-id-cache-intercept-value.js: Added.
     11        (foo):
     12
    1132018-05-30  Caio Lima  <ticaiolima@gmail.com>
    214
  • trunk/Source/JavaScriptCore/ChangeLog

    r232295 r232313  
     12018-05-30  Keith Miller  <keith_miller@apple.com>
     2
     3        LLInt get_by_id prototype caching doesn't properly handle changes
     4        https://bugs.webkit.org/show_bug.cgi?id=186112
     5
     6        Reviewed by Filip Pizlo.
     7
     8        The caching would sometimes fail to track that a prototype had changed
     9        and wouldn't update its set of watchpoints.
     10
     11        * bytecode/CodeBlock.cpp:
     12        (JSC::CodeBlock::finalizeLLIntInlineCaches):
     13        * bytecode/CodeBlock.h:
     14        * bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h:
     15        (JSC::LLIntPrototypeLoadAdaptiveStructureWatchpoint::key const):
     16        * bytecode/ObjectPropertyConditionSet.h:
     17        (JSC::ObjectPropertyConditionSet::size const):
     18        * bytecode/Watchpoint.h:
     19        (JSC::Watchpoint::Watchpoint): Deleted.
     20        * llint/LLIntSlowPaths.cpp:
     21        (JSC::LLInt::setupGetByIdPrototypeCache):
     22
    1232018-05-30  Caio Lima  <ticaiolima@gmail.com>
    224
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r232070 r232313  
    12601260        Instruction* curInstruction = &instructions()[propertyAccessInstructions[i]];
    12611261        switch (Interpreter::getOpcodeID(curInstruction[0])) {
    1262         case op_get_by_id:
    1263         case op_get_by_id_proto_load:
    1264         case op_get_by_id_unset: {
     1262        case op_get_by_id: {
    12651263            StructureID oldStructureID = curInstruction[4].u.structureID;
    12661264            if (!oldStructureID || Heap::isMarked(vm.heap.structureIDTable().get(oldStructureID)))
     
    13011299        case op_resolve_scope_for_hoisting_func_decl_in_eval:
    13021300            break;
     1301        case op_get_by_id_proto_load:
     1302        case op_get_by_id_unset:
    13031303        case op_get_array_length:
    13041304            break;
     
    13581358    // We can't just remove all the sets when we clear the caches since we might have created a watchpoint set
    13591359    // then cleared the cache without GCing in between.
    1360     m_llintGetByIdWatchpointMap.removeIf([](const StructureWatchpointMap::KeyValuePairType& pair) -> bool {
    1361         return !Heap::isMarked(pair.key);
     1360    m_llintGetByIdWatchpointMap.removeIf([&] (const StructureWatchpointMap::KeyValuePairType& pair) -> bool {
     1361        auto clear = [&] () {
     1362            Instruction* instruction = std::get<1>(pair.key);
     1363            OpcodeID opcode = Interpreter::getOpcodeID(*instruction);
     1364            if (opcode == op_get_by_id_proto_load || opcode == op_get_by_id_unset) {
     1365                if (Options::verboseOSR())
     1366                    dataLogF("Clearing LLInt property access.\n");
     1367                clearLLIntGetByIdCache(instruction);
     1368            }
     1369            return true;
     1370        };
     1371
     1372        if (!Heap::isMarked(std::get<0>(pair.key)))
     1373            return clear();
     1374
     1375        for (const LLIntPrototypeLoadAdaptiveStructureWatchpoint* watchpoint : pair.value) {
     1376            if (!watchpoint->key().isStillLive())
     1377                return clear();
     1378        }
     1379
     1380        return false;
    13621381    });
    13631382
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r232080 r232313  
    628628    }
    629629
    630     typedef HashMap<Structure*, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>> StructureWatchpointMap;
     630    typedef HashMap<std::tuple<Structure*, Instruction*>, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>> StructureWatchpointMap;
    631631    StructureWatchpointMap& llintGetByIdWatchpointMap() { return m_llintGetByIdWatchpointMap; }
    632632
  • trunk/Source/JavaScriptCore/bytecode/LLIntPrototypeLoadAdaptiveStructureWatchpoint.h

    r231719 r232313  
    3434class LLIntPrototypeLoadAdaptiveStructureWatchpoint : public Watchpoint {
    3535public:
     36    LLIntPrototypeLoadAdaptiveStructureWatchpoint() = default;
    3637    LLIntPrototypeLoadAdaptiveStructureWatchpoint(const ObjectPropertyCondition&, Instruction*);
    3738
    3839    void install();
     40
     41    const ObjectPropertyCondition& key() const { return m_key; }
    3942
    4043protected:
     
    4346private:
    4447    ObjectPropertyCondition m_key;
    45     Instruction* m_getByIdInstruction;
     48    Instruction* m_getByIdInstruction { nullptr };
    4649};
    4750
  • trunk/Source/JavaScriptCore/bytecode/ObjectPropertyConditionSet.h

    r231961 r232313  
    6868
    6969    bool isValidAndWatchable() const;
    70    
     70
     71    size_t size() const { return m_data ? m_data->vector.size() : 0; }
    7172    bool isEmpty() const
    7273    {
  • trunk/Source/JavaScriptCore/bytecode/Watchpoint.h

    r231534 r232313  
    6969    WTF_MAKE_FAST_ALLOCATED;
    7070public:
    71     Watchpoint()
    72     {
    73     }
     71    Watchpoint() = default;
    7472   
    7573    virtual ~Watchpoint();
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r232211 r232313  
    671671    PropertyOffset offset = invalidOffset;
    672672    CodeBlock::StructureWatchpointMap& watchpointMap = codeBlock->llintGetByIdWatchpointMap();
    673     auto result = watchpointMap.add(structure, Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint>());
     673    Bag<LLIntPrototypeLoadAdaptiveStructureWatchpoint> watchpoints;
    674674    for (ObjectPropertyCondition condition : conditions) {
    675675        if (!condition.isWatchable())
     
    677677        if (condition.condition().kind() == PropertyCondition::Presence)
    678678            offset = condition.condition().offset();
    679         result.iterator->value.add(condition, pc)->install();
    680     }
     679        watchpoints.add(condition, pc)->install();
     680    }
     681
    681682    ASSERT((offset == invalidOffset) == slot.isUnset());
     683    auto result = watchpointMap.add(std::make_tuple(structure, pc), WTFMove(watchpoints));
     684    ASSERT_UNUSED(result, result.isNewEntry);
    682685
    683686    ConcurrentJSLocker locker(codeBlock->m_lock);
  • trunk/Source/WTF/ChangeLog

    r232302 r232313  
     12018-05-30  Keith Miller  <keith_miller@apple.com>
     2
     3        LLInt get_by_id prototype caching doesn't properly handle changes
     4        https://bugs.webkit.org/show_bug.cgi?id=186112
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Mark some methods const.
     9
     10        * wtf/Bag.h:
     11        (WTF::Bag::begin const):
     12        (WTF::Bag::end const):
     13        (WTF::Bag::unwrappedHead const):
     14        (WTF::Bag::end): Deleted.
     15        (WTF::Bag::unwrappedHead): Deleted.
     16
    1172018-05-30  Alex Christensen  <achristensen@webkit.org>
    218
  • trunk/Source/WTF/wtf/Bag.h

    r227527 r232313  
    139139        return result;
    140140    }
    141    
    142     iterator end() { return iterator(); }
     141
     142    const iterator begin() const
     143    {
     144        iterator result;
     145        result.m_node = unwrappedHead();
     146        return result;
     147    }
     148
     149
     150    iterator end() const { return iterator(); }
    143151   
    144152    bool isEmpty() const { return !m_head; }
    145153   
    146154private:
    147     Node* unwrappedHead() { return PtrTraits::unwrap(m_head); }
     155    Node* unwrappedHead() const { return PtrTraits::unwrap(m_head); }
    148156
    149157    typename PtrTraits::StorageType m_head { nullptr };
Note: See TracChangeset for help on using the changeset viewer.