Ignore:
Timestamp:
Sep 27, 2017, 5:44:28 PM (8 years ago)
Author:
[email protected]
Message:

Propagate hasBeenFlattenedBefore in Structure's transition constructor and fix our for-in caching to fail when the prototype chain has an object with a dictionary structure
https://bugs.webkit.org/show_bug.cgi?id=177523

Reviewed by Mark Lam.

JSTests:

  • stress/prototype-chain-has-dictionary-structure-for-in-caching.js: Added.

(assert):
(Test):
(addMethods.Test.prototype.string_appeared_here.i.methodNumber):
(addMethods):
(i.Test.prototype.propName):

Source/JavaScriptCore:

There was a bug in Structure's transition constructor where it didn't
propagate forward the hasBeenFlattenedBefore bit. In practice, this meant
that every time we asked a dictionary structure if it has been flattened
before, it would return false. This patch fixes this bug. It also fixes
a bug that this uncovers in our for-in implementation. Our implementation
would cache the property name enumerator even when the prototype chain
included a structure that is as dictionary. This is wrong because that
prototype object may add properties without transitioning, and the for-in
loop would vend a stale set of prototype properties.

  • jit/JITOperations.cpp:
  • runtime/JSPropertyNameEnumerator.h:

(JSC::propertyNameEnumerator):

  • runtime/Structure.cpp:

(JSC::Structure::Structure):
(JSC::Structure::canCachePropertyNameEnumerator const):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/Structure.cpp

    r222473 r222590  
    254254{
    255255    setDictionaryKind(previous->dictionaryKind());
    256     setIsPinnedPropertyTable(previous->hasBeenFlattenedBefore());
     256    setIsPinnedPropertyTable(false);
     257    setHasBeenFlattenedBefore(previous->hasBeenFlattenedBefore());
    257258    setHasGetterSetterProperties(previous->hasGetterSetterProperties());
    258259    setHasCustomGetterSetterProperties(previous->hasCustomGetterSetterProperties());
     
    12881289        if (!structure->get())
    12891290            break;
     1291        if (structure->get()->isDictionary())
     1292            return false;
    12901293        if (structure->get()->typeInfo().overridesGetPropertyNames())
    12911294            return false;
Note: See TracChangeset for help on using the changeset viewer.