Title: [265640] trunk/Source/_javascript_Core
Revision
265640
Author
[email protected]
Date
2020-08-13 18:56:43 -0700 (Thu, 13 Aug 2020)

Log Message

Rework StructureTransitionTable::Hash::Key encoding
https://bugs.webkit.org/show_bug.cgi?id=215483

Reviewed by Yusuke Suzuki.

This patch implements new encoding of StructureTransitionTable::Hash::Key
to enable storing attribute change transitions in a transition table.

Since PropertyMapEntry attributes are always uint8_t, the remaining 8 bits
are used for TransitionKind, which also accommodates non-property transitions,
removing a bit hacky toAttributes() and utilization of unused pointer bits.

This change also introduces TransitionKind::Unknown we can validate against,
preventing addition transition from being a default, which could be unsafe.

No behavior change.

* 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::convertUndecidedToArrayStorage):
(JSC::JSObject::convertInt32ToDouble):
(JSC::JSObject::convertInt32ToContiguous):
(JSC::JSObject::convertInt32ToArrayStorage):
(JSC::JSObject::convertDoubleToContiguous):
(JSC::JSObject::convertDoubleToArrayStorage):
(JSC::JSObject::convertContiguousToArrayStorage):
(JSC::JSObject::convertFromCopyOnWrite):
(JSC::JSObject::switchToSlowPutArrayStorage):
(JSC::JSObject::suggestedArrayStorageTransition const):
* runtime/JSObject.h:
* runtime/Structure.cpp:
(JSC::StructureTransitionTable::contains const):
(JSC::StructureTransitionTable::get const):
(JSC::StructureTransitionTable::add):
(JSC::Structure::Structure):
(JSC::Structure::addPropertyTransitionToExistingStructureImpl):
(JSC::Structure::addNewPropertyTransition):
(JSC::Structure::removePropertyTransitionFromExistingStructureImpl):
(JSC::Structure::removeNewPropertyTransition):
(JSC::Structure::sealTransition):
(JSC::Structure::freezeTransition):
(JSC::Structure::preventExtensionsTransition):
(JSC::Structure::nonPropertyTransitionSlow):
* runtime/Structure.h:
* runtime/StructureInlines.h:
(JSC::Structure::nonPropertyTransition):
* runtime/StructureTransitionTable.h:
(JSC::changesIndexingType):
(JSC::newIndexingType):
(JSC::preventsExtensions):
(JSC::setsDontDeleteOnAllProperties):
(JSC::setsReadOnlyOnNonAccessorProperties):
(JSC::StructureTransitionTable::Hash::Key::Key):
(JSC::StructureTransitionTable::Hash::Key::attributes const):
(JSC::StructureTransitionTable::Hash::Key::transitionKind const):
(JSC::StructureTransitionTable::Hash::hash):
(JSC::toAttributes): Deleted.
(JSC::StructureTransitionTable::Hash::Key::isAddition const): Deleted.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (265639 => 265640)


--- trunk/Source/_javascript_Core/ChangeLog	2020-08-14 00:25:56 UTC (rev 265639)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-08-14 01:56:43 UTC (rev 265640)
@@ -1,3 +1,71 @@
+2020-08-13  Alexey Shvayka  <[email protected]>
+
+        Rework StructureTransitionTable::Hash::Key encoding
+        https://bugs.webkit.org/show_bug.cgi?id=215483
+
+        Reviewed by Yusuke Suzuki.
+
+        This patch implements new encoding of StructureTransitionTable::Hash::Key
+        to enable storing attribute change transitions in a transition table.
+
+        Since PropertyMapEntry attributes are always uint8_t, the remaining 8 bits
+        are used for TransitionKind, which also accommodates non-property transitions,
+        removing a bit hacky toAttributes() and utilization of unused pointer bits.
+
+        This change also introduces TransitionKind::Unknown we can validate against,
+        preventing addition transition from being a default, which could be unsafe.
+
+        No behavior change.
+
+        * 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::convertUndecidedToArrayStorage):
+        (JSC::JSObject::convertInt32ToDouble):
+        (JSC::JSObject::convertInt32ToContiguous):
+        (JSC::JSObject::convertInt32ToArrayStorage):
+        (JSC::JSObject::convertDoubleToContiguous):
+        (JSC::JSObject::convertDoubleToArrayStorage):
+        (JSC::JSObject::convertContiguousToArrayStorage):
+        (JSC::JSObject::convertFromCopyOnWrite):
+        (JSC::JSObject::switchToSlowPutArrayStorage):
+        (JSC::JSObject::suggestedArrayStorageTransition const):
+        * runtime/JSObject.h:
+        * runtime/Structure.cpp:
+        (JSC::StructureTransitionTable::contains const):
+        (JSC::StructureTransitionTable::get const):
+        (JSC::StructureTransitionTable::add):
+        (JSC::Structure::Structure):
+        (JSC::Structure::addPropertyTransitionToExistingStructureImpl):
+        (JSC::Structure::addNewPropertyTransition):
+        (JSC::Structure::removePropertyTransitionFromExistingStructureImpl):
+        (JSC::Structure::removeNewPropertyTransition):
+        (JSC::Structure::sealTransition):
+        (JSC::Structure::freezeTransition):
+        (JSC::Structure::preventExtensionsTransition):
+        (JSC::Structure::nonPropertyTransitionSlow):
+        * runtime/Structure.h:
+        * runtime/StructureInlines.h:
+        (JSC::Structure::nonPropertyTransition):
+        * runtime/StructureTransitionTable.h:
+        (JSC::changesIndexingType):
+        (JSC::newIndexingType):
+        (JSC::preventsExtensions):
+        (JSC::setsDontDeleteOnAllProperties):
+        (JSC::setsReadOnlyOnNonAccessorProperties):
+        (JSC::StructureTransitionTable::Hash::Key::Key):
+        (JSC::StructureTransitionTable::Hash::Key::attributes const):
+        (JSC::StructureTransitionTable::Hash::Key::transitionKind const):
+        (JSC::StructureTransitionTable::Hash::hash):
+        (JSC::toAttributes): Deleted.
+        (JSC::StructureTransitionTable::Hash::Key::isAddition const): Deleted.
+
 2020-08-12  Keith Rollin  <[email protected]>
 
         Remove the need for defining USE_NEW_BUILD_SYSTEM

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (265639 => 265640)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2020-08-14 00:25:56 UTC (rev 265639)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2020-08-14 01:56:43 UTC (rev 265640)
@@ -1078,7 +1078,7 @@
     if (mayInterceptIndexedAccesses(vm))
         return;
     
-    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AddIndexedAccessors));
+    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), TransitionKind::AddIndexedAccessors));
     
     if (!mayBePrototype())
         return;
@@ -1110,7 +1110,7 @@
     Butterfly* newButterfly = createInitialIndexedStorage(vm, length);
     StructureID oldStructureID = this->structureID();
     Structure* oldStructure = vm.getStructure(oldStructureID);
-    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, NonPropertyTransition::AllocateUndecided);
+    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, TransitionKind::AllocateUndecided);
     nukeStructureAndSetButterfly(vm, oldStructureID, newButterfly);
     setStructure(vm, newStructure);
     return newButterfly;
@@ -1124,7 +1124,7 @@
         newButterfly->contiguous().at(this, i).setWithoutWriteBarrier(JSValue());
     StructureID oldStructureID = this->structureID();
     Structure* oldStructure = vm.getStructure(oldStructureID);
-    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, NonPropertyTransition::AllocateInt32);
+    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, TransitionKind::AllocateInt32);
     nukeStructureAndSetButterfly(vm, oldStructureID, newButterfly);
     setStructure(vm, newStructure);
     return newButterfly->contiguousInt32();
@@ -1138,7 +1138,7 @@
         newButterfly->contiguousDouble().at(this, i) = PNaN;
     StructureID oldStructureID = this->structureID();
     Structure* oldStructure = vm.getStructure(oldStructureID);
-    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, NonPropertyTransition::AllocateDouble);
+    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, TransitionKind::AllocateDouble);
     nukeStructureAndSetButterfly(vm, oldStructureID, newButterfly);
     setStructure(vm, newStructure);
     return newButterfly->contiguousDouble();
@@ -1152,7 +1152,7 @@
         newButterfly->contiguous().at(this, i).setWithoutWriteBarrier(JSValue());
     StructureID oldStructureID = this->structureID();
     Structure* oldStructure = vm.getStructure(oldStructureID);
-    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, NonPropertyTransition::AllocateContiguous);
+    Structure* newStructure = Structure::nonPropertyTransition(vm, oldStructure, TransitionKind::AllocateContiguous);
     nukeStructureAndSetButterfly(vm, oldStructureID, newButterfly);
     setStructure(vm, newStructure);
     return newButterfly->contiguous();
@@ -1207,7 +1207,7 @@
     for (unsigned i = butterfly->vectorLength(); i--;)
         butterfly->contiguous().at(this, i).setWithoutWriteBarrier(JSValue());
 
-    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateInt32));
+    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), TransitionKind::AllocateInt32));
     return m_butterfly->contiguousInt32();
 }
 
@@ -1219,7 +1219,7 @@
     for (unsigned i = butterfly->vectorLength(); i--;)
         butterfly->contiguousDouble().at(this, i) = PNaN;
     
-    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateDouble));
+    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), TransitionKind::AllocateDouble));
     return m_butterfly->contiguousDouble();
 }
 
@@ -1232,7 +1232,7 @@
         butterfly->contiguous().at(this, i).setWithoutWriteBarrier(JSValue());
 
     WTF::storeStoreFence();
-    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateContiguous));
+    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), TransitionKind::AllocateContiguous));
     return m_butterfly->contiguous();
 }
 
@@ -1259,7 +1259,7 @@
     return newStorage;
 }
 
-ArrayStorage* JSObject::convertUndecidedToArrayStorage(VM& vm, NonPropertyTransition transition)
+ArrayStorage* JSObject::convertUndecidedToArrayStorage(VM& vm, TransitionKind transition)
 {
     DeferGC deferGC(vm.heap);
     ASSERT(hasUndecided(indexingType()));
@@ -1302,7 +1302,7 @@
         *currentAsDouble = v.asInt32();
     }
     
-    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateDouble));
+    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), TransitionKind::AllocateDouble));
     return m_butterfly->contiguousDouble();
 }
 
@@ -1310,11 +1310,11 @@
 {
     ASSERT(hasInt32(indexingType()));
     
-    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateContiguous));
+    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), TransitionKind::AllocateContiguous));
     return m_butterfly->contiguous();
 }
 
-ArrayStorage* JSObject::convertInt32ToArrayStorage(VM& vm, NonPropertyTransition transition)
+ArrayStorage* JSObject::convertInt32ToArrayStorage(VM& vm, TransitionKind transition)
 {
     DeferGC deferGC(vm.heap);
     ASSERT(hasInt32(indexingType()));
@@ -1361,11 +1361,11 @@
     }
     
     WTF::storeStoreFence();
-    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::AllocateContiguous));
+    setStructure(vm, Structure::nonPropertyTransition(vm, structure(vm), TransitionKind::AllocateContiguous));
     return m_butterfly->contiguous();
 }
 
-ArrayStorage* JSObject::convertDoubleToArrayStorage(VM& vm, NonPropertyTransition transition)
+ArrayStorage* JSObject::convertDoubleToArrayStorage(VM& vm, TransitionKind transition)
 {
     DeferGC deferGC(vm.heap);
     ASSERT(hasDouble(indexingType()));
@@ -1396,7 +1396,7 @@
     return convertDoubleToArrayStorage(vm, suggestedArrayStorageTransition(vm));
 }
 
-ArrayStorage* JSObject::convertContiguousToArrayStorage(VM& vm, NonPropertyTransition transition)
+ArrayStorage* JSObject::convertContiguousToArrayStorage(VM& vm, TransitionKind transition)
 {
     DeferGC deferGC(vm.heap);
     ASSERT(hasContiguous(indexingType()));
@@ -1540,17 +1540,17 @@
     gcSafeMemcpy(newButterfly->propertyStorage(), oldButterfly->propertyStorage(), oldButterfly->vectorLength() * sizeof(JSValue) + sizeof(IndexingHeader));
 
     WTF::storeStoreFence();
-    NonPropertyTransition transition = ([&] () {
+    TransitionKind transition = ([&] () {
         switch (indexingType()) {
         case ArrayWithInt32:
-            return NonPropertyTransition::AllocateInt32;
+            return TransitionKind::AllocateInt32;
         case ArrayWithDouble:
-            return NonPropertyTransition::AllocateDouble;
+            return TransitionKind::AllocateDouble;
         case ArrayWithContiguous:
-            return NonPropertyTransition::AllocateContiguous;
+            return TransitionKind::AllocateContiguous;
         default:
             RELEASE_ASSERT_NOT_REACHED();
-            return NonPropertyTransition::AllocateContiguous;
+            return TransitionKind::AllocateContiguous;
         }
     })();
     StructureID oldStructureID = structureID();
@@ -1785,24 +1785,24 @@
         break;
 
     case ALL_UNDECIDED_INDEXING_TYPES:
-        convertUndecidedToArrayStorage(vm, NonPropertyTransition::AllocateSlowPutArrayStorage);
+        convertUndecidedToArrayStorage(vm, TransitionKind::AllocateSlowPutArrayStorage);
         break;
         
     case ALL_INT32_INDEXING_TYPES:
-        convertInt32ToArrayStorage(vm, NonPropertyTransition::AllocateSlowPutArrayStorage);
+        convertInt32ToArrayStorage(vm, TransitionKind::AllocateSlowPutArrayStorage);
         break;
         
     case ALL_DOUBLE_INDEXING_TYPES:
-        convertDoubleToArrayStorage(vm, NonPropertyTransition::AllocateSlowPutArrayStorage);
+        convertDoubleToArrayStorage(vm, TransitionKind::AllocateSlowPutArrayStorage);
         break;
         
     case ALL_CONTIGUOUS_INDEXING_TYPES:
-        convertContiguousToArrayStorage(vm, NonPropertyTransition::AllocateSlowPutArrayStorage);
+        convertContiguousToArrayStorage(vm, TransitionKind::AllocateSlowPutArrayStorage);
         break;
         
     case NonArrayWithArrayStorage:
     case ArrayWithArrayStorage: {
-        Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), NonPropertyTransition::SwitchToSlowPutArrayStorage);
+        Structure* newStructure = Structure::nonPropertyTransition(vm, structure(vm), TransitionKind::SwitchToSlowPutArrayStorage);
         setStructure(vm, newStructure);
         break;
     }
@@ -3904,12 +3904,12 @@
     return anyObjectInChainMayInterceptIndexedAccesses(vm) || globalObject(vm)->isHavingABadTime();
 }
 
-NonPropertyTransition JSObject::suggestedArrayStorageTransition(VM& vm) const
+TransitionKind JSObject::suggestedArrayStorageTransition(VM& vm) const
 {
     if (needsSlowPutIndexing(vm))
-        return NonPropertyTransition::AllocateSlowPutArrayStorage;
+        return TransitionKind::AllocateSlowPutArrayStorage;
     
-    return NonPropertyTransition::AllocateArrayStorage;
+    return TransitionKind::AllocateArrayStorage;
 }
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (265639 => 265640)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2020-08-14 00:25:56 UTC (rev 265639)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2020-08-14 01:56:43 UTC (rev 265640)
@@ -84,12 +84,6 @@
 extern JS_EXPORT_PRIVATE const ASCIILiteral UnconfigurablePropertyChangeEnumerabilityError;
 extern JS_EXPORT_PRIVATE const ASCIILiteral UnconfigurablePropertyChangeWritabilityError;
 
-COMPILE_ASSERT(PropertyAttribute::None < FirstInternalAttribute, None_is_below_FirstInternalAttribute);
-COMPILE_ASSERT(PropertyAttribute::ReadOnly < FirstInternalAttribute, ReadOnly_is_below_FirstInternalAttribute);
-COMPILE_ASSERT(PropertyAttribute::DontEnum < FirstInternalAttribute, DontEnum_is_below_FirstInternalAttribute);
-COMPILE_ASSERT(PropertyAttribute::DontDelete < FirstInternalAttribute, DontDelete_is_below_FirstInternalAttribute);
-COMPILE_ASSERT(PropertyAttribute::Accessor < FirstInternalAttribute, Accessor_is_below_FirstInternalAttribute);
-
 class JSFinalObject;
 
 #if ASSERT_ENABLED
@@ -824,7 +818,7 @@
     bool needsSlowPutIndexing(VM&) const;
 
 private:
-    NonPropertyTransition suggestedArrayStorageTransition(VM&) const;
+    TransitionKind suggestedArrayStorageTransition(VM&) const;
 public:
     // You should only call isStructureExtensible() when:
     // - Performing this check in a way that isn't described in the specification 
@@ -1032,19 +1026,19 @@
     ContiguousJSValues convertUndecidedToInt32(VM&);
     ContiguousDoubles convertUndecidedToDouble(VM&);
     ContiguousJSValues convertUndecidedToContiguous(VM&);
-    ArrayStorage* convertUndecidedToArrayStorage(VM&, NonPropertyTransition);
+    ArrayStorage* convertUndecidedToArrayStorage(VM&, TransitionKind);
     ArrayStorage* convertUndecidedToArrayStorage(VM&);
         
     ContiguousDoubles convertInt32ToDouble(VM&);
     ContiguousJSValues convertInt32ToContiguous(VM&);
-    ArrayStorage* convertInt32ToArrayStorage(VM&, NonPropertyTransition);
+    ArrayStorage* convertInt32ToArrayStorage(VM&, TransitionKind);
     ArrayStorage* convertInt32ToArrayStorage(VM&);
 
     ContiguousJSValues convertDoubleToContiguous(VM&);
-    ArrayStorage* convertDoubleToArrayStorage(VM&, NonPropertyTransition);
+    ArrayStorage* convertDoubleToArrayStorage(VM&, TransitionKind);
     ArrayStorage* convertDoubleToArrayStorage(VM&);
         
-    ArrayStorage* convertContiguousToArrayStorage(VM&, NonPropertyTransition);
+    ArrayStorage* convertContiguousToArrayStorage(VM&, TransitionKind);
     ArrayStorage* convertContiguousToArrayStorage(VM&);
 
         

Modified: trunk/Source/_javascript_Core/runtime/Structure.cpp (265639 => 265640)


--- trunk/Source/_javascript_Core/runtime/Structure.cpp	2020-08-14 00:25:56 UTC (rev 265639)
+++ trunk/Source/_javascript_Core/runtime/Structure.cpp	2020-08-14 01:56:43 UTC (rev 265640)
@@ -78,22 +78,22 @@
     m_data = bitwise_cast<intptr_t>(impl) | UsingSingleSlotFlag;
 }
 
-bool StructureTransitionTable::contains(UniquedStringImpl* rep, unsigned attributes, bool isAddition) const
+bool StructureTransitionTable::contains(UniquedStringImpl* rep, unsigned attributes, TransitionKind transitionKind) const
 {
     if (isUsingSingleSlot()) {
         Structure* transition = singleTransition();
-        return transition && transition->m_transitionPropertyName == rep && transition->transitionPropertyAttributes() == attributes && transition->isPropertyDeletionTransition() == !isAddition;
+        return transition && transition->m_transitionPropertyName == rep && transition->transitionPropertyAttributes() == attributes && transition->transitionKind() == transitionKind;
     }
-    return map()->get(StructureTransitionTable::Hash::Key(rep, attributes, isAddition));
+    return map()->get(StructureTransitionTable::Hash::Key(rep, attributes, transitionKind));
 }
 
-inline Structure* StructureTransitionTable::get(UniquedStringImpl* rep, unsigned attributes, bool isAddition) const
+inline Structure* StructureTransitionTable::get(UniquedStringImpl* rep, unsigned attributes, TransitionKind transitionKind) const
 {
     if (isUsingSingleSlot()) {
         Structure* transition = singleTransition();
-        return (transition && transition->m_transitionPropertyName == rep && transition->transitionPropertyAttributes() == attributes && transition->isPropertyDeletionTransition() == !isAddition) ? transition : nullptr;
+        return (transition && transition->m_transitionPropertyName == rep && transition->transitionPropertyAttributes() == attributes && transition->transitionKind() == transitionKind) ? transition : nullptr;
     }
-    return map()->get(StructureTransitionTable::Hash::Key(rep, attributes, isAddition));
+    return map()->get(StructureTransitionTable::Hash::Key(rep, attributes, transitionKind));
 }
 
 void StructureTransitionTable::add(VM& vm, Structure* structure)
@@ -114,7 +114,7 @@
     }
 
     // Add the structure to the map.
-    map()->set(StructureTransitionTable::Hash::Key(structure->m_transitionPropertyName.get(), structure->transitionPropertyAttributes(), !structure->isPropertyDeletionTransition()), structure);
+    map()->set(StructureTransitionTable::Hash::Key(structure->m_transitionPropertyName.get(), structure->transitionPropertyAttributes(), structure->transitionKind()), structure);
 }
 
 void Structure::dumpStatistics()
@@ -244,6 +244,7 @@
     setHasUnderscoreProtoPropertyExcludingOriginalProto(false);
     setIsQuickPropertyAccessAllowedForEnumeration(true);
     setTransitionPropertyAttributes(0);
+    setTransitionKind(TransitionKind::Unknown);
     setDidPreventExtensions(false);
     setDidTransition(false);
     setStaticPropertiesReified(false);
@@ -250,7 +251,6 @@
     setTransitionWatchpointIsLikelyToBeFired(false);
     setHasBeenDictionary(false);
     setProtectPropertyTableWhileTransitioning(false);
-    setIsPropertyDeletionTransition(false);
     setTransitionOffset(vm, invalidOffset);
     setMaxOffset(vm, invalidOffset);
  
@@ -282,6 +282,7 @@
     setHasUnderscoreProtoPropertyExcludingOriginalProto(false);
     setIsQuickPropertyAccessAllowedForEnumeration(true);
     setTransitionPropertyAttributes(0);
+    setTransitionKind(TransitionKind::Unknown);
     setDidPreventExtensions(false);
     setDidTransition(false);
     setStaticPropertiesReified(false);
@@ -288,7 +289,6 @@
     setTransitionWatchpointIsLikelyToBeFired(false);
     setHasBeenDictionary(false);
     setProtectPropertyTableWhileTransitioning(false);
-    setIsPropertyDeletionTransition(false);
     setTransitionOffset(vm, invalidOffset);
     setMaxOffset(vm, invalidOffset);
  
@@ -320,12 +320,12 @@
     setHasUnderscoreProtoPropertyExcludingOriginalProto(previous->hasUnderscoreProtoPropertyExcludingOriginalProto());
     setIsQuickPropertyAccessAllowedForEnumeration(previous->isQuickPropertyAccessAllowedForEnumeration());
     setTransitionPropertyAttributes(0);
+    setTransitionKind(TransitionKind::Unknown);
     setDidPreventExtensions(previous->didPreventExtensions());
     setDidTransition(true);
     setStaticPropertiesReified(previous->staticPropertiesReified());
     setHasBeenDictionary(previous->hasBeenDictionary());
     setProtectPropertyTableWhileTransitioning(false);
-    setIsPropertyDeletionTransition(false);
     setTransitionOffset(vm, invalidOffset);
     setMaxOffset(vm, invalidOffset);
  
@@ -472,8 +472,7 @@
     ASSERT(!structure->isDictionary());
     ASSERT(structure->isObject());
 
-    constexpr bool isAddition = true;
-    if (Structure* existingTransition = structure->m_transitionTable.get(uid, attributes, isAddition)) {
+    if (Structure* existingTransition = structure->m_transitionTable.get(uid, attributes, TransitionKind::PropertyAddition)) {
         validateOffset(existingTransition->transitionOffset(), existingTransition->inlineCapacity());
         offset = existingTransition->transitionOffset();
         return existingTransition;
@@ -571,6 +570,7 @@
     transition->m_blob.setIndexingModeIncludingHistory(structure->indexingModeIncludingHistory() & ~CopyOnWrite);
     transition->m_transitionPropertyName = propertyName.uid();
     transition->setTransitionPropertyAttributes(attributes);
+    transition->setTransitionKind(TransitionKind::PropertyAddition);
     transition->setPropertyTable(vm, structure->takePropertyTableOrCloneIfPinned(vm));
     transition->setMaxOffset(vm, structure->maxOffset());
 
@@ -607,9 +607,8 @@
     ASSERT(!structure->isUncacheableDictionary());
     ASSERT(structure->isObject());
 
-    constexpr bool isAddition = false;
     offset = invalidOffset;
-    if (Structure* existingTransition = structure->m_transitionTable.get(propertyName.uid(), attributes, isAddition)) {
+    if (Structure* existingTransition = structure->m_transitionTable.get(propertyName.uid(), attributes, TransitionKind::PropertyDeletion)) {
         validateOffset(existingTransition->transitionOffset(), existingTransition->inlineCapacity());
         offset = existingTransition->transitionOffset();
         return existingTransition;
@@ -667,9 +666,9 @@
 
     transition->m_blob.setIndexingModeIncludingHistory(structure->indexingModeIncludingHistory() & ~CopyOnWrite);
     transition->m_transitionPropertyName = propertyName.uid();
+    transition->setTransitionKind(TransitionKind::PropertyDeletion);
     transition->setPropertyTable(vm, structure->takePropertyTableOrCloneIfPinned(vm));
     transition->setMaxOffset(vm, structure->maxOffset());
-    transition->setIsPropertyDeletionTransition(true);
 
     offset = transition->remove(vm, propertyName);
     ASSERT(offset != invalidOffset);
@@ -762,17 +761,17 @@
 
 Structure* Structure::sealTransition(VM& vm, Structure* structure)
 {
-    return nonPropertyTransition(vm, structure, NonPropertyTransition::Seal);
+    return nonPropertyTransition(vm, structure, TransitionKind::Seal);
 }
 
 Structure* Structure::freezeTransition(VM& vm, Structure* structure)
 {
-    return nonPropertyTransition(vm, structure, NonPropertyTransition::Freeze);
+    return nonPropertyTransition(vm, structure, TransitionKind::Freeze);
 }
 
 Structure* Structure::preventExtensionsTransition(VM& vm, Structure* structure)
 {
-    return nonPropertyTransition(vm, structure, NonPropertyTransition::PreventExtensions);
+    return nonPropertyTransition(vm, structure, TransitionKind::PreventExtensions);
 }
 
 PropertyTable* Structure::takePropertyTableOrCloneIfPinned(VM& vm)
@@ -790,15 +789,13 @@
     return materializePropertyTable(vm, setPropertyTable);
 }
 
-Structure* Structure::nonPropertyTransitionSlow(VM& vm, Structure* structure, NonPropertyTransition transitionKind)
+Structure* Structure::nonPropertyTransitionSlow(VM& vm, Structure* structure, TransitionKind transitionKind)
 {
-    unsigned attributes = toAttributes(transitionKind);
     IndexingType indexingModeIncludingHistory = newIndexingType(structure->indexingModeIncludingHistory(), transitionKind);
     
     Structure* existingTransition;
-    constexpr bool isAddition = true;
-    if (!structure->isDictionary() && (existingTransition = structure->m_transitionTable.get(nullptr, attributes, isAddition))) {
-        ASSERT(existingTransition->transitionPropertyAttributes() == attributes);
+    if (!structure->isDictionary() && (existingTransition = structure->m_transitionTable.get(nullptr, 0, transitionKind))) {
+        ASSERT(existingTransition->transitionKind() == transitionKind);
         ASSERT(existingTransition->indexingModeIncludingHistory() == indexingModeIncludingHistory);
         return existingTransition;
     }
@@ -806,7 +803,7 @@
     DeferGC deferGC(vm.heap);
     
     Structure* transition = create(vm, structure);
-    transition->setTransitionPropertyAttributes(attributes);
+    transition->setTransitionKind(transitionKind);
     transition->m_blob.setIndexingModeIncludingHistory(indexingModeIncludingHistory);
     
     if (preventsExtensions(transitionKind))

Modified: trunk/Source/_javascript_Core/runtime/Structure.h (265639 => 265640)


--- trunk/Source/_javascript_Core/runtime/Structure.h	2020-08-14 00:25:56 UTC (rev 265639)
+++ trunk/Source/_javascript_Core/runtime/Structure.h	2020-08-14 01:56:43 UTC (rev 265640)
@@ -203,8 +203,8 @@
     JS_EXPORT_PRIVATE static Structure* sealTransition(VM&, Structure*);
     JS_EXPORT_PRIVATE static Structure* freezeTransition(VM&, Structure*);
     static Structure* preventExtensionsTransition(VM&, Structure*);
-    static Structure* nonPropertyTransition(VM&, Structure*, NonPropertyTransition);
-    JS_EXPORT_PRIVATE static Structure* nonPropertyTransitionSlow(VM&, Structure*, NonPropertyTransition);
+    static Structure* nonPropertyTransition(VM&, Structure*, TransitionKind);
+    JS_EXPORT_PRIVATE static Structure* nonPropertyTransitionSlow(VM&, Structure*, TransitionKind);
 
     JS_EXPORT_PRIVATE bool isSealed(VM&);
     JS_EXPORT_PRIVATE bool isFrozen(VM&);
@@ -691,7 +691,7 @@
     void set##upperName(type newValue) \
     {\
         m_bitField &= ~(s_##lowerName##Mask << offset);\
-        m_bitField |= (newValue & s_##lowerName##Mask) << offset;\
+        m_bitField |= (static_cast<uint32_t>(newValue) & s_##lowerName##Mask) << offset;\
     }
 
     DEFINE_BITFIELD(DictionaryKind, dictionaryKind, DictionaryKind, 2, 0);
@@ -699,7 +699,8 @@
     DEFINE_BITFIELD(bool, hasGetterSetterProperties, HasGetterSetterProperties, 1, 3);
     DEFINE_BITFIELD(bool, hasReadOnlyOrGetterSetterPropertiesExcludingProto, HasReadOnlyOrGetterSetterPropertiesExcludingProto, 1, 4);
     DEFINE_BITFIELD(bool, isQuickPropertyAccessAllowedForEnumeration, IsQuickPropertyAccessAllowedForEnumeration, 1, 5);
-    DEFINE_BITFIELD(unsigned, transitionPropertyAttributes, TransitionPropertyAttributes, 14, 6);
+    DEFINE_BITFIELD(TransitionPropertyAttributes, transitionPropertyAttributes, TransitionPropertyAttributes, 8, 6);
+    DEFINE_BITFIELD(TransitionKind, transitionKind, TransitionKind, 6, 14);
     DEFINE_BITFIELD(bool, didPreventExtensions, DidPreventExtensions, 1, 20);
     DEFINE_BITFIELD(bool, didTransition, DidTransition, 1, 21);
     DEFINE_BITFIELD(bool, staticPropertiesReified, StaticPropertiesReified, 1, 22);
@@ -710,10 +711,13 @@
     DEFINE_BITFIELD(bool, hasBeenDictionary, HasBeenDictionary, 1, 27);
     DEFINE_BITFIELD(bool, protectPropertyTableWhileTransitioning, ProtectPropertyTableWhileTransitioning, 1, 28);
     DEFINE_BITFIELD(bool, hasUnderscoreProtoPropertyExcludingOriginalProto, HasUnderscoreProtoPropertyExcludingOriginalProto, 1, 29);
-    DEFINE_BITFIELD(bool, isPropertyDeletionTransition, IsPropertyDeletionTransition, 1, 30);
 
     static_assert(s_bitWidthOfTransitionPropertyAttributes <= sizeof(TransitionPropertyAttributes) * 8);
+    static_assert(s_bitWidthOfTransitionKind <= sizeof(TransitionKind) * 8);
 
+    bool isPropertyAdditionTransition() const { return transitionKind() == TransitionKind::PropertyAddition; }
+    bool isPropertyDeletionTransition() const { return transitionKind() == TransitionKind::PropertyDeletion; }
+
 private:
     friend class LLIntOffsetsExtractor;
 

Modified: trunk/Source/_javascript_Core/runtime/StructureInlines.h (265639 => 265640)


--- trunk/Source/_javascript_Core/runtime/StructureInlines.h	2020-08-14 00:25:56 UTC (rev 265639)
+++ trunk/Source/_javascript_Core/runtime/StructureInlines.h	2020-08-14 01:56:43 UTC (rev 265640)
@@ -608,7 +608,7 @@
     return !aObj && !bObj;
 }
 
-inline Structure* Structure::nonPropertyTransition(VM& vm, Structure* structure, NonPropertyTransition transitionKind)
+inline Structure* Structure::nonPropertyTransition(VM& vm, Structure* structure, TransitionKind transitionKind)
 {
     IndexingType indexingModeIncludingHistory = newIndexingType(structure->indexingModeIncludingHistory(), transitionKind);
 

Modified: trunk/Source/_javascript_Core/runtime/StructureTransitionTable.h (265639 => 265640)


--- trunk/Source/_javascript_Core/runtime/StructureTransitionTable.h	2020-08-14 00:25:56 UTC (rev 265639)
+++ trunk/Source/_javascript_Core/runtime/StructureTransitionTable.h	2020-08-14 01:56:43 UTC (rev 265640)
@@ -35,11 +35,16 @@
 class JSCell;
 class Structure;
 
-static constexpr unsigned FirstInternalAttribute = 1 << 6; // Use for transitions that don't have to do with property additions.
+using TransitionPropertyAttributes = uint8_t;
 
-// Support for attributes used to indicate transitions not related to properties.
-// If any of these are used, the string portion of the key should be 0.
-enum class NonPropertyTransition : unsigned {
+enum class TransitionKind : uint8_t {
+    Unknown,
+    PropertyAddition,
+    PropertyDeletion,
+    PropertyAttributeChange,
+
+    // Support for transitions not related to properties.
+    // If any of these are used, the string portion of the key should be 0.
     AllocateUndecided,
     AllocateInt32,
     AllocateDouble,
@@ -52,24 +57,20 @@
     Seal,
     Freeze
 };
-using TransitionPropertyAttributes = uint16_t;
 
-inline unsigned toAttributes(NonPropertyTransition transition)
-{
-    return static_cast<unsigned>(transition) + FirstInternalAttribute;
-}
+static constexpr auto FirstNonPropertyTransitionKind = TransitionKind::AllocateUndecided;
 
-inline bool changesIndexingType(NonPropertyTransition transition)
+inline bool changesIndexingType(TransitionKind transition)
 {
     switch (transition) {
-    case NonPropertyTransition::AllocateUndecided:
-    case NonPropertyTransition::AllocateInt32:
-    case NonPropertyTransition::AllocateDouble:
-    case NonPropertyTransition::AllocateContiguous:
-    case NonPropertyTransition::AllocateArrayStorage:
-    case NonPropertyTransition::AllocateSlowPutArrayStorage:
-    case NonPropertyTransition::SwitchToSlowPutArrayStorage:
-    case NonPropertyTransition::AddIndexedAccessors:
+    case TransitionKind::AllocateUndecided:
+    case TransitionKind::AllocateInt32:
+    case TransitionKind::AllocateDouble:
+    case TransitionKind::AllocateContiguous:
+    case TransitionKind::AllocateArrayStorage:
+    case TransitionKind::AllocateSlowPutArrayStorage:
+    case TransitionKind::SwitchToSlowPutArrayStorage:
+    case TransitionKind::AddIndexedAccessors:
         return true;
     default:
         return false;
@@ -76,31 +77,31 @@
     }
 }
 
-inline IndexingType newIndexingType(IndexingType oldType, NonPropertyTransition transition)
+inline IndexingType newIndexingType(IndexingType oldType, TransitionKind transition)
 {
     switch (transition) {
-    case NonPropertyTransition::AllocateUndecided:
+    case TransitionKind::AllocateUndecided:
         ASSERT(!hasIndexedProperties(oldType));
         return oldType | UndecidedShape;
-    case NonPropertyTransition::AllocateInt32:
+    case TransitionKind::AllocateInt32:
         ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || oldType == CopyOnWriteArrayWithInt32);
         return (oldType & ~IndexingShapeAndWritabilityMask) | Int32Shape;
-    case NonPropertyTransition::AllocateDouble:
+    case TransitionKind::AllocateDouble:
         ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || oldType == CopyOnWriteArrayWithDouble);
         return (oldType & ~IndexingShapeAndWritabilityMask) | DoubleShape;
-    case NonPropertyTransition::AllocateContiguous:
+    case TransitionKind::AllocateContiguous:
         ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || oldType == CopyOnWriteArrayWithContiguous);
         return (oldType & ~IndexingShapeAndWritabilityMask) | ContiguousShape;
-    case NonPropertyTransition::AllocateArrayStorage:
+    case TransitionKind::AllocateArrayStorage:
         ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType));
         return (oldType & ~IndexingShapeAndWritabilityMask) | ArrayStorageShape;
-    case NonPropertyTransition::AllocateSlowPutArrayStorage:
+    case TransitionKind::AllocateSlowPutArrayStorage:
         ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType));
         return (oldType & ~IndexingShapeAndWritabilityMask) | SlowPutArrayStorageShape;
-    case NonPropertyTransition::SwitchToSlowPutArrayStorage:
+    case TransitionKind::SwitchToSlowPutArrayStorage:
         ASSERT(hasArrayStorage(oldType));
         return (oldType & ~IndexingShapeAndWritabilityMask) | SlowPutArrayStorageShape;
-    case NonPropertyTransition::AddIndexedAccessors:
+    case TransitionKind::AddIndexedAccessors:
         return oldType | MayHaveIndexedAccessors;
     default:
         return oldType;
@@ -107,12 +108,12 @@
     }
 }
 
-inline bool preventsExtensions(NonPropertyTransition transition)
+inline bool preventsExtensions(TransitionKind transition)
 {
     switch (transition) {
-    case NonPropertyTransition::PreventExtensions:
-    case NonPropertyTransition::Seal:
-    case NonPropertyTransition::Freeze:
+    case TransitionKind::PreventExtensions:
+    case TransitionKind::Seal:
+    case TransitionKind::Freeze:
         return true;
     default:
         return false;
@@ -119,11 +120,11 @@
     }
 }
 
-inline bool setsDontDeleteOnAllProperties(NonPropertyTransition transition)
+inline bool setsDontDeleteOnAllProperties(TransitionKind transition)
 {
     switch (transition) {
-    case NonPropertyTransition::Seal:
-    case NonPropertyTransition::Freeze:
+    case TransitionKind::Seal:
+    case TransitionKind::Freeze:
         return true;
     default:
         return false;
@@ -130,10 +131,10 @@
     }
 }
 
-inline bool setsReadOnlyOnNonAccessorProperties(NonPropertyTransition transition)
+inline bool setsReadOnlyOnNonAccessorProperties(TransitionKind transition)
 {
     switch (transition) {
-    case NonPropertyTransition::Freeze:
+    case TransitionKind::Freeze:
         return true;
     default:
         return false;
@@ -146,27 +147,28 @@
     
 #if CPU(ADDRESS64)
     struct Hash {
-        // Logically, Key is a tuple of (1) UniquedStringImpl*, (2) unsigned attributes, and (3) bool isAddition.
-        // We encode (2) and (3) into (1)'s empty bits since a pointer is 48bit and lower 3 bits are usable because of alignment.
+        // Logically, Key is a tuple of (1) UniquedStringImpl*, (2) unsigned attributes, and (3) transitionKind.
         struct Key {
             friend struct Hash;
             static_assert(WTF_OS_CONSTANT_EFFECTIVE_ADDRESS_WIDTH <= 48);
-            static constexpr uintptr_t isAdditionMask = 1ULL;
-            static constexpr uintptr_t stringMask = ((1ULL << 48) - 1) & (~isAdditionMask);
             static constexpr unsigned attributesShift = 48;
+            static constexpr unsigned transitionKindShift = 56;
+            static constexpr uintptr_t stringMask = (1ULL << attributesShift) - 1;
             static constexpr uintptr_t hashTableDeletedValue = 0x2;
-            static_assert(sizeof(TransitionPropertyAttributes) * 8 <= 16);
+            static_assert(sizeof(TransitionPropertyAttributes) * 8 <= 8);
+            static_assert(sizeof(TransitionKind) * 8 <= 8);
             static_assert(hashTableDeletedValue < alignof(UniquedStringImpl));
 
-            // Highest 16 bits are for TransitionPropertyAttributes.
-            // Lowest 1 bit is for isAddition flag.
+            // Highest 8 bits are for TransitionKind; next 8 belong to TransitionPropertyAttributes.
             // Remaining bits are for UniquedStringImpl*.
-            Key(UniquedStringImpl* impl, unsigned attributes, bool isAddition)
-                : m_encodedData(bitwise_cast<uintptr_t>(impl) | (static_cast<uintptr_t>(attributes) << attributesShift) | (static_cast<uintptr_t>(isAddition) & isAdditionMask))
+            Key(UniquedStringImpl* impl, unsigned attributes, TransitionKind transitionKind)
+                : m_encodedData(bitwise_cast<uintptr_t>(impl) | (static_cast<uintptr_t>(attributes) << attributesShift) | (static_cast<uintptr_t>(transitionKind) << transitionKindShift))
             {
                 ASSERT(impl == this->impl());
-                ASSERT(isAddition == this->isAddition());
+                ASSERT(attributes <= UINT8_MAX);
                 ASSERT(attributes == this->attributes());
+                ASSERT(transitionKind != TransitionKind::Unknown);
+                ASSERT(transitionKind == this->transitionKind());
             }
 
             Key() = default;
@@ -178,8 +180,8 @@
             bool isHashTableDeletedValue() const { return m_encodedData == hashTableDeletedValue; }
 
             UniquedStringImpl* impl() const { return bitwise_cast<UniquedStringImpl*>(m_encodedData & stringMask); }
-            bool isAddition() const { return m_encodedData & isAdditionMask; }
-            unsigned attributes() const { return m_encodedData >> attributesShift; }
+            TransitionPropertyAttributes attributes() const { return (m_encodedData >> attributesShift) & UINT8_MAX; }
+            TransitionKind transitionKind() const { return static_cast<TransitionKind>(m_encodedData >> transitionKindShift); }
 
             friend bool operator==(const Key& a, const Key& b)
             {
@@ -210,12 +212,12 @@
     };
 #else
     struct Hash {
-        using Key = std::tuple<UniquedStringImpl*, unsigned, bool>;
+        using Key = std::tuple<UniquedStringImpl*, unsigned, TransitionKind>;
         using KeyTraits = HashTraits<Key>;
         
         static unsigned hash(const Key& p)
         {
-            return PtrHash<UniquedStringImpl*>::hash(std::get<0>(p)) + std::get<1>(p);
+            return PtrHash<UniquedStringImpl*>::hash(std::get<0>(p)) + std::get<1>(p) + static_cast<unsigned>(std::get<2>(p));
         }
 
         static bool equal(const Key& a, const Key& b)
@@ -249,8 +251,8 @@
     }
 
     void add(VM&, Structure*);
-    bool contains(UniquedStringImpl*, unsigned attributes, bool isAddition) const;
-    Structure* get(UniquedStringImpl*, unsigned attributes, bool isAddition) const;
+    bool contains(UniquedStringImpl*, unsigned attributes, TransitionKind) const;
+    Structure* get(UniquedStringImpl*, unsigned attributes, TransitionKind) const;
 
 private:
     friend class SingleSlotTransitionWeakOwner;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to