aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/builtins-collections-gen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/builtins/builtins-collections-gen.cc')
-rw-r--r--deps/v8/src/builtins/builtins-collections-gen.cc712
1 files changed, 502 insertions, 210 deletions
diff --git a/deps/v8/src/builtins/builtins-collections-gen.cc b/deps/v8/src/builtins/builtins-collections-gen.cc
index 1ff64b0877..d782f241b0 100644
--- a/deps/v8/src/builtins/builtins-collections-gen.cc
+++ b/deps/v8/src/builtins/builtins-collections-gen.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/builtins/builtins-collections-gen.h"
+
#include "src/builtins/builtins-constructor-gen.h"
#include "src/builtins/builtins-iterator-gen.h"
#include "src/builtins/builtins-utils-gen.h"
@@ -9,6 +11,8 @@
#include "src/heap/factory-inl.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/js-collection.h"
+#include "torque-generated/builtins-base-from-dsl-gen.h"
+#include "torque-generated/builtins-collections-from-dsl-gen.h"
namespace v8 {
namespace internal {
@@ -19,10 +23,11 @@ using TNode = compiler::TNode<T>;
template <class T>
using TVariable = compiler::TypedCodeAssemblerVariable<T>;
-class BaseCollectionsAssembler : public CodeStubAssembler {
+class BaseCollectionsAssembler : public CodeStubAssembler,
+ public CollectionsBuiltinsFromDSLAssembler {
public:
explicit BaseCollectionsAssembler(compiler::CodeAssemblerState* state)
- : CodeStubAssembler(state) {}
+ : CodeStubAssembler(state), CollectionsBuiltinsFromDSLAssembler(state) {}
virtual ~BaseCollectionsAssembler() = default;
@@ -101,6 +106,16 @@ class BaseCollectionsAssembler : public CodeStubAssembler {
TNode<JSFunction> GetInitialAddFunction(Variant variant,
TNode<Context> native_context);
+ // Checks whether {collection}'s initial add/set function has been modified
+ // (depending on {variant}, loaded from {native_context}).
+ void GotoIfInitialAddFunctionModified(Variant variant,
+ TNode<Context> native_context,
+ TNode<Object> collection,
+ Label* if_modified);
+
+ // Gets root index for the name of the add/set function.
+ RootIndex GetAddFunctionNameIndex(Variant variant);
+
// Retrieves the offset to access the backing table from the collection.
int GetTableOffset(Variant variant);
@@ -117,6 +132,10 @@ class BaseCollectionsAssembler : public CodeStubAssembler {
TNode<Context> native_context,
TNode<Object> collection);
+ // Gets the initial prototype map for given collection {variant}.
+ TNode<Map> GetInitialCollectionPrototype(Variant variant,
+ TNode<Context> native_context);
+
// Loads an element from a fixed array. If the element is the hole, returns
// `undefined`.
TNode<Object> LoadAndNormalizeFixedArrayElement(TNode<FixedArray> elements,
@@ -126,14 +145,6 @@ class BaseCollectionsAssembler : public CodeStubAssembler {
// returns `undefined`.
TNode<Object> LoadAndNormalizeFixedDoubleArrayElement(
TNode<HeapObject> elements, TNode<IntPtrT> index);
-
- // Loads key and value variables with the first and second elements of an
- // array. If the array lacks 2 elements, undefined is used.
- void LoadKeyValue(TNode<Context> context, TNode<Object> maybe_array,
- TVariable<Object>* key, TVariable<Object>* value,
- Label* if_may_have_side_effects = nullptr,
- Label* if_exception = nullptr,
- TVariable<Object>* var_exception = nullptr);
};
void BaseCollectionsAssembler::AddConstructorEntry(
@@ -141,22 +152,23 @@ void BaseCollectionsAssembler::AddConstructorEntry(
TNode<Object> add_function, TNode<Object> key_value,
Label* if_may_have_side_effects, Label* if_exception,
TVariable<Object>* var_exception) {
+ compiler::CodeAssemblerScopedExceptionHandler handler(this, if_exception,
+ var_exception);
CSA_ASSERT(this, Word32BinaryNot(IsTheHole(key_value)));
if (variant == kMap || variant == kWeakMap) {
- TVARIABLE(Object, key);
- TVARIABLE(Object, value);
- LoadKeyValue(context, key_value, &key, &value, if_may_have_side_effects,
- if_exception, var_exception);
- Node* key_n = key.value();
- Node* value_n = value.value();
- Node* ret = CallJS(CodeFactory::Call(isolate()), context, add_function,
- collection, key_n, value_n);
- GotoIfException(ret, if_exception, var_exception);
+ BaseBuiltinsFromDSLAssembler::KeyValuePair pair =
+ if_may_have_side_effects != nullptr
+ ? LoadKeyValuePairNoSideEffects(context, key_value,
+ if_may_have_side_effects)
+ : LoadKeyValuePair(context, key_value);
+ Node* key_n = pair.key;
+ Node* value_n = pair.value;
+ CallJS(CodeFactory::Call(isolate()), context, add_function, collection,
+ key_n, value_n);
} else {
DCHECK(variant == kSet || variant == kWeakSet);
- Node* ret = CallJS(CodeFactory::Call(isolate()), context, add_function,
- collection, key_value);
- GotoIfException(ret, if_exception, var_exception);
+ CallJS(CodeFactory::Call(isolate()), context, add_function, collection,
+ key_value);
}
}
@@ -164,7 +176,7 @@ void BaseCollectionsAssembler::AddConstructorEntries(
Variant variant, TNode<Context> context, TNode<Context> native_context,
TNode<Object> collection, TNode<Object> initial_entries) {
TVARIABLE(BoolT, use_fast_loop,
- IsFastJSArrayWithNoCustomIteration(initial_entries, context));
+ IsFastJSArrayWithNoCustomIteration(context, initial_entries));
TNode<IntPtrT> at_least_space_for =
EstimatedInitialSize(initial_entries, use_fast_loop.value());
Label allocate_table(this, &use_fast_loop), exit(this), fast_loop(this),
@@ -175,9 +187,8 @@ void BaseCollectionsAssembler::AddConstructorEntries(
TNode<Object> table = AllocateTable(variant, context, at_least_space_for);
StoreObjectField(collection, GetTableOffset(variant), table);
GotoIf(IsNullOrUndefined(initial_entries), &exit);
- GotoIfNot(
- HasInitialCollectionPrototype(variant, native_context, collection),
- &slow_loop);
+ GotoIfInitialAddFunctionModified(variant, native_context, collection,
+ &slow_loop);
Branch(use_fast_loop.value(), &fast_loop, &slow_loop);
}
BIND(&fast_loop);
@@ -185,8 +196,8 @@ void BaseCollectionsAssembler::AddConstructorEntries(
TNode<JSArray> initial_entries_jsarray =
UncheckedCast<JSArray>(initial_entries);
#if DEBUG
- CSA_ASSERT(this, IsFastJSArrayWithNoCustomIteration(initial_entries_jsarray,
- context));
+ CSA_ASSERT(this, IsFastJSArrayWithNoCustomIteration(
+ context, initial_entries_jsarray));
TNode<Map> original_initial_entries_map = LoadMap(initial_entries_jsarray);
#endif
@@ -199,8 +210,16 @@ void BaseCollectionsAssembler::AddConstructorEntries(
if (variant == kMap || variant == kWeakMap) {
BIND(&if_may_have_side_effects);
#if DEBUG
- CSA_ASSERT(this, HasInitialCollectionPrototype(variant, native_context,
- collection));
+ {
+ // Check that add/set function has not been modified.
+ Label if_not_modified(this), if_modified(this);
+ GotoIfInitialAddFunctionModified(variant, native_context, collection,
+ &if_modified);
+ Goto(&if_not_modified);
+ BIND(&if_modified);
+ Unreachable();
+ BIND(&if_not_modified);
+ }
CSA_ASSERT(this, WordEqual(original_initial_entries_map,
LoadMap(initial_entries_jsarray)));
#endif
@@ -227,7 +246,7 @@ void BaseCollectionsAssembler::AddConstructorEntriesFromFastJSArray(
CSA_ASSERT(
this,
WordEqual(GetAddFunction(variant, native_context, collection), add_func));
- CSA_ASSERT(this, IsFastJSArrayWithNoCustomIteration(fast_jsarray, context));
+ CSA_ASSERT(this, IsFastJSArrayWithNoCustomIteration(context, fast_jsarray));
TNode<IntPtrT> length = SmiUntag(LoadFastJSArrayLength(fast_jsarray));
CSA_ASSERT(this, IntPtrGreaterThanOrEqual(length, IntPtrConstant(0)));
CSA_ASSERT(
@@ -297,7 +316,8 @@ void BaseCollectionsAssembler::AddConstructorEntriesFromIterable(
TNode<Object> add_func = GetAddFunction(variant, context, collection);
IteratorBuiltinsAssembler iterator_assembler(this->state());
- IteratorRecord iterator = iterator_assembler.GetIterator(context, iterable);
+ IteratorBuiltinsAssembler::IteratorRecord iterator =
+ iterator_assembler.GetIterator(context, iterable);
CSA_ASSERT(this, Word32BinaryNot(IsUndefined(iterator.object)));
@@ -308,8 +328,8 @@ void BaseCollectionsAssembler::AddConstructorEntriesFromIterable(
Goto(&loop);
BIND(&loop);
{
- TNode<Object> next = CAST(iterator_assembler.IteratorStep(
- context, iterator, &exit, fast_iterator_result_map));
+ TNode<Object> next = iterator_assembler.IteratorStep(
+ context, iterator, &exit, fast_iterator_result_map);
TNode<Object> next_value = CAST(iterator_assembler.IteratorValue(
context, next, fast_iterator_result_map));
AddConstructorEntry(variant, context, collection, add_func, next_value,
@@ -319,11 +339,35 @@ void BaseCollectionsAssembler::AddConstructorEntriesFromIterable(
BIND(&if_exception);
{
iterator_assembler.IteratorCloseOnException(context, iterator,
- &var_exception);
+ var_exception.value());
}
BIND(&exit);
}
+RootIndex BaseCollectionsAssembler::GetAddFunctionNameIndex(Variant variant) {
+ switch (variant) {
+ case kMap:
+ case kWeakMap:
+ return RootIndex::kset_string;
+ case kSet:
+ case kWeakSet:
+ return RootIndex::kadd_string;
+ }
+ UNREACHABLE();
+}
+
+void BaseCollectionsAssembler::GotoIfInitialAddFunctionModified(
+ Variant variant, TNode<Context> native_context, TNode<Object> collection,
+ Label* if_modified) {
+ STATIC_ASSERT(JSCollection::kAddFunctionDescriptorIndex ==
+ JSWeakCollection::kAddFunctionDescriptorIndex);
+ GotoIfInitialPrototypePropertyModified(
+ LoadMap(CAST(collection)),
+ GetInitialCollectionPrototype(variant, native_context),
+ JSCollection::kAddFunctionDescriptorIndex,
+ GetAddFunctionNameIndex(variant), if_modified);
+}
+
TNode<Object> BaseCollectionsAssembler::AllocateJSCollection(
TNode<Context> context, TNode<JSFunction> constructor,
TNode<Object> new_target) {
@@ -463,8 +507,8 @@ void BaseCollectionsAssembler::GotoIfNotJSReceiver(Node* const obj,
GotoIfNot(IsJSReceiver(obj), if_not_receiver);
}
-TNode<BoolT> BaseCollectionsAssembler::HasInitialCollectionPrototype(
- Variant variant, TNode<Context> native_context, TNode<Object> collection) {
+TNode<Map> BaseCollectionsAssembler::GetInitialCollectionPrototype(
+ Variant variant, TNode<Context> native_context) {
int initial_prototype_index;
switch (variant) {
case kMap:
@@ -480,12 +524,16 @@ TNode<BoolT> BaseCollectionsAssembler::HasInitialCollectionPrototype(
initial_prototype_index = Context::INITIAL_WEAKSET_PROTOTYPE_MAP_INDEX;
break;
}
- TNode<Map> initial_prototype_map =
- CAST(LoadContextElement(native_context, initial_prototype_index));
+ return CAST(LoadContextElement(native_context, initial_prototype_index));
+}
+
+TNode<BoolT> BaseCollectionsAssembler::HasInitialCollectionPrototype(
+ Variant variant, TNode<Context> native_context, TNode<Object> collection) {
TNode<Map> collection_proto_map =
LoadMap(LoadMapPrototype(LoadMap(CAST(collection))));
- return WordEqual(collection_proto_map, initial_prototype_map);
+ return WordEqual(collection_proto_map,
+ GetInitialCollectionPrototype(variant, native_context));
}
TNode<Object> BaseCollectionsAssembler::LoadAndNormalizeFixedArrayElement(
@@ -515,114 +563,27 @@ TNode<Object> BaseCollectionsAssembler::LoadAndNormalizeFixedDoubleArrayElement(
return entry.value();
}
-void BaseCollectionsAssembler::LoadKeyValue(
- TNode<Context> context, TNode<Object> maybe_array, TVariable<Object>* key,
- TVariable<Object>* value, Label* if_may_have_side_effects,
- Label* if_exception, TVariable<Object>* var_exception) {
- CSA_ASSERT(this, Word32BinaryNot(IsTheHole(maybe_array)));
-
- Label exit(this), if_fast(this), if_slow(this, Label::kDeferred);
- BranchIfFastJSArray(maybe_array, context, &if_fast, &if_slow);
- BIND(&if_fast);
- {
- TNode<JSArray> array = CAST(maybe_array);
- TNode<Smi> length = LoadFastJSArrayLength(array);
- TNode<FixedArrayBase> elements = LoadElements(array);
- TNode<Int32T> elements_kind = LoadElementsKind(array);
-
- Label if_smiorobjects(this), if_doubles(this);
- Branch(IsFastSmiOrTaggedElementsKind(elements_kind), &if_smiorobjects,
- &if_doubles);
- BIND(&if_smiorobjects);
- {
- Label if_one(this), if_two(this);
- GotoIf(SmiGreaterThan(length, SmiConstant(1)), &if_two);
- GotoIf(SmiEqual(length, SmiConstant(1)), &if_one);
- { // empty array
- *key = UndefinedConstant();
- *value = UndefinedConstant();
- Goto(&exit);
- }
- BIND(&if_one);
- {
- *key = LoadAndNormalizeFixedArrayElement(CAST(elements),
- IntPtrConstant(0));
- *value = UndefinedConstant();
- Goto(&exit);
- }
- BIND(&if_two);
- {
- TNode<FixedArray> elements_fixed_array = CAST(elements);
- *key = LoadAndNormalizeFixedArrayElement(elements_fixed_array,
- IntPtrConstant(0));
- *value = LoadAndNormalizeFixedArrayElement(elements_fixed_array,
- IntPtrConstant(1));
- Goto(&exit);
- }
- }
- BIND(&if_doubles);
- {
- Label if_one(this), if_two(this);
- GotoIf(SmiGreaterThan(length, SmiConstant(1)), &if_two);
- GotoIf(SmiEqual(length, SmiConstant(1)), &if_one);
- { // empty array
- *key = UndefinedConstant();
- *value = UndefinedConstant();
- Goto(&exit);
- }
- BIND(&if_one);
- {
- *key = LoadAndNormalizeFixedDoubleArrayElement(elements,
- IntPtrConstant(0));
- *value = UndefinedConstant();
- Goto(&exit);
- }
- BIND(&if_two);
- {
- *key = LoadAndNormalizeFixedDoubleArrayElement(elements,
- IntPtrConstant(0));
- *value = LoadAndNormalizeFixedDoubleArrayElement(elements,
- IntPtrConstant(1));
- Goto(&exit);
- }
- }
- }
- BIND(&if_slow);
- {
- Label if_notobject(this, Label::kDeferred);
- GotoIfNotJSReceiver(maybe_array, &if_notobject);
- if (if_may_have_side_effects != nullptr) {
- // If the element is not a fast array, we cannot guarantee accessing the
- // key and value won't execute user code that will break fast path
- // assumptions.
- Goto(if_may_have_side_effects);
- } else {
- *key = UncheckedCast<Object>(GetProperty(
- context, maybe_array, isolate()->factory()->zero_string()));
- GotoIfException(key->value(), if_exception, var_exception);
-
- *value = UncheckedCast<Object>(GetProperty(
- context, maybe_array, isolate()->factory()->one_string()));
- GotoIfException(value->value(), if_exception, var_exception);
- Goto(&exit);
- }
- BIND(&if_notobject);
- {
- Node* ret = CallRuntime(
- Runtime::kThrowTypeError, context,
- SmiConstant(MessageTemplate::kIteratorValueNotAnObject), maybe_array);
- GotoIfException(ret, if_exception, var_exception);
- Unreachable();
- }
- }
- BIND(&exit);
-}
-
class CollectionsBuiltinsAssembler : public BaseCollectionsAssembler {
public:
explicit CollectionsBuiltinsAssembler(compiler::CodeAssemblerState* state)
: BaseCollectionsAssembler(state) {}
+ // Check whether |iterable| is a JS_MAP_KEY_ITERATOR_TYPE or
+ // JS_MAP_VALUE_ITERATOR_TYPE object that is not partially consumed and still
+ // has original iteration behavior.
+ void BranchIfIterableWithOriginalKeyOrValueMapIterator(TNode<Object> iterable,
+ TNode<Context> context,
+ Label* if_true,
+ Label* if_false);
+
+ // Check whether |iterable| is a JS_SET_TYPE or JS_SET_VALUE_ITERATOR_TYPE
+ // object that still has original iteration behavior. In case of the iterator,
+ // the iterator also must not have been partially consumed.
+ void BranchIfIterableWithOriginalValueSetIterator(TNode<Object> iterable,
+ TNode<Context> context,
+ Label* if_true,
+ Label* if_false);
+
protected:
template <typename IteratorType>
Node* AllocateJSCollectionIterator(Node* context, int map_index,
@@ -720,6 +681,26 @@ class CollectionsBuiltinsAssembler : public BaseCollectionsAssembler {
Node* const key, Node* const hash,
Node* const number_of_buckets,
Node* const occupancy);
+
+ // Create a JSArray with PACKED_ELEMENTS kind from a Map.prototype.keys() or
+ // Map.prototype.values() iterator. The iterator is assumed to satisfy
+ // IterableWithOriginalKeyOrValueMapIterator. This function will skip the
+ // iterator and iterate directly on the underlying hash table. In the end it
+ // will update the state of the iterator to 'exhausted'.
+ TNode<JSArray> MapIteratorToList(TNode<Context> context,
+ TNode<JSMapIterator> iterator);
+
+ // Create a JSArray with PACKED_ELEMENTS kind from a Set.prototype.keys() or
+ // Set.prototype.values() iterator, or a Set. The |iterable| is assumed to
+ // satisfy IterableWithOriginalValueSetIterator. This function will skip the
+ // iterator and iterate directly on the underlying hash table. In the end, if
+ // |iterable| is an iterator, it will update the state of the iterator to
+ // 'exhausted'.
+ TNode<JSArray> SetOrSetIteratorToList(TNode<Context> context,
+ TNode<Object> iterable);
+
+ void BranchIfMapIteratorProtectorValid(Label* if_true, Label* if_false);
+ void BranchIfSetIteratorProtectorValid(Label* if_true, Label* if_false);
};
template <typename IteratorType>
@@ -841,6 +822,308 @@ void CollectionsBuiltinsAssembler::SameValueZeroSmi(Node* key_smi,
Goto(if_not_same);
}
+void CollectionsBuiltinsAssembler::BranchIfMapIteratorProtectorValid(
+ Label* if_true, Label* if_false) {
+ Node* protector_cell = LoadRoot(RootIndex::kMapIteratorProtector);
+ DCHECK(isolate()->heap()->map_iterator_protector()->IsPropertyCell());
+ Branch(WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset),
+ SmiConstant(Isolate::kProtectorValid)),
+ if_true, if_false);
+}
+
+void CollectionsBuiltinsAssembler::
+ BranchIfIterableWithOriginalKeyOrValueMapIterator(TNode<Object> iterator,
+ TNode<Context> context,
+ Label* if_true,
+ Label* if_false) {
+ Label if_key_or_value_iterator(this), extra_checks(this);
+
+ // Check if iterator is a keys or values JSMapIterator.
+ GotoIf(TaggedIsSmi(iterator), if_false);
+ TNode<Map> iter_map = LoadMap(CAST(iterator));
+ Node* const instance_type = LoadMapInstanceType(iter_map);
+ GotoIf(InstanceTypeEqual(instance_type, JS_MAP_KEY_ITERATOR_TYPE),
+ &if_key_or_value_iterator);
+ Branch(InstanceTypeEqual(instance_type, JS_MAP_VALUE_ITERATOR_TYPE),
+ &if_key_or_value_iterator, if_false);
+
+ BIND(&if_key_or_value_iterator);
+ // Check that the iterator is not partially consumed.
+ Node* const index =
+ LoadObjectField(CAST(iterator), JSMapIterator::kIndexOffset);
+ GotoIfNot(WordEqual(index, SmiConstant(0)), if_false);
+ BranchIfMapIteratorProtectorValid(&extra_checks, if_false);
+
+ BIND(&extra_checks);
+ // Check if the iterator object has the original %MapIteratorPrototype%.
+ Node* const native_context = LoadNativeContext(context);
+ Node* const initial_map_iter_proto = LoadContextElement(
+ native_context, Context::INITIAL_MAP_ITERATOR_PROTOTYPE_INDEX);
+ Node* const map_iter_proto = LoadMapPrototype(iter_map);
+ GotoIfNot(WordEqual(map_iter_proto, initial_map_iter_proto), if_false);
+
+ // Check if the original MapIterator prototype has the original
+ // %IteratorPrototype%.
+ Node* const initial_iter_proto = LoadContextElement(
+ native_context, Context::INITIAL_ITERATOR_PROTOTYPE_INDEX);
+ Node* const iter_proto = LoadMapPrototype(LoadMap(map_iter_proto));
+ Branch(WordEqual(iter_proto, initial_iter_proto), if_true, if_false);
+}
+
+void BranchIfIterableWithOriginalKeyOrValueMapIterator(
+ compiler::CodeAssemblerState* state, TNode<Object> iterable,
+ TNode<Context> context, compiler::CodeAssemblerLabel* if_true,
+ compiler::CodeAssemblerLabel* if_false) {
+ CollectionsBuiltinsAssembler assembler(state);
+ assembler.BranchIfIterableWithOriginalKeyOrValueMapIterator(
+ iterable, context, if_true, if_false);
+}
+
+void CollectionsBuiltinsAssembler::BranchIfSetIteratorProtectorValid(
+ Label* if_true, Label* if_false) {
+ Node* const protector_cell = LoadRoot(RootIndex::kSetIteratorProtector);
+ DCHECK(isolate()->heap()->set_iterator_protector()->IsPropertyCell());
+ Branch(WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset),
+ SmiConstant(Isolate::kProtectorValid)),
+ if_true, if_false);
+}
+
+void CollectionsBuiltinsAssembler::BranchIfIterableWithOriginalValueSetIterator(
+ TNode<Object> iterable, TNode<Context> context, Label* if_true,
+ Label* if_false) {
+ Label if_set(this), if_value_iterator(this), check_protector(this);
+ TVARIABLE(BoolT, var_result);
+
+ GotoIf(TaggedIsSmi(iterable), if_false);
+ TNode<Map> iterable_map = LoadMap(CAST(iterable));
+ Node* const instance_type = LoadMapInstanceType(iterable_map);
+
+ GotoIf(InstanceTypeEqual(instance_type, JS_SET_TYPE), &if_set);
+ Branch(InstanceTypeEqual(instance_type, JS_SET_VALUE_ITERATOR_TYPE),
+ &if_value_iterator, if_false);
+
+ BIND(&if_set);
+ // Check if the set object has the original Set prototype.
+ Node* const initial_set_proto = LoadContextElement(
+ LoadNativeContext(context), Context::INITIAL_SET_PROTOTYPE_INDEX);
+ Node* const set_proto = LoadMapPrototype(iterable_map);
+ GotoIfNot(WordEqual(set_proto, initial_set_proto), if_false);
+ Goto(&check_protector);
+
+ BIND(&if_value_iterator);
+ // Check that the iterator is not partially consumed.
+ Node* const index =
+ LoadObjectField(CAST(iterable), JSSetIterator::kIndexOffset);
+ GotoIfNot(WordEqual(index, SmiConstant(0)), if_false);
+
+ // Check if the iterator object has the original SetIterator prototype.
+ Node* const native_context = LoadNativeContext(context);
+ Node* const initial_set_iter_proto = LoadContextElement(
+ native_context, Context::INITIAL_SET_ITERATOR_PROTOTYPE_INDEX);
+ Node* const set_iter_proto = LoadMapPrototype(iterable_map);
+ GotoIfNot(WordEqual(set_iter_proto, initial_set_iter_proto), if_false);
+
+ // Check if the original SetIterator prototype has the original
+ // %IteratorPrototype%.
+ Node* const initial_iter_proto = LoadContextElement(
+ native_context, Context::INITIAL_ITERATOR_PROTOTYPE_INDEX);
+ Node* const iter_proto = LoadMapPrototype(LoadMap(set_iter_proto));
+ GotoIfNot(WordEqual(iter_proto, initial_iter_proto), if_false);
+ Goto(&check_protector);
+
+ BIND(&check_protector);
+ BranchIfSetIteratorProtectorValid(if_true, if_false);
+}
+
+void BranchIfIterableWithOriginalValueSetIterator(
+ compiler::CodeAssemblerState* state, TNode<Object> iterable,
+ TNode<Context> context, compiler::CodeAssemblerLabel* if_true,
+ compiler::CodeAssemblerLabel* if_false) {
+ CollectionsBuiltinsAssembler assembler(state);
+ assembler.BranchIfIterableWithOriginalValueSetIterator(iterable, context,
+ if_true, if_false);
+}
+
+TNode<JSArray> CollectionsBuiltinsAssembler::MapIteratorToList(
+ TNode<Context> context, TNode<JSMapIterator> iterator) {
+ // Transition the {iterator} table if necessary.
+ TNode<OrderedHashMap> table;
+ TNode<IntPtrT> index;
+ std::tie(table, index) =
+ TransitionAndUpdate<JSMapIterator, OrderedHashMap>(iterator);
+ CSA_ASSERT(this, IntPtrEqual(index, IntPtrConstant(0)));
+
+ TNode<IntPtrT> size =
+ LoadAndUntagObjectField(table, OrderedHashMap::NumberOfElementsOffset());
+
+ const ElementsKind kind = PACKED_ELEMENTS;
+ TNode<Map> array_map =
+ LoadJSArrayElementsMap(kind, LoadNativeContext(context));
+ TNode<JSArray> array =
+ AllocateJSArray(kind, array_map, size, SmiTag(size), nullptr,
+ INTPTR_PARAMETERS, kAllowLargeObjectAllocation);
+ TNode<FixedArray> elements = CAST(LoadElements(array));
+
+ const int first_element_offset = FixedArray::kHeaderSize - kHeapObjectTag;
+ TNode<IntPtrT> first_to_element_offset =
+ ElementOffsetFromIndex(IntPtrConstant(0), kind, INTPTR_PARAMETERS, 0);
+ VARIABLE(
+ var_offset, MachineType::PointerRepresentation(),
+ IntPtrAdd(first_to_element_offset, IntPtrConstant(first_element_offset)));
+ TVARIABLE(IntPtrT, var_index, index);
+ VariableList vars({&var_index, &var_offset}, zone());
+ Label done(this, {&var_index}), loop(this, vars), continue_loop(this, vars),
+ write_key(this, vars), write_value(this, vars);
+
+ Goto(&loop);
+
+ BIND(&loop);
+ {
+ // Read the next entry from the {table}, skipping holes.
+ TNode<Object> entry_key;
+ TNode<IntPtrT> entry_start_position;
+ TNode<IntPtrT> cur_index;
+ std::tie(entry_key, entry_start_position, cur_index) =
+ NextSkipHoles<OrderedHashMap>(table, var_index.value(), &done);
+
+ // Decide to write key or value.
+ Branch(
+ InstanceTypeEqual(LoadInstanceType(iterator), JS_MAP_KEY_ITERATOR_TYPE),
+ &write_key, &write_value);
+
+ BIND(&write_key);
+ {
+ Store(elements, var_offset.value(), entry_key);
+ Goto(&continue_loop);
+ }
+
+ BIND(&write_value);
+ {
+ CSA_ASSERT(this, InstanceTypeEqual(LoadInstanceType(iterator),
+ JS_MAP_VALUE_ITERATOR_TYPE));
+ TNode<Object> entry_value =
+ LoadFixedArrayElement(table, entry_start_position,
+ (OrderedHashMap::HashTableStartIndex() +
+ OrderedHashMap::kValueOffset) *
+ kTaggedSize);
+
+ Store(elements, var_offset.value(), entry_value);
+ Goto(&continue_loop);
+ }
+
+ BIND(&continue_loop);
+ {
+ // Increment the array offset and continue the loop to the next entry.
+ var_index = cur_index;
+ var_offset.Bind(
+ IntPtrAdd(var_offset.value(), IntPtrConstant(kTaggedSize)));
+ Goto(&loop);
+ }
+ }
+
+ BIND(&done);
+ // Set the {iterator} to exhausted.
+ StoreObjectFieldRoot(iterator, JSMapIterator::kTableOffset,
+ RootIndex::kEmptyOrderedHashMap);
+ StoreObjectFieldNoWriteBarrier(iterator, JSMapIterator::kIndexOffset,
+ SmiTag(var_index.value()));
+ return UncheckedCast<JSArray>(array);
+}
+
+TF_BUILTIN(MapIteratorToList, CollectionsBuiltinsAssembler) {
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<JSMapIterator> iterator = CAST(Parameter(Descriptor::kSource));
+ Return(MapIteratorToList(context, iterator));
+}
+
+TNode<JSArray> CollectionsBuiltinsAssembler::SetOrSetIteratorToList(
+ TNode<Context> context, TNode<Object> iterable) {
+ TVARIABLE(OrderedHashSet, var_table);
+ Label if_set(this), if_iterator(this), copy(this);
+
+ Node* const instance_type = LoadInstanceType(CAST(iterable));
+ Branch(InstanceTypeEqual(instance_type, JS_SET_TYPE), &if_set, &if_iterator);
+
+ BIND(&if_set);
+ {
+ // {iterable} is a JSSet.
+ var_table = CAST(LoadObjectField(CAST(iterable), JSSet::kTableOffset));
+ Goto(&copy);
+ }
+
+ BIND(&if_iterator);
+ {
+ // {iterable} is a JSSetIterator.
+ // Transition the {iterable} table if necessary.
+ TNode<OrderedHashSet> iter_table;
+ TNode<IntPtrT> iter_index;
+ std::tie(iter_table, iter_index) =
+ TransitionAndUpdate<JSSetIterator, OrderedHashSet>(CAST(iterable));
+ CSA_ASSERT(this, IntPtrEqual(iter_index, IntPtrConstant(0)));
+ var_table = iter_table;
+ Goto(&copy);
+ }
+
+ BIND(&copy);
+ TNode<OrderedHashSet> table = var_table.value();
+ TNode<IntPtrT> size =
+ LoadAndUntagObjectField(table, OrderedHashMap::NumberOfElementsOffset());
+
+ const ElementsKind kind = PACKED_ELEMENTS;
+ TNode<Map> array_map =
+ LoadJSArrayElementsMap(kind, LoadNativeContext(context));
+ TNode<JSArray> array =
+ AllocateJSArray(kind, array_map, size, SmiTag(size), nullptr,
+ INTPTR_PARAMETERS, kAllowLargeObjectAllocation);
+ TNode<FixedArray> elements = CAST(LoadElements(array));
+
+ const int first_element_offset = FixedArray::kHeaderSize - kHeapObjectTag;
+ TNode<IntPtrT> first_to_element_offset =
+ ElementOffsetFromIndex(IntPtrConstant(0), kind, INTPTR_PARAMETERS, 0);
+ VARIABLE(
+ var_offset, MachineType::PointerRepresentation(),
+ IntPtrAdd(first_to_element_offset, IntPtrConstant(first_element_offset)));
+ TVARIABLE(IntPtrT, var_index, IntPtrConstant(0));
+ Label done(this), finalize(this, {&var_index}),
+ loop(this, {&var_index, &var_offset});
+
+ Goto(&loop);
+
+ BIND(&loop);
+ {
+ // Read the next entry from the {table}, skipping holes.
+ TNode<Object> entry_key;
+ TNode<IntPtrT> entry_start_position;
+ TNode<IntPtrT> cur_index;
+ std::tie(entry_key, entry_start_position, cur_index) =
+ NextSkipHoles<OrderedHashSet>(table, var_index.value(), &finalize);
+
+ Store(elements, var_offset.value(), entry_key);
+
+ var_index = cur_index;
+ var_offset.Bind(IntPtrAdd(var_offset.value(), IntPtrConstant(kTaggedSize)));
+ Goto(&loop);
+ }
+
+ BIND(&finalize);
+ GotoIf(InstanceTypeEqual(instance_type, JS_SET_TYPE), &done);
+ // Set the {iterable} to exhausted if it's an iterator.
+ StoreObjectFieldRoot(iterable, JSSetIterator::kTableOffset,
+ RootIndex::kEmptyOrderedHashSet);
+ StoreObjectFieldNoWriteBarrier(iterable, JSSetIterator::kIndexOffset,
+ SmiTag(var_index.value()));
+ Goto(&done);
+
+ BIND(&done);
+ return UncheckedCast<JSArray>(array);
+}
+
+TF_BUILTIN(SetOrSetIteratorToList, CollectionsBuiltinsAssembler) {
+ TNode<Context> context = CAST(Parameter(Descriptor::kContext));
+ TNode<Object> object = CAST(Parameter(Descriptor::kSource));
+ Return(SetOrSetIteratorToList(context, object));
+}
+
template <typename CollectionType>
void CollectionsBuiltinsAssembler::FindOrderedHashTableEntryForSmiKey(
Node* table, Node* smi_key, Variable* result, Label* entry_found,
@@ -1008,10 +1291,14 @@ TF_BUILTIN(OrderedHashTableHealIndex, CollectionsBuiltinsAssembler) {
GotoIfNot(SmiLessThan(SmiConstant(0), index), &return_zero);
// Check if the {table} was cleared.
+ STATIC_ASSERT(OrderedHashMap::NumberOfDeletedElementsOffset() ==
+ OrderedHashSet::NumberOfDeletedElementsOffset());
Node* number_of_deleted_elements = LoadAndUntagObjectField(
- table, OrderedHashTableBase::kNumberOfDeletedElementsOffset);
+ table, OrderedHashMap::NumberOfDeletedElementsOffset());
+ STATIC_ASSERT(OrderedHashMap::kClearedTableSentinel ==
+ OrderedHashSet::kClearedTableSentinel);
GotoIf(WordEqual(number_of_deleted_elements,
- IntPtrConstant(OrderedHashTableBase::kClearedTableSentinel)),
+ IntPtrConstant(OrderedHashMap::kClearedTableSentinel)),
&return_zero);
VARIABLE(var_i, MachineType::PointerRepresentation(), IntPtrConstant(0));
@@ -1022,9 +1309,10 @@ TF_BUILTIN(OrderedHashTableHealIndex, CollectionsBuiltinsAssembler) {
{
Node* i = var_i.value();
GotoIfNot(IntPtrLessThan(i, number_of_deleted_elements), &return_index);
+ STATIC_ASSERT(OrderedHashMap::RemovedHolesIndex() ==
+ OrderedHashSet::RemovedHolesIndex());
TNode<Smi> removed_index = CAST(LoadFixedArrayElement(
- CAST(table), i,
- OrderedHashTableBase::kRemovedHolesIndex * kPointerSize));
+ CAST(table), i, OrderedHashMap::RemovedHolesIndex() * kTaggedSize));
GotoIf(SmiGreaterThanOrEqual(removed_index, index), &return_index);
Decrement(&var_index, 1, SMI_PARAMETERS);
Increment(&var_i);
@@ -1047,7 +1335,7 @@ CollectionsBuiltinsAssembler::Transition(
TVARIABLE(TableType, var_table, table);
Label if_done(this), if_transition(this, Label::kDeferred);
Branch(TaggedIsSmi(
- LoadObjectField(var_table.value(), TableType::kNextTableOffset)),
+ LoadObjectField(var_table.value(), TableType::NextTableOffset())),
&if_done, &if_transition);
BIND(&if_transition);
@@ -1060,7 +1348,7 @@ CollectionsBuiltinsAssembler::Transition(
TNode<IntPtrT> index = var_index.value();
TNode<Object> next_table =
- LoadObjectField(table, TableType::kNextTableOffset);
+ LoadObjectField(table, TableType::NextTableOffset());
GotoIf(TaggedIsSmi(next_table), &done_loop);
var_table = CAST(next_table);
@@ -1102,11 +1390,11 @@ CollectionsBuiltinsAssembler::NextSkipHoles(TNode<TableType> table,
Label* if_end) {
// Compute the used capacity for the {table}.
TNode<IntPtrT> number_of_buckets =
- LoadAndUntagObjectField(table, TableType::kNumberOfBucketsOffset);
+ LoadAndUntagObjectField(table, TableType::NumberOfBucketsOffset());
TNode<IntPtrT> number_of_elements =
- LoadAndUntagObjectField(table, TableType::kNumberOfElementsOffset);
- TNode<IntPtrT> number_of_deleted_elements =
- LoadAndUntagObjectField(table, TableType::kNumberOfDeletedElementsOffset);
+ LoadAndUntagObjectField(table, TableType::NumberOfElementsOffset());
+ TNode<IntPtrT> number_of_deleted_elements = LoadAndUntagObjectField(
+ table, TableType::NumberOfDeletedElementsOffset());
TNode<IntPtrT> used_capacity =
IntPtrAdd(number_of_elements, number_of_deleted_elements);
@@ -1123,7 +1411,7 @@ CollectionsBuiltinsAssembler::NextSkipHoles(TNode<TableType> table,
number_of_buckets);
entry_key =
LoadFixedArrayElement(table, entry_start_position,
- TableType::kHashTableStartIndex * kPointerSize);
+ TableType::HashTableStartIndex() * kTaggedSize);
Increment(&var_index);
Branch(IsTheHole(entry_key), &loop, &done_loop);
}
@@ -1151,8 +1439,8 @@ TF_BUILTIN(MapPrototypeGet, CollectionsBuiltinsAssembler) {
BIND(&if_found);
Return(LoadFixedArrayElement(
CAST(table), SmiUntag(index),
- (OrderedHashMap::kHashTableStartIndex + OrderedHashMap::kValueOffset) *
- kPointerSize));
+ (OrderedHashMap::HashTableStartIndex() + OrderedHashMap::kValueOffset) *
+ kTaggedSize));
BIND(&if_not_found);
Return(UndefinedConstant());
@@ -1222,8 +1510,8 @@ TF_BUILTIN(MapPrototypeSet, CollectionsBuiltinsAssembler) {
// If we found the entry, we just store the value there.
StoreFixedArrayElement(table, entry_start_position_or_hash.value(), value,
UPDATE_WRITE_BARRIER,
- kPointerSize * (OrderedHashMap::kHashTableStartIndex +
- OrderedHashMap::kValueOffset));
+ kTaggedSize * (OrderedHashMap::HashTableStartIndex() +
+ OrderedHashMap::kValueOffset));
Return(receiver);
Label no_hash(this), add_entry(this), store_new_entry(this);
@@ -1246,14 +1534,14 @@ TF_BUILTIN(MapPrototypeSet, CollectionsBuiltinsAssembler) {
{
// Check we have enough space for the entry.
number_of_buckets.Bind(SmiUntag(CAST(
- LoadFixedArrayElement(table, OrderedHashMap::kNumberOfBucketsIndex))));
+ LoadFixedArrayElement(table, OrderedHashMap::NumberOfBucketsIndex()))));
STATIC_ASSERT(OrderedHashMap::kLoadFactor == 2);
Node* const capacity = WordShl(number_of_buckets.value(), 1);
Node* const number_of_elements = SmiUntag(
- CAST(LoadObjectField(table, OrderedHashMap::kNumberOfElementsOffset)));
+ CAST(LoadObjectField(table, OrderedHashMap::NumberOfElementsOffset())));
Node* const number_of_deleted = SmiUntag(CAST(LoadObjectField(
- table, OrderedHashMap::kNumberOfDeletedElementsOffset)));
+ table, OrderedHashMap::NumberOfDeletedElementsOffset())));
occupancy.Bind(IntPtrAdd(number_of_elements, number_of_deleted));
GotoIf(IntPtrLessThan(occupancy.value(), capacity), &store_new_entry);
@@ -1262,11 +1550,11 @@ TF_BUILTIN(MapPrototypeSet, CollectionsBuiltinsAssembler) {
CallRuntime(Runtime::kMapGrow, context, receiver);
table_var = CAST(LoadObjectField(receiver, JSMap::kTableOffset));
number_of_buckets.Bind(SmiUntag(CAST(LoadFixedArrayElement(
- table_var.value(), OrderedHashMap::kNumberOfBucketsIndex))));
+ table_var.value(), OrderedHashMap::NumberOfBucketsIndex()))));
Node* const new_number_of_elements = SmiUntag(CAST(LoadObjectField(
- table_var.value(), OrderedHashMap::kNumberOfElementsOffset)));
+ table_var.value(), OrderedHashMap::NumberOfElementsOffset())));
Node* const new_number_of_deleted = SmiUntag(CAST(LoadObjectField(
- table_var.value(), OrderedHashMap::kNumberOfDeletedElementsOffset)));
+ table_var.value(), OrderedHashMap::NumberOfDeletedElementsOffset())));
occupancy.Bind(IntPtrAdd(new_number_of_elements, new_number_of_deleted));
Goto(&store_new_entry);
}
@@ -1284,29 +1572,30 @@ void CollectionsBuiltinsAssembler::StoreOrderedHashMapNewEntry(
Node* const bucket =
WordAnd(hash, IntPtrSub(number_of_buckets, IntPtrConstant(1)));
Node* const bucket_entry = LoadFixedArrayElement(
- table, bucket, OrderedHashMap::kHashTableStartIndex * kPointerSize);
+ table, bucket, OrderedHashMap::HashTableStartIndex() * kTaggedSize);
// Store the entry elements.
Node* const entry_start = IntPtrAdd(
IntPtrMul(occupancy, IntPtrConstant(OrderedHashMap::kEntrySize)),
number_of_buckets);
StoreFixedArrayElement(table, entry_start, key, UPDATE_WRITE_BARRIER,
- kPointerSize * OrderedHashMap::kHashTableStartIndex);
+ kTaggedSize * OrderedHashMap::HashTableStartIndex());
StoreFixedArrayElement(table, entry_start, value, UPDATE_WRITE_BARRIER,
- kPointerSize * (OrderedHashMap::kHashTableStartIndex +
- OrderedHashMap::kValueOffset));
+ kTaggedSize * (OrderedHashMap::HashTableStartIndex() +
+ OrderedHashMap::kValueOffset));
StoreFixedArrayElement(table, entry_start, bucket_entry, SKIP_WRITE_BARRIER,
- kPointerSize * (OrderedHashMap::kHashTableStartIndex +
- OrderedHashMap::kChainOffset));
+ kTaggedSize * (OrderedHashMap::HashTableStartIndex() +
+ OrderedHashMap::kChainOffset));
// Update the bucket head.
StoreFixedArrayElement(table, bucket, SmiTag(occupancy), SKIP_WRITE_BARRIER,
- OrderedHashMap::kHashTableStartIndex * kPointerSize);
+ OrderedHashMap::HashTableStartIndex() * kTaggedSize);
// Bump the elements count.
TNode<Smi> const number_of_elements =
- CAST(LoadObjectField(table, OrderedHashMap::kNumberOfElementsOffset));
- StoreObjectFieldNoWriteBarrier(table, OrderedHashMap::kNumberOfElementsOffset,
+ CAST(LoadObjectField(table, OrderedHashMap::NumberOfElementsOffset()));
+ StoreObjectFieldNoWriteBarrier(table,
+ OrderedHashMap::NumberOfElementsOffset(),
SmiAdd(number_of_elements, SmiConstant(1)));
}
@@ -1336,27 +1625,28 @@ TF_BUILTIN(MapPrototypeDelete, CollectionsBuiltinsAssembler) {
// If we found the entry, mark the entry as deleted.
StoreFixedArrayElement(table, entry_start_position_or_hash.value(),
TheHoleConstant(), UPDATE_WRITE_BARRIER,
- kPointerSize * OrderedHashMap::kHashTableStartIndex);
+ kTaggedSize * OrderedHashMap::HashTableStartIndex());
StoreFixedArrayElement(table, entry_start_position_or_hash.value(),
TheHoleConstant(), UPDATE_WRITE_BARRIER,
- kPointerSize * (OrderedHashMap::kHashTableStartIndex +
- OrderedHashMap::kValueOffset));
+ kTaggedSize * (OrderedHashMap::HashTableStartIndex() +
+ OrderedHashMap::kValueOffset));
// Decrement the number of elements, increment the number of deleted elements.
TNode<Smi> const number_of_elements = SmiSub(
- CAST(LoadObjectField(table, OrderedHashMap::kNumberOfElementsOffset)),
+ CAST(LoadObjectField(table, OrderedHashMap::NumberOfElementsOffset())),
SmiConstant(1));
- StoreObjectFieldNoWriteBarrier(table, OrderedHashMap::kNumberOfElementsOffset,
- number_of_elements);
+ StoreObjectFieldNoWriteBarrier(
+ table, OrderedHashMap::NumberOfElementsOffset(), number_of_elements);
TNode<Smi> const number_of_deleted =
SmiAdd(CAST(LoadObjectField(
- table, OrderedHashMap::kNumberOfDeletedElementsOffset)),
+ table, OrderedHashMap::NumberOfDeletedElementsOffset())),
SmiConstant(1));
StoreObjectFieldNoWriteBarrier(
- table, OrderedHashMap::kNumberOfDeletedElementsOffset, number_of_deleted);
+ table, OrderedHashMap::NumberOfDeletedElementsOffset(),
+ number_of_deleted);
- TNode<Smi> const number_of_buckets =
- CAST(LoadFixedArrayElement(table, OrderedHashMap::kNumberOfBucketsIndex));
+ TNode<Smi> const number_of_buckets = CAST(
+ LoadFixedArrayElement(table, OrderedHashMap::NumberOfBucketsIndex()));
// If there fewer elements than #buckets / 2, shrink the table.
Label shrink(this);
@@ -1414,14 +1704,14 @@ TF_BUILTIN(SetPrototypeAdd, CollectionsBuiltinsAssembler) {
{
// Check we have enough space for the entry.
number_of_buckets.Bind(SmiUntag(CAST(
- LoadFixedArrayElement(table, OrderedHashSet::kNumberOfBucketsIndex))));
+ LoadFixedArrayElement(table, OrderedHashSet::NumberOfBucketsIndex()))));
STATIC_ASSERT(OrderedHashSet::kLoadFactor == 2);
Node* const capacity = WordShl(number_of_buckets.value(), 1);
Node* const number_of_elements = SmiUntag(
- CAST(LoadObjectField(table, OrderedHashSet::kNumberOfElementsOffset)));
+ CAST(LoadObjectField(table, OrderedHashSet::NumberOfElementsOffset())));
Node* const number_of_deleted = SmiUntag(CAST(LoadObjectField(
- table, OrderedHashSet::kNumberOfDeletedElementsOffset)));
+ table, OrderedHashSet::NumberOfDeletedElementsOffset())));
occupancy.Bind(IntPtrAdd(number_of_elements, number_of_deleted));
GotoIf(IntPtrLessThan(occupancy.value(), capacity), &store_new_entry);
@@ -1430,11 +1720,11 @@ TF_BUILTIN(SetPrototypeAdd, CollectionsBuiltinsAssembler) {
CallRuntime(Runtime::kSetGrow, context, receiver);
table_var = CAST(LoadObjectField(receiver, JSMap::kTableOffset));
number_of_buckets.Bind(SmiUntag(CAST(LoadFixedArrayElement(
- table_var.value(), OrderedHashSet::kNumberOfBucketsIndex))));
+ table_var.value(), OrderedHashSet::NumberOfBucketsIndex()))));
Node* const new_number_of_elements = SmiUntag(CAST(LoadObjectField(
- table_var.value(), OrderedHashSet::kNumberOfElementsOffset)));
+ table_var.value(), OrderedHashSet::NumberOfElementsOffset())));
Node* const new_number_of_deleted = SmiUntag(CAST(LoadObjectField(
- table_var.value(), OrderedHashSet::kNumberOfDeletedElementsOffset)));
+ table_var.value(), OrderedHashSet::NumberOfDeletedElementsOffset())));
occupancy.Bind(IntPtrAdd(new_number_of_elements, new_number_of_deleted));
Goto(&store_new_entry);
}
@@ -1452,26 +1742,27 @@ void CollectionsBuiltinsAssembler::StoreOrderedHashSetNewEntry(
Node* const bucket =
WordAnd(hash, IntPtrSub(number_of_buckets, IntPtrConstant(1)));
Node* const bucket_entry = LoadFixedArrayElement(
- table, bucket, OrderedHashSet::kHashTableStartIndex * kPointerSize);
+ table, bucket, OrderedHashSet::HashTableStartIndex() * kTaggedSize);
// Store the entry elements.
Node* const entry_start = IntPtrAdd(
IntPtrMul(occupancy, IntPtrConstant(OrderedHashSet::kEntrySize)),
number_of_buckets);
StoreFixedArrayElement(table, entry_start, key, UPDATE_WRITE_BARRIER,
- kPointerSize * OrderedHashSet::kHashTableStartIndex);
+ kTaggedSize * OrderedHashSet::HashTableStartIndex());
StoreFixedArrayElement(table, entry_start, bucket_entry, SKIP_WRITE_BARRIER,
- kPointerSize * (OrderedHashSet::kHashTableStartIndex +
- OrderedHashSet::kChainOffset));
+ kTaggedSize * (OrderedHashSet::HashTableStartIndex() +
+ OrderedHashSet::kChainOffset));
// Update the bucket head.
StoreFixedArrayElement(table, bucket, SmiTag(occupancy), SKIP_WRITE_BARRIER,
- OrderedHashSet::kHashTableStartIndex * kPointerSize);
+ OrderedHashSet::HashTableStartIndex() * kTaggedSize);
// Bump the elements count.
TNode<Smi> const number_of_elements =
- CAST(LoadObjectField(table, OrderedHashSet::kNumberOfElementsOffset));
- StoreObjectFieldNoWriteBarrier(table, OrderedHashSet::kNumberOfElementsOffset,
+ CAST(LoadObjectField(table, OrderedHashSet::NumberOfElementsOffset()));
+ StoreObjectFieldNoWriteBarrier(table,
+ OrderedHashSet::NumberOfElementsOffset(),
SmiAdd(number_of_elements, SmiConstant(1)));
}
@@ -1501,23 +1792,24 @@ TF_BUILTIN(SetPrototypeDelete, CollectionsBuiltinsAssembler) {
// If we found the entry, mark the entry as deleted.
StoreFixedArrayElement(table, entry_start_position_or_hash.value(),
TheHoleConstant(), UPDATE_WRITE_BARRIER,
- kPointerSize * OrderedHashSet::kHashTableStartIndex);
+ kTaggedSize * OrderedHashSet::HashTableStartIndex());
// Decrement the number of elements, increment the number of deleted elements.
TNode<Smi> const number_of_elements = SmiSub(
- CAST(LoadObjectField(table, OrderedHashSet::kNumberOfElementsOffset)),
+ CAST(LoadObjectField(table, OrderedHashSet::NumberOfElementsOffset())),
SmiConstant(1));
- StoreObjectFieldNoWriteBarrier(table, OrderedHashSet::kNumberOfElementsOffset,
- number_of_elements);
+ StoreObjectFieldNoWriteBarrier(
+ table, OrderedHashSet::NumberOfElementsOffset(), number_of_elements);
TNode<Smi> const number_of_deleted =
SmiAdd(CAST(LoadObjectField(
- table, OrderedHashSet::kNumberOfDeletedElementsOffset)),
+ table, OrderedHashSet::NumberOfDeletedElementsOffset())),
SmiConstant(1));
StoreObjectFieldNoWriteBarrier(
- table, OrderedHashSet::kNumberOfDeletedElementsOffset, number_of_deleted);
+ table, OrderedHashSet::NumberOfDeletedElementsOffset(),
+ number_of_deleted);
- TNode<Smi> const number_of_buckets =
- CAST(LoadFixedArrayElement(table, OrderedHashSet::kNumberOfBucketsIndex));
+ TNode<Smi> const number_of_buckets = CAST(
+ LoadFixedArrayElement(table, OrderedHashSet::NumberOfBucketsIndex()));
// If there fewer elements than #buckets / 2, shrink the table.
Label shrink(this);
@@ -1546,7 +1838,7 @@ TF_BUILTIN(MapPrototypeGetSize, CollectionsBuiltinsAssembler) {
ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE,
"get Map.prototype.size");
Node* const table = LoadObjectField(receiver, JSMap::kTableOffset);
- Return(LoadObjectField(table, OrderedHashMap::kNumberOfElementsOffset));
+ Return(LoadObjectField(table, OrderedHashMap::NumberOfElementsOffset()));
}
TF_BUILTIN(MapPrototypeForEach, CollectionsBuiltinsAssembler) {
@@ -1588,8 +1880,8 @@ TF_BUILTIN(MapPrototypeForEach, CollectionsBuiltinsAssembler) {
// Load the entry value as well.
Node* entry_value = LoadFixedArrayElement(
table, entry_start_position,
- (OrderedHashMap::kHashTableStartIndex + OrderedHashMap::kValueOffset) *
- kPointerSize);
+ (OrderedHashMap::HashTableStartIndex() + OrderedHashMap::kValueOffset) *
+ kTaggedSize);
// Invoke the {callback} passing the {entry_key}, {entry_value} and the
// {receiver}.
@@ -1677,8 +1969,8 @@ TF_BUILTIN(MapIteratorPrototypeNext, CollectionsBuiltinsAssembler) {
&return_value);
var_value.Bind(LoadFixedArrayElement(
table, entry_start_position,
- (OrderedHashMap::kHashTableStartIndex + OrderedHashMap::kValueOffset) *
- kPointerSize));
+ (OrderedHashMap::HashTableStartIndex() + OrderedHashMap::kValueOffset) *
+ kTaggedSize));
Branch(InstanceTypeEqual(receiver_instance_type, JS_MAP_VALUE_ITERATOR_TYPE),
&return_value, &return_entry);
@@ -1777,7 +2069,7 @@ TF_BUILTIN(SetPrototypeGetSize, CollectionsBuiltinsAssembler) {
ThrowIfNotInstanceType(context, receiver, JS_SET_TYPE,
"get Set.prototype.size");
Node* const table = LoadObjectField(receiver, JSSet::kTableOffset);
- Return(LoadObjectField(table, OrderedHashSet::kNumberOfElementsOffset));
+ Return(LoadObjectField(table, OrderedHashSet::NumberOfElementsOffset()));
}
TF_BUILTIN(SetPrototypeForEach, CollectionsBuiltinsAssembler) {