⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 201590 in webkit


Ignore:
Timestamp:
Jun 1, 2016, 9:26:32 PM (10 years ago)
Author:
fpizlo@apple.com
Message:

Structure::previousID() races with Structure::allocateRareData()
https://bugs.webkit.org/show_bug.cgi?id=158280

Reviewed by Mark Lam.

The problem is that previousID() would test hasRareData() and then either load the
previous Structure from the rare data, or load it directly. allocateRareData() would set
the hasRareData() bit separately from moving the Structure pointer into the rare data. So
we'd have a race that would cause previousID() to sometimes return the rarae data instead
of the previous Structure.

The fix is to get rid of the hasRareData bit. We can use the structureID of the
previousOrRareData cell to determine if it's the previousID or the RareData. This fixes the
race and it's probably not any slower.

  • runtime/Structure.cpp:

(JSC::Structure::Structure):
(JSC::Structure::allocateRareData):

  • runtime/Structure.h:
Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r201589 r201590  
     12016-06-01  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Structure::previousID() races with Structure::allocateRareData()
     4        https://bugs.webkit.org/show_bug.cgi?id=158280
     5
     6        Reviewed by Mark Lam.
     7       
     8        The problem is that previousID() would test hasRareData() and then either load the
     9        previous Structure from the rare data, or load it directly. allocateRareData() would set
     10        the hasRareData() bit separately from moving the Structure pointer into the rare data. So
     11        we'd have a race that would cause previousID() to sometimes return the rarae data instead
     12        of the previous Structure.
     13
     14        The fix is to get rid of the hasRareData bit. We can use the structureID of the
     15        previousOrRareData cell to determine if it's the previousID or the RareData. This fixes the
     16        race and it's probably not any slower.
     17
     18        * runtime/Structure.cpp:
     19        (JSC::Structure::Structure):
     20        (JSC::Structure::allocateRareData):
     21        * runtime/Structure.h:
     22
    1232016-06-01  Michael Saboff  <msaboff@apple.com>
    224
  • trunk/Source/JavaScriptCore/runtime/Structure.cpp

    r200405 r201590  
    207207    setDidTransition(false);
    208208    setStaticFunctionsReified(false);
    209     setHasRareData(false);
    210209    setTransitionWatchpointIsLikelyToBeFired(false);
    211210    setHasBeenDictionary(false);
     
    239238    setDidTransition(false);
    240239    setStaticFunctionsReified(false);
    241     setHasRareData(false);
    242240    setTransitionWatchpointIsLikelyToBeFired(false);
    243241    setHasBeenDictionary(false);
     
    270268    setDidTransition(true);
    271269    setStaticFunctionsReified(previous->staticFunctionsReified());
    272     setHasRareData(false);
    273270    setHasBeenDictionary(previous->hasBeenDictionary());
    274271 
     
    824821{
    825822    ASSERT(!hasRareData());
    826     StructureRareData* rareData = StructureRareData::create(vm, previous());
     823    StructureRareData* rareData = StructureRareData::create(vm, previousID());
    827824    WTF::storeStoreFence();
    828825    m_previousOrRareData.set(vm, this, rareData);
    829     WTF::storeStoreFence();
    830     setHasRareData(true);
    831826    ASSERT(hasRareData());
    832827}
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r200405 r201590  
    275275    // Will just the prototype chain intercept this property access?
    276276    JS_EXPORT_PRIVATE bool prototypeChainMayInterceptStoreTo(VM&, PropertyName);
    277        
     277   
     278    bool hasRareData() const
     279    {
     280        return isRareData(m_previousOrRareData.get());
     281    }
     282   
    278283    Structure* previousID() const
    279284    {
    280285        ASSERT(structure()->classInfo() == info());
    281         if (hasRareData())
    282             return rareData()->previousID();
    283         return previous();
     286        // This is so written because it's used concurrently. We only load from m_previousOrRareData
     287        // once, and this load is guaranteed atomic.
     288        JSCell* cell = m_previousOrRareData.get();
     289        if (isRareData(cell))
     290            return static_cast<StructureRareData*>(cell)->previousID();
     291        return static_cast<Structure*>(cell);
    284292    }
    285293    bool transitivelyTransitionedFrom(Structure* structureToFind);
     
    603611    DEFINE_BITFIELD(bool, didTransition, DidTransition, 1, 21);
    604612    DEFINE_BITFIELD(bool, staticFunctionsReified, StaticFunctionsReified, 1, 22);
    605     DEFINE_BITFIELD(bool, hasRareData, HasRareData, 1, 23);
    606     DEFINE_BITFIELD(bool, hasBeenFlattenedBefore, HasBeenFlattenedBefore, 1, 24);
    607     DEFINE_BITFIELD(bool, hasCustomGetterSetterProperties, HasCustomGetterSetterProperties, 1, 25);
    608     DEFINE_BITFIELD(bool, didWatchInternalProperties, DidWatchInternalProperties, 1, 26);
    609     DEFINE_BITFIELD(bool, transitionWatchpointIsLikelyToBeFired, TransitionWatchpointIsLikelyToBeFired, 1, 27);
    610     DEFINE_BITFIELD(bool, hasBeenDictionary, HasBeenDictionary, 1, 28);
     613    DEFINE_BITFIELD(bool, hasBeenFlattenedBefore, HasBeenFlattenedBefore, 1, 23);
     614    DEFINE_BITFIELD(bool, hasCustomGetterSetterProperties, HasCustomGetterSetterProperties, 1, 24);
     615    DEFINE_BITFIELD(bool, didWatchInternalProperties, DidWatchInternalProperties, 1, 25);
     616    DEFINE_BITFIELD(bool, transitionWatchpointIsLikelyToBeFired, TransitionWatchpointIsLikelyToBeFired, 1, 26);
     617    DEFINE_BITFIELD(bool, hasBeenDictionary, HasBeenDictionary, 1, 27);
    611618
    612619private:
     
    694701       
    695702    void pin();
    696 
    697     Structure* previous() const
    698     {
    699         ASSERT(!hasRareData());
    700         return static_cast<Structure*>(m_previousOrRareData.get());
     703   
     704    bool isRareData(JSCell* cell) const
     705    {
     706        return cell && cell->structureID() != structureID();
    701707    }
    702708
Note: See TracChangeset for help on using the changeset viewer.