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

Changeset 203368 in webkit


Ignore:
Timestamp:
Jul 18, 2016, 1:12:45 PM (10 years ago)
Author:
fpizlo@apple.com
Message:

Object.preventExtensions/seal/freeze makes code much slower
​https://bugs.webkit.org/show_bug.cgi?id=143247

Reviewed by Michael Saboff.

Source/JavaScriptCore:

This has been a huge pet peeve of mine for a long time, but I was always afraid of fixing
it because I thought that it would be hard. Well, it looks like it's not hard at all.

The problem is that you cannot mutate a structure that participates in transition caching.
You can only clone the structure and mutate that one. But if you do this, you have to make
a hard choice:

1) Clone the structure without caching the transition. This is what the code did before

this change. It's the most obvious choice, but it introduces an uncacheable transition
that leads to an explosion of structures, which then breaks all inline caches.


2) Perform one of the existing cacheable transitions. Cacheable transitions can either add

properties or they can do one of the NonPropertyTransitions, which until now have been
restricted to just IndexingType transitions. So, only adding transitions or making
certain prescribed changes to the indexing type count as cacheable transitions.


This change decouples NonPropertyTransition from IndexingType and adds three new kinds of
transitions: PreventExtensions, Seal, and Freeze. We have to give any cacheable transition
a name that fully disambiguates this transition from any other, so that the transition can
be cached. Since we're already giving them names in an enum, I figured that the most
pragmatic way to implement them is to have Structure::nonPropertyTransition() case on the
NonPropertyTransition and implement all of the mutations associated with that transition.
The alternative would have been to allow callers of nonPropertyTransition() to supply
something like a lambda that describes the mutation, but this seemed awkward since each
set of mutations has to anyway be tied to one of the NonPropertyTransition members.

This is an enormous speed-up on microbenchmarks that use Object.preventExtensions(),
Object.seal(), or Object.freeze(). I don't know if "real" benchmarks use these features
and I don't really care. This should be fast.

  • runtime/JSObject.cpp:

(JSC::JSObject::notifyPresenceOfIndexedAccessors):
(JSC::JSObject::createInitialUndecided):
(JSC::JSObject::createInitialInt32):
(JSC::JSObject::createInitialDouble):
(JSC::JSObject::createInitialContiguous):
(JSC::JSObject::convertUndecidedToInt32):
(JSC::JSObject::convertUndecidedToDouble):
(JSC::JSObject::convertUndecidedToContiguous):
(JSC::JSObject::convertInt32ToDouble):
(JSC::JSObject::convertInt32ToContiguous):
(JSC::JSObject::convertDoubleToContiguous):
(JSC::JSObject::switchToSlowPutArrayStorage):

  • runtime/Structure.cpp:

(JSC::Structure::suggestedArrayStorageTransition):
(JSC::Structure::addPropertyTransition):
(JSC::Structure::toUncacheableDictionaryTransition):
(JSC::Structure::sealTransition):
(JSC::Structure::freezeTransition):
(JSC::Structure::preventExtensionsTransition):
(JSC::Structure::takePropertyTableOrCloneIfPinned):
(JSC::Structure::nonPropertyTransition):
(JSC::Structure::pin):
(JSC::Structure::pinForCaching):
(JSC::Structure::allocateRareData):

  • runtime/Structure.h:
  • runtime/StructureTransitionTable.h:

(JSC::toAttributes):
(JSC::changesIndexingType):
(JSC::newIndexingType):
(JSC::preventsExtensions):
(JSC::setsDontDeleteOnAllProperties):
(JSC::setsReadOnlyOnAllProperties):

LayoutTests:

These tests now run ~25x faster.

  • js/regress/freeze-and-do-work-expected.txt: Added.
  • js/regress/freeze-and-do-work.html: Added.
  • js/regress/prevent-extensions-and-do-work-expected.txt: Added.
  • js/regress/prevent-extensions-and-do-work.html: Added.
  • js/regress/script-tests/freeze-and-do-work.js: Added.

(Foo):

  • js/regress/script-tests/prevent-extensions-and-do-work.js: Added.

(Foo):

  • js/regress/script-tests/seal-and-do-work.js: Added.

(Foo):

  • js/regress/seal-and-do-work-expected.txt: Added.
  • js/regress/seal-and-do-work.html: Added.
Location:
trunk
Files:
9 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r203367 r203368  
     12016-07-17  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Object.preventExtensions/seal/freeze makes code much slower
     4        https://bugs.webkit.org/show_bug.cgi?id=143247
     5
     6        Reviewed by Michael Saboff.
     7       
     8        These tests now run ~25x faster.
     9
     10        * js/regress/freeze-and-do-work-expected.txt: Added.
     11        * js/regress/freeze-and-do-work.html: Added.
     12        * js/regress/prevent-extensions-and-do-work-expected.txt: Added.
     13        * js/regress/prevent-extensions-and-do-work.html: Added.
     14        * js/regress/script-tests/freeze-and-do-work.js: Added.
     15        (Foo):
     16        * js/regress/script-tests/prevent-extensions-and-do-work.js: Added.
     17        (Foo):
     18        * js/regress/script-tests/seal-and-do-work.js: Added.
     19        (Foo):
     20        * js/regress/seal-and-do-work-expected.txt: Added.
     21        * js/regress/seal-and-do-work.html: Added.
     22
    1232016-07-18  Ryan Haddad  <ryanhaddad@apple.com>
    224
  • trunk/Source/JavaScriptCore/ChangeLog

    r203365 r203368  
     12016-07-17  Filip Pizlo  <fpizlo@apple.com>
     2
     3        Object.preventExtensions/seal/freeze makes code much slower
     4        https://bugs.webkit.org/show_bug.cgi?id=143247
     5
     6        Reviewed by Michael Saboff.
     7       
     8        This has been a huge pet peeve of mine for a long time, but I was always afraid of fixing
     9        it because I thought that it would be hard. Well, it looks like it's not hard at all.
     10       
     11        The problem is that you cannot mutate a structure that participates in transition caching.
     12        You can only clone the structure and mutate that one. But if you do this, you have to make
     13        a hard choice:
     14       
     15        1) Clone the structure without caching the transition. This is what the code did before
     16           this change. It's the most obvious choice, but it introduces an uncacheable transition
     17           that leads to an explosion of structures, which then breaks all inline caches.
     18       
     19        2) Perform one of the existing cacheable transitions. Cacheable transitions can either add
     20           properties or they can do one of the NonPropertyTransitions, which until now have been
     21           restricted to just IndexingType transitions. So, only adding transitions or making
     22           certain prescribed changes to the indexing type count as cacheable transitions.
     23       
     24        This change decouples NonPropertyTransition from IndexingType and adds three new kinds of
     25        transitions: PreventExtensions, Seal, and Freeze. We have to give any cacheable transition
     26        a name that fully disambiguates this transition from any other, so that the transition can
     27        be cached. Since we're already giving them names in an enum, I figured that the most
     28        pragmatic way to implement them is to have Structure::nonPropertyTransition() case on the
     29        NonPropertyTransition and implement all of the mutations associated with that transition.
     30        The alternative would have been to allow callers of nonPropertyTransition() to supply
     31        something like a lambda that describes the mutation, but this seemed awkward since each
     32        set of mutations has to anyway be tied to one of the NonPropertyTransition members.
     33       
     34        This is an enormous speed-up on microbenchmarks that use Object.preventExtensions(),
     35        Object.seal(), or Object.freeze(). I don't know if "real" benchmarks use these features
     36        and I don't really care. This should be fast.
     37
     38        * runtime/JSObject.cpp:
     39        (JSC::JSObject::notifyPresenceOfIndexedAccessors):
     40        (JSC::JSObject::createInitialUndecided):
     41        (JSC::JSObject::createInitialInt32):
     42        (JSC::JSObject::createInitialDouble):
     43        (JSC::JSObject::createInitialContiguous):
     44        (JSC::JSObject::convertUndecidedToInt32):
     45        (JSC::JSObject::convertUndecidedToDouble):
     46        (JSC::JSObject::convertUndecidedToContiguous):
     47        (JSC::JSObject::convertInt32ToDouble):
     48        (JSC::JSObject::convertInt32ToContiguous):
     49        (JSC::JSObject::convertDoubleToContiguous):
     50        (JSC::JSObject::switchToSlowPutArrayStorage):
     51        * runtime/Structure.cpp:
     52        (JSC::Structure::suggestedArrayStorageTransition):
     53        (JSC::Structure::addPropertyTransition):
     54        (JSC::Structure::toUncacheableDictionaryTransition):
     55        (JSC::Structure::sealTransition):
     56        (JSC::Structure::freezeTransition):
     57        (JSC::Structure::preventExtensionsTransition):
     58        (JSC::Structure::takePropertyTableOrCloneIfPinned):
     59        (JSC::Structure::nonPropertyTransition):
     60        (JSC::Structure::pin):
     61        (JSC::Structure::pinForCaching):
     62        (JSC::Structure::allocateRareData):
     63        * runtime/Structure.h:
     64        * runtime/StructureTransitionTable.h:
     65        (JSC::toAttributes):
     66        (JSC::changesIndexingType):
     67        (JSC::newIndexingType):
     68        (JSC::preventsExtensions):
     69        (JSC::setsDontDeleteOnAllProperties):
     70        (JSC::setsReadOnlyOnAllProperties):
     71
    1722016-07-17  Filip Pizlo  <fpizlo@apple.com>
    273
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r203004 r203368  
    771771        return;
    772772   
    773     setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), AddIndexedAccessors));
     773    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AddIndexedAccessors));
    774774   
    775775    if (!vm.prototypeMap.isPrototype(this))
    … …  
    799799    DeferGC deferGC(vm.heap);
    800800    Butterfly* newButterfly = createInitialIndexedStorage(vm, length, sizeof(EncodedJSValue));
    801     Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), AllocateUndecided);
     801    Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateUndecided);
    802802    setStructureAndButterfly(vm, newStructure, newButterfly);
    803803    return newButterfly;
    … …  
    808808    DeferGC deferGC(vm.heap);
    809809    Butterfly* newButterfly = createInitialIndexedStorage(vm, length, sizeof(EncodedJSValue));
    810     Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), AllocateInt32);
     810    Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateInt32);
    811811    setStructureAndButterfly(vm, newStructure, newButterfly);
    812812    return newButterfly->contiguousInt32();
    … …  
    819819    for (unsigned i = newButterfly->vectorLength(); i--;)
    820820        newButterfly->contiguousDouble()[i] = PNaN;
    821     Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), AllocateDouble);
     821    Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateDouble);
    822822    setStructureAndButterfly(vm, newStructure, newButterfly);
    823823    return newButterfly->contiguousDouble();
    … …  
    828828    DeferGC deferGC(vm.heap);
    829829    Butterfly* newButterfly = createInitialIndexedStorage(vm, length, sizeof(EncodedJSValue));
    830     Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), AllocateContiguous);
     830    Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateContiguous);
    831831    setStructureAndButterfly(vm, newStructure, newButterfly);
    832832    return newButterfly->contiguous();
    … …  
    863863{
    864864    ASSERT(hasUndecided(indexingType()));
    865     setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), AllocateInt32));
     865    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateInt32));
    866866    return m_butterfly.get()->contiguousInt32();
    867867}
    … …  
    875875        butterfly->contiguousDouble()[i] = PNaN;
    876876   
    877     setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), AllocateDouble));
     877    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateDouble));
    878878    return m_butterfly.get()->contiguousDouble();
    879879}
    … …  
    882882{
    883883    ASSERT(hasUndecided(indexingType()));
    884     setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), AllocateContiguous));
     884    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateContiguous));
    885885    return m_butterfly.get()->contiguous();
    886886}
    … …  
    947947    }
    948948   
    949     setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), AllocateDouble));
     949    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateDouble));
    950950    return m_butterfly.get()->contiguousDouble();
    951951}
    … …  
    955955    ASSERT(hasInt32(indexingType()));
    956956   
    957     setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), AllocateContiguous));
     957    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateContiguous));
    958958    return m_butterfly.get()->contiguous();
    959959}
    … …  
    10031003    }
    10041004   
    1005     setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), AllocateContiguous));
     1005    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateContiguous));
    10061006    return m_butterfly.get()->contiguous();
    10071007}
    … …  
    12911291    switch (indexingType()) {
    12921292    case ALL_UNDECIDED_INDEXING_TYPES:
    1293         convertUndecidedToArrayStorage(vm, AllocateSlowPutArrayStorage);
     1293        convertUndecidedToArrayStorage(vm, NonPropertyTransition::AllocateSlowPutArrayStorage);
    12941294        break;
    12951295       
    12961296    case ALL_INT32_INDEXING_TYPES:
    1297         convertInt32ToArrayStorage(vm, AllocateSlowPutArrayStorage);
     1297        convertInt32ToArrayStorage(vm, NonPropertyTransition::AllocateSlowPutArrayStorage);
    12981298        break;
    12991299       
    13001300    case ALL_DOUBLE_INDEXING_TYPES:
    1301         convertDoubleToArrayStorage(vm, AllocateSlowPutArrayStorage);
     1301        convertDoubleToArrayStorage(vm, NonPropertyTransition::AllocateSlowPutArrayStorage);
    13021302        break;
    13031303       
    13041304    case ALL_CONTIGUOUS_INDEXING_TYPES:
    1305         convertContiguousToArrayStorage(vm, AllocateSlowPutArrayStorage);
     1305        convertContiguousToArrayStorage(vm, NonPropertyTransition::AllocateSlowPutArrayStorage);
    13061306        break;
    13071307       
    13081308    case NonArrayWithArrayStorage:
    13091309    case ArrayWithArrayStorage: {
    1310         Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), SwitchToSlowPutArrayStorage);
     1310        Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::SwitchToSlowPutArrayStorage);
    13111311        setStructure(vm, newStructure);
    13121312        break;
  • trunk/Source/JavaScriptCore/runtime/Structure.cpp

    r202588 r203368  
    436436{
    437437    if (needsSlowPutIndexing())
    438         return AllocateSlowPutArrayStorage;
    439    
    440     return AllocateArrayStorage;
     438        return NonPropertyTransition::AllocateSlowPutArrayStorage;
     439   
     440    return NonPropertyTransition::AllocateArrayStorage;
    441441}
    442442
    … …  
    588588}
    589589
    590 // In future we may want to cache this transition.
    591590Structure* Structure::sealTransition(VM& vm, Structure* structure)
    592591{
    593     Structure* transition = preventExtensionsTransition(vm, structure);
    594 
    595     if (transition->propertyTable()) {
    596         PropertyTable::iterator end = transition->propertyTable()->end();
    597         for (PropertyTable::iterator iter = transition->propertyTable()->begin(); iter != end; ++iter)
    598             iter->attributes |= DontDelete;
    599     }
    600 
    601     transition->checkOffsetConsistency();
    602     return transition;
    603 }
    604 
    605 // In future we may want to cache this transition.
     592    return nonPropertyTransition(vm, structure, NonPropertyTransition::Seal);
     593}
     594
    606595Structure* Structure::freezeTransition(VM& vm, Structure* structure)
    607596{
    608     Structure* transition = preventExtensionsTransition(vm, structure);
    609 
    610     if (transition->propertyTable()) {
    611         PropertyTable::iterator iter = transition->propertyTable()->begin();
    612         PropertyTable::iterator end = transition->propertyTable()->end();
    613         if (iter != end)
    614             transition->setHasReadOnlyOrGetterSetterPropertiesExcludingProto(true);
    615         for (; iter != end; ++iter)
    616             iter->attributes |= iter->attributes & Accessor ? DontDelete : (DontDelete | ReadOnly);
    617     }
    618 
    619     ASSERT(transition->hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !transition->classInfo()->hasStaticSetterOrReadonlyProperties());
    620     ASSERT(transition->hasGetterSetterProperties() || !transition->classInfo()->hasStaticSetterOrReadonlyProperties());
    621     transition->checkOffsetConsistency();
    622     return transition;
    623 }
    624 
    625 // In future we may want to cache this transition.
     597    return nonPropertyTransition(vm, structure, NonPropertyTransition::Freeze);
     598}
     599
    626600Structure* Structure::preventExtensionsTransition(VM& vm, Structure* structure)
    627601{
    628     Structure* transition = create(vm, structure);
    629 
    630     // Don't set m_offset, as one cannot transition to this.
    631 
    632     DeferGC deferGC(vm.heap);
    633     structure->materializePropertyMapIfNecessary(vm, deferGC);
    634     transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm));
    635     transition->m_offset = structure->m_offset;
    636     transition->setDidPreventExtensions(true);
    637     transition->pin();
    638 
    639     transition->checkOffsetConsistency();
    640     return transition;
     602    return nonPropertyTransition(vm, structure, NonPropertyTransition::PreventExtensions);
    641603}
    642604
    … …  
    663625    IndexingType indexingType = newIndexingType(structure->indexingTypeIncludingHistory(), transitionKind);
    664626   
    665     if (JSGlobalObject* globalObject = structure->m_globalObject.get()) {
    666         if (globalObject->isOriginalArrayStructure(structure)) {
    667             Structure* result = globalObject->originalArrayStructureForIndexingType(indexingType);
    668             if (result->indexingTypeIncludingHistory() == indexingType) {
    669                 structure->didTransitionFromThisStructure();
    670                 return result;
     627    if (changesIndexingType(transitionKind)) {
     628        if (JSGlobalObject* globalObject = structure->m_globalObject.get()) {
     629            if (globalObject->isOriginalArrayStructure(structure)) {
     630                Structure* result = globalObject->originalArrayStructureForIndexingType(indexingType);
     631                if (result->indexingTypeIncludingHistory() == indexingType) {
     632                    structure->didTransitionFromThisStructure();
     633                    return result;
     634                }
    671635            }
    672636        }
    … …  
    680644    }
    681645   
     646    DeferGC deferGC(vm.heap);
     647   
    682648    Structure* transition = create(vm, structure);
    683649    transition->setAttributesInPrevious(attributes);
    684650    transition->m_blob.setIndexingType(indexingType);
    685     transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm));
    686     transition->m_offset = structure->m_offset;
    687     checkOffset(transition->m_offset, transition->inlineCapacity());
     651   
     652    if (preventsExtensions(transitionKind))
     653        transition->setDidPreventExtensions(true);
     654   
     655    unsigned additionalPropertyAttributes = 0;
     656    if (setsDontDeleteOnAllProperties(transitionKind))
     657        additionalPropertyAttributes |= DontDelete;
     658    if (setsReadOnlyOnAllProperties(transitionKind))
     659        additionalPropertyAttributes |= ReadOnly;
     660    if (additionalPropertyAttributes) {
     661        // We pin the property table on transitions that do wholesale editing of the property
     662        // table, since our logic for walking the property transition chain to rematerialize the
     663        // table doesn't know how to take into account such wholesale edits.
     664       
     665        structure->materializePropertyMapIfNecessary(vm, deferGC);
     666        transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm));
     667        transition->m_offset = structure->m_offset;
     668        transition->pinForCaching();
     669       
     670        if (transition->propertyTable()) {
     671            for (auto& entry : *transition->propertyTable().get())
     672                entry.attributes |= additionalPropertyAttributes;
     673        }
     674    } else {
     675        transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm));
     676        transition->m_offset = structure->m_offset;
     677        checkOffset(transition->m_offset, transition->inlineCapacity());
     678    }
     679   
     680    if (setsReadOnlyOnAllProperties(transitionKind)
     681        && transition->propertyTable()
     682        && !transition->propertyTable()->isEmpty())
     683        transition->setHasReadOnlyOrGetterSetterPropertiesExcludingProto(true);
    688684   
    689685    if (structure->isDictionary())
    … …  
    693689        structure->m_transitionTable.add(vm, transition);
    694690    }
     691
    695692    transition->checkOffsetConsistency();
    696693    return transition;
    … …  
    815812    setIsPinnedPropertyTable(true);
    816813    clearPreviousID();
     814    m_nameInPrevious = nullptr;
     815}
     816
     817void Structure::pinForCaching()
     818{
     819    ASSERT(propertyTable());
     820    setIsPinnedPropertyTable(true);
    817821    m_nameInPrevious = nullptr;
    818822}
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r201853 r203368  
    701701       
    702702    void pin();
     703    void pinForCaching();
    703704   
    704705    bool isRareData(JSCell* cell) const
  • trunk/Source/JavaScriptCore/runtime/StructureTransitionTable.h

    r188978 r203368  
    4141// Support for attributes used to indicate transitions not related to properties.
    4242// If any of these are used, the string portion of the key should be 0.
    43 enum NonPropertyTransition {
     43enum class NonPropertyTransition : unsigned {
    4444    AllocateUndecided,
    4545    AllocateInt32,
    … …  
    4949    AllocateSlowPutArrayStorage,
    5050    SwitchToSlowPutArrayStorage,
    51     AddIndexedAccessors
     51    AddIndexedAccessors,
     52    PreventExtensions,
     53    Seal,
     54    Freeze
    5255};
    5356
    5457inline unsigned toAttributes(NonPropertyTransition transition)
    5558{
    56     return transition + FirstInternalAttribute;
     59    return static_cast<unsigned>(transition) + FirstInternalAttribute;
     60}
     61
     62inline bool changesIndexingType(NonPropertyTransition transition)
     63{
     64    switch (transition) {
     65    case NonPropertyTransition::AllocateUndecided:
     66    case NonPropertyTransition::AllocateInt32:
     67    case NonPropertyTransition::AllocateDouble:
     68    case NonPropertyTransition::AllocateContiguous:
     69    case NonPropertyTransition::AllocateArrayStorage:
     70    case NonPropertyTransition::AllocateSlowPutArrayStorage:
     71    case NonPropertyTransition::SwitchToSlowPutArrayStorage:
     72    case NonPropertyTransition::AddIndexedAccessors:
     73        return true;
     74    default:
     75        return false;
     76    }
    5777}
    5878
    … …  
    6080{
    6181    switch (transition) {
    62     case AllocateUndecided:
     82    case NonPropertyTransition::AllocateUndecided:
    6383        ASSERT(!hasIndexedProperties(oldType));
    6484        return oldType | UndecidedShape;
    65     case AllocateInt32:
     85    case NonPropertyTransition::AllocateInt32:
    6686        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType));
    6787        return (oldType & ~IndexingShapeMask) | Int32Shape;
    68     case AllocateDouble:
     88    case NonPropertyTransition::AllocateDouble:
    6989        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType));
    7090        return (oldType & ~IndexingShapeMask) | DoubleShape;
    71     case AllocateContiguous:
     91    case NonPropertyTransition::AllocateContiguous:
    7292        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType));
    7393        return (oldType & ~IndexingShapeMask) | ContiguousShape;
    74     case AllocateArrayStorage:
     94    case NonPropertyTransition::AllocateArrayStorage:
    7595        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType));
    7696        return (oldType & ~IndexingShapeMask) | ArrayStorageShape;
    77     case AllocateSlowPutArrayStorage:
     97    case NonPropertyTransition::AllocateSlowPutArrayStorage:
    7898        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType) || hasContiguous(oldType));
    7999        return (oldType & ~IndexingShapeMask) | SlowPutArrayStorageShape;
    80     case SwitchToSlowPutArrayStorage:
     100    case NonPropertyTransition::SwitchToSlowPutArrayStorage:
    81101        ASSERT(hasArrayStorage(oldType));
    82102        return (oldType & ~IndexingShapeMask) | SlowPutArrayStorageShape;
    83     case AddIndexedAccessors:
     103    case NonPropertyTransition::AddIndexedAccessors:
    84104        return oldType | MayHaveIndexedAccessors;
    85105    default:
    86         RELEASE_ASSERT_NOT_REACHED();
    87106        return oldType;
     107    }
     108}
     109
     110inline bool preventsExtensions(NonPropertyTransition transition)
     111{
     112    switch (transition) {
     113    case NonPropertyTransition::PreventExtensions:
     114    case NonPropertyTransition::Seal:
     115    case NonPropertyTransition::Freeze:
     116        return true;
     117    default:
     118        return false;
     119    }
     120}
     121
     122inline bool setsDontDeleteOnAllProperties(NonPropertyTransition transition)
     123{
     124    switch (transition) {
     125    case NonPropertyTransition::Seal:
     126    case NonPropertyTransition::Freeze:
     127        return true;
     128    default:
     129        return false;
     130    }
     131}
     132
     133inline bool setsReadOnlyOnAllProperties(NonPropertyTransition transition)
     134{
     135    switch (transition) {
     136    case NonPropertyTransition::Freeze:
     137        return true;
     138    default:
     139        return false;
    88140    }
    89141}
Note: See TracChangeset for help on using the changeset viewer.