[builtins] Port Map and Set iterators to CodeStubAssembler.

This is the next step towards faster Map and Set iteration. It
introduces the appropriate instance types for Map and Set
iterators (following the pattern for Array iterators) and migrates
the following builtins to the CodeStubAssembler:

  - Set.prototype.entries
  - Set.prototype.values
  - Map.prototype.entries
  - Map.prototype.keys
  - Map.prototype.values
  - %SetIteratorPrototype%.next
  - %MapIteratorPrototype%.next

This already provides a significant performance boost for regular
for-of iteration of Sets and Maps, by a factor of 5-10 depending
on the input. The final step will be to inline some fast-paths
into TurboFan.

Drive-by-fix: Remove obsolete %IsJSSetIterator and %IsJSMapIterator
intrinsics and runtime functions.

Bug: v8:6571, chromium:740122
Change-Id: Iad7a7dec643d8f8b5799327f89a351108ae856bf
Reviewed-on: https://chromium-review.googlesource.com/563399
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46492}
This commit is contained in:
Benedikt Meurer 2017-07-08 18:44:44 +02:00 committed by Commit Bot
parent ed8df4dd4c
commit 3f22832be7
30 changed files with 625 additions and 316 deletions

View File

@ -7378,13 +7378,20 @@ Maybe<bool> Map::Delete(Local<Context> context, Local<Value> key) {
}
namespace {
enum class MapAsArrayKind {
kEntries = i::JS_MAP_KEY_VALUE_ITERATOR_TYPE,
kKeys = i::JS_MAP_KEY_ITERATOR_TYPE,
kValues = i::JS_MAP_VALUE_ITERATOR_TYPE
};
i::Handle<i::JSArray> MapAsArray(i::Isolate* isolate, i::Object* table_obj,
int offset, int kind) {
int offset, MapAsArrayKind kind) {
i::Factory* factory = isolate->factory();
i::Handle<i::OrderedHashMap> table(i::OrderedHashMap::cast(table_obj));
if (offset >= table->NumberOfElements()) return factory->NewJSArray(0);
int length = (table->NumberOfElements() - offset) *
(kind == i::JSMapIterator::kKindEntries ? 2 : 1);
(kind == MapAsArrayKind::kEntries ? 2 : 1);
i::Handle<i::FixedArray> result = factory->NewFixedArray(length);
int result_index = 0;
{
@ -7395,12 +7402,10 @@ i::Handle<i::JSArray> MapAsArray(i::Isolate* isolate, i::Object* table_obj,
i::Object* key = table->KeyAt(i);
if (key == the_hole) continue;
if (offset-- > 0) continue;
if (kind == i::JSMapIterator::kKindEntries ||
kind == i::JSMapIterator::kKindKeys) {
if (kind == MapAsArrayKind::kEntries || kind == MapAsArrayKind::kKeys) {
result->set(result_index++, key);
}
if (kind == i::JSMapIterator::kKindEntries ||
kind == i::JSMapIterator::kKindValues) {
if (kind == MapAsArrayKind::kEntries || kind == MapAsArrayKind::kValues) {
result->set(result_index++, table->ValueAt(i));
}
}
@ -7409,6 +7414,7 @@ i::Handle<i::JSArray> MapAsArray(i::Isolate* isolate, i::Object* table_obj,
DCHECK_EQ(result_index, length);
return factory->NewJSArrayWithElements(result, i::PACKED_ELEMENTS, length);
}
} // namespace
Local<Array> Map::AsArray() const {
@ -7417,7 +7423,7 @@ Local<Array> Map::AsArray() const {
LOG_API(isolate, Map, AsArray);
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
return Utils::ToLocal(
MapAsArray(isolate, obj->table(), 0, i::JSMapIterator::kKindEntries));
MapAsArray(isolate, obj->table(), 0, MapAsArrayKind::kEntries));
}
@ -9777,12 +9783,13 @@ v8::MaybeLocal<v8::Array> debug::EntriesPreview(Isolate* v8_isolate,
if (object->IsJSMapIterator()) {
i::Handle<i::JSMapIterator> iterator =
i::Handle<i::JSMapIterator>::cast(object);
int iterator_kind = i::Smi::cast(iterator->kind())->value();
*is_key_value = iterator_kind == i::JSMapIterator::kKindEntries;
MapAsArrayKind const kind =
static_cast<MapAsArrayKind>(iterator->map()->instance_type());
*is_key_value = kind == MapAsArrayKind::kEntries;
if (!iterator->HasMore()) return v8::Array::New(v8_isolate);
return Utils::ToLocal(MapAsArray(isolate, iterator->table(),
i::Smi::cast(iterator->index())->value(),
iterator_kind));
kind));
}
if (object->IsJSSetIterator()) {
i::Handle<i::JSSetIterator> it = i::Handle<i::JSSetIterator>::cast(object);

View File

@ -3643,10 +3643,20 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
// Setup SetIterator constructor.
Handle<JSFunction> set_iterator_function =
InstallFunction(container, "SetIterator", JS_SET_ITERATOR_TYPE,
InstallFunction(container, "SetIterator", JS_SET_VALUE_ITERATOR_TYPE,
JSSetIterator::kSize, prototype, Builtins::kIllegal);
set_iterator_function->shared()->set_native(false);
set_iterator_function->shared()->set_instance_class_name(*name);
native_context->set_set_iterator_map(set_iterator_function->initial_map());
Handle<Map> set_value_iterator_map(set_iterator_function->initial_map(),
isolate);
native_context->set_set_value_iterator_map(*set_value_iterator_map);
Handle<Map> set_key_value_iterator_map =
Map::Copy(set_value_iterator_map, "JS_SET_KEY_VALUE_ITERATOR_TYPE");
set_key_value_iterator_map->set_instance_type(
JS_SET_KEY_VALUE_ITERATOR_TYPE);
native_context->set_set_key_value_iterator_map(*set_key_value_iterator_map);
}
{ // -- M a p I t e r a t o r
@ -3669,10 +3679,25 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
// Setup MapIterator constructor.
Handle<JSFunction> map_iterator_function =
InstallFunction(container, "MapIterator", JS_MAP_ITERATOR_TYPE,
InstallFunction(container, "MapIterator", JS_MAP_KEY_ITERATOR_TYPE,
JSMapIterator::kSize, prototype, Builtins::kIllegal);
map_iterator_function->shared()->set_native(false);
map_iterator_function->shared()->set_instance_class_name(*name);
native_context->set_map_iterator_map(map_iterator_function->initial_map());
Handle<Map> map_key_iterator_map(map_iterator_function->initial_map(),
isolate);
native_context->set_map_key_iterator_map(*map_key_iterator_map);
Handle<Map> map_key_value_iterator_map =
Map::Copy(map_key_iterator_map, "JS_MAP_KEY_VALUE_ITERATOR_TYPE");
map_key_value_iterator_map->set_instance_type(
JS_MAP_KEY_VALUE_ITERATOR_TYPE);
native_context->set_map_key_value_iterator_map(*map_key_value_iterator_map);
Handle<Map> map_value_iterator_map =
Map::Copy(map_key_iterator_map, "JS_MAP_VALUE_ITERATOR_TYPE");
map_value_iterator_map->set_instance_type(JS_MAP_VALUE_ITERATOR_TYPE);
native_context->set_map_value_iterator_map(*map_value_iterator_map);
}
{ // -- S c r i p t

View File

@ -24,11 +24,20 @@ class CollectionsBuiltinsAssembler : public CodeStubAssembler {
template <typename CollectionType>
Node* AllocateOrderedHashTable();
Node* AllocateJSCollection(Node* js_map_function);
template <typename IteratorType>
Node* AllocateJSCollectionIterator(Node* context, int map_index,
Node* collection);
Node* CallGetRaw(Node* const table, Node* const key);
template <typename CollectionType, int entrysize>
Node* CallHasRaw(Node* const table, Node* const key);
template <typename IteratorType, typename TableType>
std::tuple<Node*, Node*> Transition(Node* const iterator);
template <typename TableType>
std::tuple<Node*, Node*, Node*> NextSkipHoles(Node* table, Node* index,
Label* if_end);
// Builds code that finds OrderedHashMap entry for given key with hash code
// {hash} with using the comparison code generated by {key_compare}. The code
// jumps to {entry_found} if the key is found, or to {not_found} if the key
@ -127,6 +136,24 @@ Node* CollectionsBuiltinsAssembler::AllocateJSCollection(
return instance;
}
template <typename IteratorType>
Node* CollectionsBuiltinsAssembler::AllocateJSCollectionIterator(
Node* context, int map_index, Node* collection) {
Node* const table = LoadObjectField(collection, JSCollection::kTableOffset);
Node* const native_context = LoadNativeContext(context);
Node* const iterator_map = LoadContextElement(native_context, map_index);
Node* const iterator = AllocateInNewSpace(IteratorType::kSize);
StoreMapNoWriteBarrier(iterator, iterator_map);
StoreObjectFieldRoot(iterator, IteratorType::kPropertiesOffset,
Heap::kEmptyFixedArrayRootIndex);
StoreObjectFieldRoot(iterator, IteratorType::kElementsOffset,
Heap::kEmptyFixedArrayRootIndex);
StoreObjectFieldNoWriteBarrier(iterator, IteratorType::kTableOffset, table);
StoreObjectFieldNoWriteBarrier(iterator, IteratorType::kIndexOffset,
SmiConstant(0));
return iterator;
}
TF_BUILTIN(MapConstructor, CollectionsBuiltinsAssembler) {
const int kIterableArg = 0;
@ -547,6 +574,115 @@ void CollectionsBuiltinsAssembler::FindOrderedHashMapEntry(
}
}
template <typename IteratorType, typename TableType>
std::tuple<Node*, Node*> CollectionsBuiltinsAssembler::Transition(
Node* const iterator) {
VARIABLE(var_table, MachineRepresentation::kTagged,
LoadObjectField(iterator, IteratorType::kTableOffset));
VARIABLE(var_index, MachineType::PointerRepresentation(),
LoadAndUntagObjectField(iterator, IteratorType::kIndexOffset));
Label if_done(this), if_transition(this, Label::kDeferred);
Branch(TaggedIsSmi(
LoadObjectField(var_table.value(), TableType::kNextTableOffset)),
&if_done, &if_transition);
BIND(&if_transition);
{
Label loop(this, {&var_table, &var_index}), done_loop(this);
Goto(&loop);
BIND(&loop);
{
Node* next_table =
LoadObjectField(var_table.value(), TableType::kNextTableOffset);
GotoIf(TaggedIsSmi(next_table), &done_loop);
Node* table = var_table.value();
Node* index = var_index.value();
var_table.Bind(next_table);
// Check if we need to update the {index}.
GotoIfNot(IntPtrLessThan(IntPtrConstant(0), index), &loop);
// Check if the {table} was cleared.
Node* nod = LoadAndUntagObjectField(
table, TableType::kNumberOfDeletedElementsOffset);
Label if_table_cleared(this), if_table_not_cleared(this);
Branch(WordEqual(nod, IntPtrConstant(TableType::kClearedTableSentinel)),
&if_table_cleared, &if_table_not_cleared);
BIND(&if_table_cleared);
{
var_index.Bind(IntPtrConstant(0));
Goto(&loop);
}
BIND(&if_table_not_cleared);
{
VARIABLE(var_i, MachineType::PointerRepresentation(),
IntPtrConstant(0));
Label iloop(this, {&var_i, &var_index});
Goto(&iloop);
BIND(&iloop);
{
Node* i = var_i.value();
GotoIfNot(IntPtrLessThan(i, nod), &loop);
Node* removed_index = SmiUntag(
LoadFixedArrayElement(table, i, TableType::kRemovedHolesOffset));
GotoIf(IntPtrLessThanOrEqual(index, removed_index), &loop);
var_index.Bind(IntPtrSub(var_index.value(), IntPtrConstant(1)));
Goto(&iloop);
}
}
}
BIND(&done_loop);
// Update the {iterator} with the new state.
StoreObjectField(iterator, IteratorType::kTableOffset, var_table.value());
StoreObjectFieldNoWriteBarrier(iterator, IteratorType::kIndexOffset,
SmiTag(var_index.value()));
Goto(&if_done);
}
BIND(&if_done);
return std::tuple<Node*, Node*>(var_table.value(), var_index.value());
}
template <typename TableType>
std::tuple<Node*, Node*, Node*> CollectionsBuiltinsAssembler::NextSkipHoles(
Node* table, Node* index, Label* if_end) {
// Compute the used capacity for the {table}.
Node* number_of_buckets =
SmiUntag(LoadFixedArrayElement(table, TableType::kNumberOfBucketsIndex));
Node* number_of_elements =
LoadAndUntagObjectField(table, TableType::kNumberOfElementsOffset);
Node* number_of_deleted_elements =
LoadAndUntagObjectField(table, TableType::kNumberOfDeletedElementsOffset);
Node* used_capacity =
IntPtrAdd(number_of_elements, number_of_deleted_elements);
Node* entry_key;
Node* entry_start_position;
VARIABLE(var_index, MachineType::PointerRepresentation(), index);
Label loop(this, &var_index), done_loop(this);
Goto(&loop);
BIND(&loop);
{
GotoIfNot(IntPtrLessThan(var_index.value(), used_capacity), if_end);
entry_start_position = IntPtrAdd(
IntPtrMul(var_index.value(), IntPtrConstant(TableType::kEntrySize)),
number_of_buckets);
entry_key =
LoadFixedArrayElement(table, entry_start_position,
TableType::kHashTableStartIndex * kPointerSize);
Increment(var_index);
Branch(IsTheHole(entry_key), &loop, &done_loop);
}
BIND(&done_loop);
return std::tuple<Node*, Node*, Node*>(entry_key, entry_start_position,
var_index.value());
}
TF_BUILTIN(MapGet, CollectionsBuiltinsAssembler) {
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const key_tagged = Parameter(Descriptor::kKey);
@ -618,6 +754,110 @@ TF_BUILTIN(MapHas, CollectionsBuiltinsAssembler) {
Return(FalseConstant());
}
TF_BUILTIN(MapPrototypeEntries, CollectionsBuiltinsAssembler) {
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const context = Parameter(Descriptor::kContext);
ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE,
"Map.prototype.entries");
Return(AllocateJSCollectionIterator<JSMapIterator>(
context, Context::MAP_KEY_VALUE_ITERATOR_MAP_INDEX, receiver));
}
TF_BUILTIN(MapPrototypeKeys, CollectionsBuiltinsAssembler) {
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const context = Parameter(Descriptor::kContext);
ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE, "Map.prototype.keys");
Return(AllocateJSCollectionIterator<JSMapIterator>(
context, Context::MAP_KEY_ITERATOR_MAP_INDEX, receiver));
}
TF_BUILTIN(MapPrototypeValues, CollectionsBuiltinsAssembler) {
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const context = Parameter(Descriptor::kContext);
ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE,
"Map.prototype.values");
Return(AllocateJSCollectionIterator<JSMapIterator>(
context, Context::MAP_VALUE_ITERATOR_MAP_INDEX, receiver));
}
TF_BUILTIN(MapIteratorPrototypeNext, CollectionsBuiltinsAssembler) {
const char* const kMethodName = "Map Iterator.prototype.next";
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const context = Parameter(Descriptor::kContext);
// Ensure that the {receiver} is actually a JSMapIterator.
Label if_receiver_valid(this), if_receiver_invalid(this, Label::kDeferred);
GotoIf(TaggedIsSmi(receiver), &if_receiver_invalid);
Node* const receiver_instance_type = LoadInstanceType(receiver);
GotoIf(
InstanceTypeEqual(receiver_instance_type, JS_MAP_KEY_VALUE_ITERATOR_TYPE),
&if_receiver_valid);
GotoIf(InstanceTypeEqual(receiver_instance_type, JS_MAP_KEY_ITERATOR_TYPE),
&if_receiver_valid);
Branch(InstanceTypeEqual(receiver_instance_type, JS_MAP_VALUE_ITERATOR_TYPE),
&if_receiver_valid, &if_receiver_invalid);
BIND(&if_receiver_invalid);
ThrowIncompatibleMethodReceiver(context, kMethodName, receiver);
BIND(&if_receiver_valid);
// Check if the {receiver} is exhausted.
Label return_value(this), return_entry(this),
return_end(this, Label::kDeferred);
VARIABLE(var_value, MachineRepresentation::kTagged, UndefinedConstant());
VARIABLE(var_done, MachineRepresentation::kTagged, TrueConstant());
// TODO(bmeurer): Don't stick undefined in here, but some canonical
// empty_table, to avoid this check.
GotoIf(IsUndefined(LoadObjectField(receiver, JSMapIterator::kTableOffset)),
&return_value);
// Transition the {receiver} table if necessary.
Node* table;
Node* index;
std::tie(table, index) = Transition<JSMapIterator, OrderedHashMap>(receiver);
// Read the next entry from the {table}, skipping holes.
Node* entry_key;
Node* entry_start_position;
std::tie(entry_key, entry_start_position, index) =
NextSkipHoles<OrderedHashMap>(table, index, &return_end);
StoreObjectFieldNoWriteBarrier(receiver, JSMapIterator::kIndexOffset,
SmiTag(index));
var_value.Bind(entry_key);
var_done.Bind(FalseConstant());
// Check how to return the {key} (depending on {receiver} type).
GotoIf(InstanceTypeEqual(receiver_instance_type, JS_MAP_KEY_ITERATOR_TYPE),
&return_value);
var_value.Bind(LoadFixedArrayElement(
table, entry_start_position,
(OrderedHashMap::kHashTableStartIndex + OrderedHashMap::kValueOffset) *
kPointerSize));
Branch(InstanceTypeEqual(receiver_instance_type, JS_MAP_VALUE_ITERATOR_TYPE),
&return_value, &return_entry);
BIND(&return_entry);
{
Node* result =
AllocateJSIteratorResultForEntry(context, entry_key, var_value.value());
Return(result);
}
BIND(&return_value);
{
Node* result =
AllocateJSIteratorResult(context, var_value.value(), var_done.value());
Return(result);
}
BIND(&return_end);
{
StoreObjectFieldRoot(receiver, JSMapIterator::kTableOffset,
Heap::kUndefinedValueRootIndex);
var_value.Bind(UndefinedConstant());
Goto(&return_value);
}
}
TF_BUILTIN(SetHas, CollectionsBuiltinsAssembler) {
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const key = Parameter(Descriptor::kKey);
@ -629,5 +869,93 @@ TF_BUILTIN(SetHas, CollectionsBuiltinsAssembler) {
Return(CallHasRaw<OrderedHashSet, 1>(table, key));
}
TF_BUILTIN(SetPrototypeEntries, CollectionsBuiltinsAssembler) {
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const context = Parameter(Descriptor::kContext);
ThrowIfNotInstanceType(context, receiver, JS_SET_TYPE,
"Set.prototype.entries");
Return(AllocateJSCollectionIterator<JSSetIterator>(
context, Context::SET_KEY_VALUE_ITERATOR_MAP_INDEX, receiver));
}
TF_BUILTIN(SetPrototypeValues, CollectionsBuiltinsAssembler) {
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const context = Parameter(Descriptor::kContext);
ThrowIfNotInstanceType(context, receiver, JS_SET_TYPE,
"Set.prototype.values");
Return(AllocateJSCollectionIterator<JSSetIterator>(
context, Context::SET_VALUE_ITERATOR_MAP_INDEX, receiver));
}
TF_BUILTIN(SetIteratorPrototypeNext, CollectionsBuiltinsAssembler) {
const char* const kMethodName = "Set Iterator.prototype.next";
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const context = Parameter(Descriptor::kContext);
// Ensure that the {receiver} is actually a JSSetIterator.
Label if_receiver_valid(this), if_receiver_invalid(this, Label::kDeferred);
GotoIf(TaggedIsSmi(receiver), &if_receiver_invalid);
Node* const receiver_instance_type = LoadInstanceType(receiver);
GotoIf(InstanceTypeEqual(receiver_instance_type, JS_SET_VALUE_ITERATOR_TYPE),
&if_receiver_valid);
Branch(
InstanceTypeEqual(receiver_instance_type, JS_SET_KEY_VALUE_ITERATOR_TYPE),
&if_receiver_valid, &if_receiver_invalid);
BIND(&if_receiver_invalid);
ThrowIncompatibleMethodReceiver(context, kMethodName, receiver);
BIND(&if_receiver_valid);
// Check if the {receiver} is exhausted.
Label return_value(this), return_entry(this),
return_end(this, Label::kDeferred);
VARIABLE(var_value, MachineRepresentation::kTagged, UndefinedConstant());
VARIABLE(var_done, MachineRepresentation::kTagged, TrueConstant());
// TODO(bmeurer): Don't stick undefined in here, but some canonical
// empty_table, to avoid this check.
GotoIf(IsUndefined(LoadObjectField(receiver, JSSetIterator::kTableOffset)),
&return_value);
// Transition the {receiver} table if necessary.
Node* table;
Node* index;
std::tie(table, index) = Transition<JSSetIterator, OrderedHashSet>(receiver);
// Read the next entry from the {table}, skipping holes.
Node* entry_key;
Node* entry_start_position;
std::tie(entry_key, entry_start_position, index) =
NextSkipHoles<OrderedHashSet>(table, index, &return_end);
StoreObjectFieldNoWriteBarrier(receiver, JSSetIterator::kIndexOffset,
SmiTag(index));
var_value.Bind(entry_key);
var_done.Bind(FalseConstant());
// Check how to return the {key} (depending on {receiver} type).
Branch(InstanceTypeEqual(receiver_instance_type, JS_SET_VALUE_ITERATOR_TYPE),
&return_value, &return_entry);
BIND(&return_entry);
{
Node* result = AllocateJSIteratorResultForEntry(context, var_value.value(),
var_value.value());
Return(result);
}
BIND(&return_value);
{
Node* result =
AllocateJSIteratorResult(context, var_value.value(), var_done.value());
Return(result);
}
BIND(&return_end);
{
StoreObjectFieldRoot(receiver, JSSetIterator::kTableOffset,
Heap::kUndefinedValueRootIndex);
var_value.Bind(UndefinedConstant());
Goto(&return_value);
}
}
} // namespace internal
} // namespace v8

View File

@ -43,7 +43,7 @@ BUILTIN(MapForEach) {
Handle<Object> receiver = args.atOrUndefined(isolate, 2);
Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()), isolate);
Handle<JSMapIterator> iterator = isolate->factory()->NewJSMapIterator(
table, 0, JSMapIterator::kKindEntries);
isolate->map_key_value_iterator_map(), table, 0);
while (iterator->HasMore()) {
Handle<Object> key(iterator->CurrentKey(), isolate);
@ -58,58 +58,6 @@ BUILTIN(MapForEach) {
return isolate->heap()->undefined_value();
}
BUILTIN(MapPrototypeEntries) {
HandleScope scope(isolate);
const char* const kMethodName = "Map.prototype.entries";
CHECK_RECEIVER(JSMap, map, kMethodName);
return *isolate->factory()->NewJSMapIterator(
handle(OrderedHashMap::cast(map->table()), isolate), 0,
JSMapIterator::kKindEntries);
}
BUILTIN(MapPrototypeKeys) {
HandleScope scope(isolate);
const char* const kMethodName = "Map.prototype.keys";
CHECK_RECEIVER(JSMap, map, kMethodName);
return *isolate->factory()->NewJSMapIterator(
handle(OrderedHashMap::cast(map->table()), isolate), 0,
JSMapIterator::kKindKeys);
}
BUILTIN(MapPrototypeValues) {
HandleScope scope(isolate);
const char* const kMethodName = "Map.prototype.values";
CHECK_RECEIVER(JSMap, map, kMethodName);
return *isolate->factory()->NewJSMapIterator(
handle(OrderedHashMap::cast(map->table()), isolate), 0,
JSMapIterator::kKindValues);
}
BUILTIN(MapIteratorPrototypeNext) {
HandleScope scope(isolate);
const char* const kMethodName = "Map Iterator.prototype.next";
CHECK_RECEIVER(JSMapIterator, iterator, kMethodName);
Handle<Object> value = isolate->factory()->undefined_value();
bool done = true;
if (iterator->HasMore()) {
done = false;
switch (Smi::cast(iterator->kind())->value()) {
case JSMapIterator::kKindEntries:
value = MakeEntryPair(isolate, handle(iterator->CurrentKey(), isolate),
handle(iterator->CurrentValue(), isolate));
break;
case JSMapIterator::kKindKeys:
value = handle(iterator->CurrentKey(), isolate);
break;
case JSMapIterator::kKindValues:
value = handle(iterator->CurrentValue(), isolate);
break;
}
iterator->MoveNext();
}
return *isolate->factory()->NewJSIteratorResult(value, done);
}
BUILTIN(SetGetSize) {
HandleScope scope(isolate);
const char* const kMethodName = "get Set.prototype.size";
@ -144,7 +92,7 @@ BUILTIN(SetForEach) {
Handle<Object> receiver = args.atOrUndefined(isolate, 2);
Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()), isolate);
Handle<JSSetIterator> iterator = isolate->factory()->NewJSSetIterator(
table, 0, JSSetIterator::kKindValues);
isolate->set_value_iterator_map(), table, 0);
while (iterator->HasMore()) {
Handle<Object> key(iterator->CurrentKey(), isolate);
@ -158,40 +106,5 @@ BUILTIN(SetForEach) {
return isolate->heap()->undefined_value();
}
BUILTIN(SetPrototypeEntries) {
HandleScope scope(isolate);
const char* const kMethodName = "Set.prototype.entries";
CHECK_RECEIVER(JSSet, set, kMethodName);
return *isolate->factory()->NewJSSetIterator(
handle(OrderedHashSet::cast(set->table()), isolate), 0,
JSSetIterator::kKindEntries);
}
BUILTIN(SetPrototypeValues) {
HandleScope scope(isolate);
const char* const kMethodName = "Set.prototype.values";
CHECK_RECEIVER(JSSet, set, kMethodName);
return *isolate->factory()->NewJSSetIterator(
handle(OrderedHashSet::cast(set->table()), isolate), 0,
JSSetIterator::kKindValues);
}
BUILTIN(SetIteratorPrototypeNext) {
HandleScope scope(isolate);
const char* const kMethodName = "Set Iterator.prototype.next";
CHECK_RECEIVER(JSSetIterator, iterator, kMethodName);
Handle<Object> value = isolate->factory()->undefined_value();
bool done = true;
if (iterator->HasMore()) {
value = handle(iterator->CurrentKey(), isolate);
done = false;
if (Smi::cast(iterator->kind())->value() == JSSetIterator::kKindEntries) {
value = MakeEntryPair(isolate, value, value);
}
iterator->MoveNext();
}
return *isolate->factory()->NewJSIteratorResult(value, done);
}
} // namespace internal
} // namespace v8

View File

@ -584,13 +584,13 @@ namespace internal {
CPP(MapClear) \
CPP(MapForEach) \
/* ES #sec-map.prototype.entries */ \
CPP(MapPrototypeEntries) \
TFJ(MapPrototypeEntries, 0) \
/* ES #sec-map.prototype.keys */ \
CPP(MapPrototypeKeys) \
TFJ(MapPrototypeKeys, 0) \
/* ES #sec-map.prototype.values */ \
CPP(MapPrototypeValues) \
TFJ(MapPrototypeValues, 0) \
/* ES #sec-%mapiteratorprototype%.next */ \
CPP(MapIteratorPrototypeNext) \
TFJ(MapIteratorPrototypeNext, 0) \
\
/* Math */ \
/* ES6 #sec-math.abs */ \
@ -874,11 +874,11 @@ namespace internal {
CPP(SetClear) \
CPP(SetForEach) \
/* ES #sec-set.prototype.entries */ \
CPP(SetPrototypeEntries) \
TFJ(SetPrototypeEntries, 0) \
/* ES #sec-set.prototype.values */ \
CPP(SetPrototypeValues) \
TFJ(SetPrototypeValues, 0) \
/* ES #sec-%setiteratorprototype%.next */ \
CPP(SetIteratorPrototypeNext) \
TFJ(SetIteratorPrototypeNext, 0) \
\
/* SharedArrayBuffer */ \
CPP(SharedArrayBufferPrototypeGetByteLength) \

View File

@ -1822,19 +1822,8 @@ TF_BUILTIN(StringIteratorPrototypeNext, StringBuiltinsAssembler) {
BIND(&return_result);
{
Node* native_context = LoadNativeContext(context);
Node* map =
LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
Node* result = Allocate(JSIteratorResult::kSize);
StoreMapNoWriteBarrier(result, map);
StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset,
Heap::kEmptyFixedArrayRootIndex);
StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset,
Heap::kEmptyFixedArrayRootIndex);
StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kValueOffset,
var_value.value());
StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kDoneOffset,
var_done.value());
Node* result =
AllocateJSIteratorResult(context, var_value.value(), var_done.value());
Return(result);
}

View File

@ -3138,6 +3138,14 @@ Node* CodeStubAssembler::ToThisValue(Node* context, Node* value,
return var_value.value();
}
void CodeStubAssembler::ThrowIncompatibleMethodReceiver(Node* context,
const char* method_name,
Node* receiver) {
CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context,
CStringConstant(method_name), receiver);
Unreachable();
}
Node* CodeStubAssembler::ThrowIfNotInstanceType(Node* context, Node* value,
InstanceType instance_type,
char const* method_name) {
@ -3155,11 +3163,7 @@ Node* CodeStubAssembler::ThrowIfNotInstanceType(Node* context, Node* value,
// The {value} is not a compatible receiver for this method.
BIND(&throw_exception);
CallRuntime(
Runtime::kThrowIncompatibleMethodReceiver, context,
HeapConstant(factory()->NewStringFromAsciiChecked(method_name, TENURED)),
value);
Unreachable();
ThrowIncompatibleMethodReceiver(context, method_name, value);
BIND(&out);
return var_value_map.value();
@ -9152,6 +9156,58 @@ Node* CodeStubAssembler::AllocateJSArrayIterator(Node* array, Node* array_map,
return iterator;
}
Node* CodeStubAssembler::AllocateJSIteratorResult(Node* context, Node* value,
Node* done) {
CSA_ASSERT(this, IsBoolean(done));
Node* native_context = LoadNativeContext(context);
Node* map =
LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
Node* result = Allocate(JSIteratorResult::kSize);
StoreMapNoWriteBarrier(result, map);
StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset,
Heap::kEmptyFixedArrayRootIndex);
StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset,
Heap::kEmptyFixedArrayRootIndex);
StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kValueOffset, value);
StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kDoneOffset, done);
return result;
}
Node* CodeStubAssembler::AllocateJSIteratorResultForEntry(Node* context,
Node* key,
Node* value) {
Node* native_context = LoadNativeContext(context);
Node* length = SmiConstant(2);
int const elements_size = FixedArray::SizeFor(2);
Node* elements =
Allocate(elements_size + JSArray::kSize + JSIteratorResult::kSize);
StoreObjectFieldRoot(elements, FixedArray::kMapOffset,
Heap::kFixedArrayMapRootIndex);
StoreObjectFieldNoWriteBarrier(elements, FixedArray::kLengthOffset, length);
StoreFixedArrayElement(elements, 0, key);
StoreFixedArrayElement(elements, 1, value);
Node* array_map = LoadContextElement(
native_context, Context::JS_ARRAY_PACKED_ELEMENTS_MAP_INDEX);
Node* array = InnerAllocate(elements, elements_size);
StoreMapNoWriteBarrier(array, array_map);
StoreObjectFieldRoot(array, JSArray::kPropertiesOffset,
Heap::kEmptyFixedArrayRootIndex);
StoreObjectFieldNoWriteBarrier(array, JSArray::kElementsOffset, elements);
StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length);
Node* iterator_map =
LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
Node* result = InnerAllocate(array, JSArray::kSize);
StoreMapNoWriteBarrier(result, iterator_map);
StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset,
Heap::kEmptyFixedArrayRootIndex);
StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset,
Heap::kEmptyFixedArrayRootIndex);
StoreObjectFieldNoWriteBarrier(result, JSIteratorResult::kValueOffset, array);
StoreObjectFieldRoot(result, JSIteratorResult::kDoneOffset,
Heap::kFalseValueRootIndex);
return result;
}
Node* CodeStubAssembler::TypedArraySpeciesCreateByLength(Node* context,
Node* originalArray,
Node* len) {

View File

@ -648,6 +648,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* context, IterationKind mode);
Node* AllocateJSArrayIterator(Node* array, Node* array_map, Node* map);
Node* AllocateJSIteratorResult(Node* context, Node* value, Node* done);
Node* AllocateJSIteratorResultForEntry(Node* context, Node* key, Node* value);
Node* TypedArraySpeciesCreateByLength(Node* context, Node* originalArray,
Node* len);
@ -756,6 +758,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* ToThisValue(Node* context, Node* value, PrimitiveType primitive_type,
char const* method_name);
// Throws a TypeError for {method_name}. Terminates the current block.
void ThrowIncompatibleMethodReceiver(Node* context, char const* method_name,
Node* receiver);
// Throws a TypeError for {method_name} if {value} is not of the given
// instance type. Returns {value}'s map.
Node* ThrowIfNotInstanceType(Node* context, Node* value,

View File

@ -62,10 +62,6 @@ Reduction JSIntrinsicLowering::Reduce(Node* node) {
return ReduceIsInstanceType(node, JS_MAP_TYPE);
case Runtime::kInlineIsJSSet:
return ReduceIsInstanceType(node, JS_SET_TYPE);
case Runtime::kInlineIsJSMapIterator:
return ReduceIsInstanceType(node, JS_MAP_ITERATOR_TYPE);
case Runtime::kInlineIsJSSetIterator:
return ReduceIsInstanceType(node, JS_SET_ITERATOR_TYPE);
case Runtime::kInlineIsJSWeakMap:
return ReduceIsInstanceType(node, JS_WEAK_MAP_TYPE);
case Runtime::kInlineIsJSWeakSet:

View File

@ -183,8 +183,6 @@ bool Linkage::NeedsFrameStateInput(Runtime::FunctionId function) {
case Runtime::kInlineIsArray:
case Runtime::kInlineIsJSMap:
case Runtime::kInlineIsJSSet:
case Runtime::kInlineIsJSMapIterator:
case Runtime::kInlineIsJSSetIterator:
case Runtime::kInlineIsJSWeakMap:
case Runtime::kInlineIsJSWeakSet:
case Runtime::kInlineIsJSReceiver:

View File

@ -222,8 +222,11 @@ Type::bitset BitsetType::Lub(i::Map* map) {
case JS_DATA_VIEW_TYPE:
case JS_SET_TYPE:
case JS_MAP_TYPE:
case JS_SET_ITERATOR_TYPE:
case JS_MAP_ITERATOR_TYPE:
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
case JS_SET_VALUE_ITERATOR_TYPE:
case JS_MAP_KEY_ITERATOR_TYPE:
case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
case JS_MAP_VALUE_ITERATOR_TYPE:
case JS_STRING_ITERATOR_TYPE:
case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:

View File

@ -291,7 +291,9 @@ enum ContextLookupFlags {
V(JS_WEAK_MAP_FUN_INDEX, JSFunction, js_weak_map_fun) \
V(JS_WEAK_SET_FUN_INDEX, JSFunction, js_weak_set_fun) \
V(MAP_CACHE_INDEX, Object, map_cache) \
V(MAP_ITERATOR_MAP_INDEX, Map, map_iterator_map) \
V(MAP_KEY_ITERATOR_MAP_INDEX, Map, map_key_iterator_map) \
V(MAP_KEY_VALUE_ITERATOR_MAP_INDEX, Map, map_key_value_iterator_map) \
V(MAP_VALUE_ITERATOR_MAP_INDEX, Map, map_value_iterator_map) \
V(MATH_RANDOM_INDEX_INDEX, Smi, math_random_index) \
V(MATH_RANDOM_CACHE_INDEX, Object, math_random_cache) \
V(MESSAGE_LISTENERS_INDEX, TemplateList, message_listeners) \
@ -332,7 +334,8 @@ enum ContextLookupFlags {
V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \
V(SECURITY_TOKEN_INDEX, Object, security_token) \
V(SELF_WEAK_CELL_INDEX, WeakCell, self_weak_cell) \
V(SET_ITERATOR_MAP_INDEX, Map, set_iterator_map) \
V(SET_VALUE_ITERATOR_MAP_INDEX, Map, set_value_iterator_map) \
V(SET_KEY_VALUE_ITERATOR_MAP_INDEX, Map, set_key_value_iterator_map) \
V(SHARED_ARRAY_BUFFER_FUN_INDEX, JSFunction, shared_array_buffer_fun) \
V(SLOPPY_ARGUMENTS_MAP_INDEX, Map, sloppy_arguments_map) \
V(SLOW_ALIASED_ARGUMENTS_MAP_INDEX, Map, slow_aliased_arguments_map) \

View File

@ -277,8 +277,6 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
V(IsJSProxy) \
V(IsJSMap) \
V(IsJSSet) \
V(IsJSMapIterator) \
V(IsJSSetIterator) \
V(IsJSWeakMap) \
V(IsJSWeakSet) \
V(IsRegExp) \

View File

@ -3682,6 +3682,35 @@ Handle<Object> TranslatedState::MaterializeCapturedObjectAt(
}
return object;
}
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
case JS_SET_VALUE_ITERATOR_TYPE: {
Handle<JSSetIterator> object = Handle<JSSetIterator>::cast(
isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
Handle<Object> properties = materializer.FieldAt(value_index);
Handle<Object> elements = materializer.FieldAt(value_index);
Handle<Object> table = materializer.FieldAt(value_index);
Handle<Object> index = materializer.FieldAt(value_index);
object->set_properties(FixedArray::cast(*properties));
object->set_elements(FixedArrayBase::cast(*elements));
object->set_table(*table);
object->set_index(*index);
return object;
}
case JS_MAP_KEY_ITERATOR_TYPE:
case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
case JS_MAP_VALUE_ITERATOR_TYPE: {
Handle<JSMapIterator> object = Handle<JSMapIterator>::cast(
isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
Handle<Object> properties = materializer.FieldAt(value_index);
Handle<Object> elements = materializer.FieldAt(value_index);
Handle<Object> table = materializer.FieldAt(value_index);
Handle<Object> index = materializer.FieldAt(value_index);
object->set_properties(FixedArray::cast(*properties));
object->set_elements(FixedArrayBase::cast(*elements));
object->set_table(*table);
object->set_index(*index);
return object;
}
case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE:
@ -3934,8 +3963,6 @@ Handle<Object> TranslatedState::MaterializeCapturedObjectAt(
case JS_DATA_VIEW_TYPE:
case JS_SET_TYPE:
case JS_MAP_TYPE:
case JS_SET_ITERATOR_TYPE:
case JS_MAP_ITERATOR_TYPE:
case JS_WEAK_MAP_TYPE:
case JS_WEAK_SET_TYPE:
case JS_PROMISE_CAPABILITY_TYPE:

View File

@ -2087,27 +2087,23 @@ Handle<JSSet> Factory::NewJSSet() {
return js_set;
}
Handle<JSMapIterator> Factory::NewJSMapIterator(Handle<OrderedHashMap> table,
int index,
JSMapIterator::Kind kind) {
Handle<Map> map(isolate()->native_context()->map_iterator_map(), isolate());
Handle<JSMapIterator> Factory::NewJSMapIterator(Handle<Map> map,
Handle<OrderedHashMap> table,
int index) {
Handle<JSMapIterator> result =
Handle<JSMapIterator>::cast(NewJSObjectFromMap(map));
result->set_table(*table);
result->set_index(Smi::FromInt(index));
result->set_kind(Smi::FromInt(kind));
return result;
}
Handle<JSSetIterator> Factory::NewJSSetIterator(Handle<OrderedHashSet> table,
int index,
JSSetIterator::Kind kind) {
Handle<Map> map(isolate()->native_context()->set_iterator_map(), isolate());
Handle<JSSetIterator> Factory::NewJSSetIterator(Handle<Map> map,
Handle<OrderedHashSet> table,
int index) {
Handle<JSSetIterator> result =
Handle<JSSetIterator>::cast(NewJSObjectFromMap(map));
result->set_table(*table);
result->set_index(Smi::FromInt(index));
result->set_kind(Smi::FromInt(kind));
return result;
}

View File

@ -572,10 +572,12 @@ class V8_EXPORT_PRIVATE Factory final {
Handle<JSMap> NewJSMap();
Handle<JSSet> NewJSSet();
Handle<JSMapIterator> NewJSMapIterator(Handle<OrderedHashMap> table,
int index, JSMapIterator::Kind kind);
Handle<JSSetIterator> NewJSSetIterator(Handle<OrderedHashSet> table,
int index, JSSetIterator::Kind kind);
Handle<JSMapIterator> NewJSMapIterator(Handle<Map> map,
Handle<OrderedHashMap> table,
int index);
Handle<JSSetIterator> NewJSSetIterator(Handle<Map> map,
Handle<OrderedHashSet> table,
int index);
// Allocates a bound function.
MaybeHandle<JSBoundFunction> NewJSBoundFunction(

View File

@ -202,21 +202,11 @@ Node* IntrinsicsGenerator::IsJSMap(Node* input, Node* arg_count,
return IsInstanceType(input, JS_MAP_TYPE);
}
Node* IntrinsicsGenerator::IsJSMapIterator(Node* input, Node* arg_count,
Node* context) {
return IsInstanceType(input, JS_MAP_ITERATOR_TYPE);
}
Node* IntrinsicsGenerator::IsJSSet(Node* input, Node* arg_count,
Node* context) {
return IsInstanceType(input, JS_SET_TYPE);
}
Node* IntrinsicsGenerator::IsJSSetIterator(Node* input, Node* arg_count,
Node* context) {
return IsInstanceType(input, JS_SET_ITERATOR_TYPE);
}
Node* IntrinsicsGenerator::IsJSWeakMap(Node* input, Node* arg_count,
Node* context) {
return IsInstanceType(input, JS_WEAK_MAP_TYPE);

View File

@ -30,11 +30,9 @@ namespace interpreter {
V(HasProperty, has_property, 2) \
V(IsArray, is_array, 1) \
V(IsJSMap, is_js_map, 1) \
V(IsJSMapIterator, is_js_map_iterator, 1) \
V(IsJSProxy, is_js_proxy, 1) \
V(IsJSReceiver, is_js_receiver, 1) \
V(IsJSSet, is_js_set, 1) \
V(IsJSSetIterator, is_js_set_iterator, 1) \
V(IsJSWeakMap, is_js_weak_map, 1) \
V(IsJSWeakSet, is_js_weak_set, 1) \
V(IsSmi, is_smi, 1) \

View File

@ -53,7 +53,7 @@ macro IS_FUNCTION(arg) = (%IsFunction(arg));
macro IS_GENERATOR(arg) = (%_ClassOf(arg) === 'Generator');
macro IS_GLOBAL(arg) = (%_ClassOf(arg) === 'global');
macro IS_MAP(arg) = (%_IsJSMap(arg));
macro IS_MAP_ITERATOR(arg) = (%_IsJSMapIterator(arg));
macro IS_MAP_ITERATOR(arg) = (%_ClassOf(arg) === 'Map Iterator');
macro IS_NULL(arg) = (arg === null);
macro IS_NULL_OR_UNDEFINED(arg) = (arg == null);
macro IS_NUMBER(arg) = (typeof(arg) === 'number');
@ -61,7 +61,7 @@ macro IS_OBJECT(arg) = (typeof(arg) === 'object');
macro IS_PROXY(arg) = (%_IsJSProxy(arg));
macro IS_SCRIPT(arg) = (%_ClassOf(arg) === 'Script');
macro IS_SET(arg) = (%_IsJSSet(arg));
macro IS_SET_ITERATOR(arg) = (%_IsJSSetIterator(arg));
macro IS_SET_ITERATOR(arg) = (%_ClassOf(arg) === 'Set Iterator');
macro IS_SHAREDARRAYBUFFER(arg) = (%_ClassOf(arg) === 'SharedArrayBuffer');
macro IS_STRING(arg) = (typeof(arg) === 'string');
macro IS_SYMBOL(arg) = (typeof(arg) === 'symbol');

View File

@ -611,8 +611,11 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) {
case JS_DATA_VIEW_TYPE:
case JS_SET_TYPE:
case JS_MAP_TYPE:
case JS_SET_ITERATOR_TYPE:
case JS_MAP_ITERATOR_TYPE:
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
case JS_SET_VALUE_ITERATOR_TYPE:
case JS_MAP_KEY_ITERATOR_TYPE:
case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
case JS_MAP_VALUE_ITERATOR_TYPE:
case JS_STRING_ITERATOR_TYPE:
case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:

View File

@ -164,10 +164,13 @@ void HeapObject::HeapObjectVerify() {
case JS_MAP_TYPE:
JSMap::cast(this)->JSMapVerify();
break;
case JS_SET_ITERATOR_TYPE:
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
case JS_SET_VALUE_ITERATOR_TYPE:
JSSetIterator::cast(this)->JSSetIteratorVerify();
break;
case JS_MAP_ITERATOR_TYPE:
case JS_MAP_KEY_ITERATOR_TYPE:
case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
case JS_MAP_VALUE_ITERATOR_TYPE:
JSMapIterator::cast(this)->JSMapIteratorVerify();
break;
@ -953,8 +956,7 @@ void JSSetIterator::JSSetIteratorVerify() {
VerifyHeapPointer(table());
Isolate* isolate = GetIsolate();
CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(isolate));
CHECK(index()->IsSmi() || index()->IsUndefined(isolate));
CHECK(kind()->IsSmi() || kind()->IsUndefined(isolate));
CHECK(index()->IsSmi());
}
@ -964,8 +966,7 @@ void JSMapIterator::JSMapIteratorVerify() {
VerifyHeapPointer(table());
Isolate* isolate = GetIsolate();
CHECK(table()->IsOrderedHashTable() || table()->IsUndefined(isolate));
CHECK(index()->IsSmi() || index()->IsUndefined(isolate));
CHECK(kind()->IsSmi() || kind()->IsUndefined(isolate));
CHECK(index()->IsSmi());
}

View File

@ -92,14 +92,12 @@ TYPE_CHECKER(JSError, JS_ERROR_TYPE)
TYPE_CHECKER(JSFunction, JS_FUNCTION_TYPE)
TYPE_CHECKER(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE)
TYPE_CHECKER(JSMap, JS_MAP_TYPE)
TYPE_CHECKER(JSMapIterator, JS_MAP_ITERATOR_TYPE)
TYPE_CHECKER(JSMessageObject, JS_MESSAGE_OBJECT_TYPE)
TYPE_CHECKER(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE)
TYPE_CHECKER(JSPromiseCapability, JS_PROMISE_CAPABILITY_TYPE)
TYPE_CHECKER(JSPromise, JS_PROMISE_TYPE)
TYPE_CHECKER(JSRegExp, JS_REGEXP_TYPE)
TYPE_CHECKER(JSSet, JS_SET_TYPE)
TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
TYPE_CHECKER(JSAsyncFromSyncIterator, JS_ASYNC_FROM_SYNC_ITERATOR_TYPE)
TYPE_CHECKER(JSStringIterator, JS_STRING_ITERATOR_TYPE)
TYPE_CHECKER(JSTypedArray, JS_TYPED_ARRAY_TYPE)
@ -289,6 +287,18 @@ bool HeapObject::IsJSObject() const {
bool HeapObject::IsJSProxy() const { return map()->IsJSProxyMap(); }
bool HeapObject::IsJSMapIterator() const {
InstanceType instance_type = map()->instance_type();
return (instance_type >= JS_MAP_KEY_ITERATOR_TYPE &&
instance_type <= JS_MAP_VALUE_ITERATOR_TYPE);
}
bool HeapObject::IsJSSetIterator() const {
InstanceType instance_type = map()->instance_type();
return (instance_type == JS_SET_VALUE_ITERATOR_TYPE ||
instance_type == JS_SET_KEY_VALUE_ITERATOR_TYPE);
}
bool HeapObject::IsJSArrayIterator() const {
InstanceType instance_type = map()->instance_type();
return (instance_type >= FIRST_ARRAY_ITERATOR_TYPE &&
@ -4829,7 +4839,6 @@ ACCESSORS(JSCollection, table, Object, kTableOffset)
ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(table, Object, kTableOffset)
ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(index, Object, kIndexOffset)
ORDERED_HASH_TABLE_ITERATOR_ACCESSORS(kind, Object, kKindOffset)
#undef ORDERED_HASH_TABLE_ITERATOR_ACCESSORS

View File

@ -201,10 +201,13 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case JS_MAP_TYPE:
JSMap::cast(this)->JSMapPrint(os);
break;
case JS_SET_ITERATOR_TYPE:
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
case JS_SET_VALUE_ITERATOR_TYPE:
JSSetIterator::cast(this)->JSSetIteratorPrint(os);
break;
case JS_MAP_ITERATOR_TYPE:
case JS_MAP_KEY_ITERATOR_TYPE:
case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
case JS_MAP_VALUE_ITERATOR_TYPE:
JSMapIterator::cast(this)->JSMapIteratorPrint(os);
break;
case JS_WEAK_MAP_TYPE:
@ -936,7 +939,6 @@ OrderedHashTableIterator<Derived, TableType>::OrderedHashTableIteratorPrint(
std::ostream& os) { // NOLINT
os << "\n - table = " << Brief(table());
os << "\n - index = " << Brief(index());
os << "\n - kind = " << Brief(kind());
os << "\n";
}

View File

@ -1324,9 +1324,12 @@ int JSObject::GetHeaderSize(InstanceType type) {
return JSSet::kSize;
case JS_MAP_TYPE:
return JSMap::kSize;
case JS_SET_ITERATOR_TYPE:
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
case JS_SET_VALUE_ITERATOR_TYPE:
return JSSetIterator::kSize;
case JS_MAP_ITERATOR_TYPE:
case JS_MAP_KEY_ITERATOR_TYPE:
case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
case JS_MAP_VALUE_ITERATOR_TYPE:
return JSMapIterator::kSize;
case JS_WEAK_MAP_TYPE:
return JSWeakMap::kSize;
@ -3045,8 +3048,11 @@ VisitorId Map::GetVisitorId(Map* map) {
case JS_DATA_VIEW_TYPE:
case JS_SET_TYPE:
case JS_MAP_TYPE:
case JS_SET_ITERATOR_TYPE:
case JS_MAP_ITERATOR_TYPE:
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
case JS_SET_VALUE_ITERATOR_TYPE:
case JS_MAP_KEY_ITERATOR_TYPE:
case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
case JS_MAP_VALUE_ITERATOR_TYPE:
case JS_STRING_ITERATOR_TYPE:
case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
@ -12673,7 +12679,6 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_FUNCTION_TYPE:
case JS_GENERATOR_OBJECT_TYPE:
case JS_ASYNC_GENERATOR_OBJECT_TYPE:
case JS_MAP_ITERATOR_TYPE:
case JS_MAP_TYPE:
case JS_MESSAGE_OBJECT_TYPE:
case JS_OBJECT_TYPE:
@ -12681,7 +12686,6 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_ARGUMENTS_TYPE:
case JS_PROMISE_TYPE:
case JS_REGEXP_TYPE:
case JS_SET_ITERATOR_TYPE:
case JS_SET_TYPE:
case JS_SPECIAL_API_OBJECT_TYPE:
case JS_TYPED_ARRAY_TYPE:

View File

@ -400,8 +400,11 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(JS_DATA_VIEW_TYPE) \
V(JS_SET_TYPE) \
V(JS_MAP_TYPE) \
V(JS_SET_ITERATOR_TYPE) \
V(JS_MAP_ITERATOR_TYPE) \
V(JS_SET_KEY_VALUE_ITERATOR_TYPE) \
V(JS_SET_VALUE_ITERATOR_TYPE) \
V(JS_MAP_KEY_ITERATOR_TYPE) \
V(JS_MAP_KEY_VALUE_ITERATOR_TYPE) \
V(JS_MAP_VALUE_ITERATOR_TYPE) \
V(JS_WEAK_MAP_TYPE) \
V(JS_WEAK_SET_TYPE) \
V(JS_PROMISE_CAPABILITY_TYPE) \
@ -757,8 +760,11 @@ enum InstanceType {
JS_DATA_VIEW_TYPE,
JS_SET_TYPE,
JS_MAP_TYPE,
JS_SET_ITERATOR_TYPE,
JS_MAP_ITERATOR_TYPE,
JS_SET_KEY_VALUE_ITERATOR_TYPE,
JS_SET_VALUE_ITERATOR_TYPE,
JS_MAP_KEY_ITERATOR_TYPE,
JS_MAP_KEY_VALUE_ITERATOR_TYPE,
JS_MAP_VALUE_ITERATOR_TYPE,
JS_WEAK_MAP_TYPE,
JS_WEAK_SET_TYPE,
JS_PROMISE_CAPABILITY_TYPE,

View File

@ -487,6 +487,7 @@ class OrderedHashTable : public FixedArray {
static const int kNumberOfDeletedElementsIndex = kNumberOfElementsIndex + 1;
static const int kNumberOfBucketsIndex = kNumberOfDeletedElementsIndex + 1;
static const int kHashTableStartIndex = kNumberOfBucketsIndex + 1;
static const int kRemovedHolesIndex = kHashTableStartIndex;
static constexpr const int kNumberOfElementsOffset =
FixedArray::OffsetOfElementAt(kNumberOfElementsIndex);
@ -498,6 +499,8 @@ class OrderedHashTable : public FixedArray {
FixedArray::OffsetOfElementAt(kNumberOfBucketsIndex);
static constexpr const int kHashTableStartOffset =
FixedArray::OffsetOfElementAt(kHashTableStartIndex);
static constexpr const int kRemovedHolesOffset =
FixedArray::OffsetOfElementAt(kRemovedHolesIndex);
static const int kEntrySize = entrysize + 1;
static const int kChainOffset = entrysize;
@ -536,8 +539,6 @@ class OrderedHashTable : public FixedArray {
void SetRemovedIndexAt(int index, int removed_index) {
return set(kRemovedHolesIndex + index, Smi::FromInt(removed_index));
}
static const int kRemovedHolesIndex = kHashTableStartIndex;
};
class OrderedHashSet : public OrderedHashTable<OrderedHashSet, 1> {
@ -856,19 +857,13 @@ class OrderedHashTableIterator : public JSObject {
// [index]: The index into the data table.
DECL_ACCESSORS(index, Object)
// [kind]: The kind of iteration this is. One of the [Kind] enum values.
DECL_ACCESSORS(kind, Object)
#ifdef OBJECT_PRINT
void OrderedHashTableIteratorPrint(std::ostream& os); // NOLINT
#endif
static const int kTableOffset = JSObject::kHeaderSize;
static const int kIndexOffset = kTableOffset + kPointerSize;
static const int kKindOffset = kIndexOffset + kPointerSize;
static const int kSize = kKindOffset + kPointerSize;
enum Kind { kKindKeys = 1, kKindValues = 2, kKindEntries = 3 };
static const int kSize = kIndexOffset + kPointerSize;
// Whether the iterator has more elements. This needs to be called before
// calling |CurrentKey| and/or |CurrentValue|.

View File

@ -80,24 +80,9 @@ RUNTIME_FUNCTION(Runtime_SetIteratorClone) {
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
return *isolate->factory()->NewJSSetIterator(
handle(holder->map(), isolate),
handle(OrderedHashSet::cast(holder->table()), isolate),
Smi::cast(holder->index())->value(),
static_cast<JSSetIterator::Kind>(Smi::cast(holder->kind())->value()));
}
// The array returned contains the following information:
// 0: HasMore flag
// 1: Iteration index
// 2: Iteration kind
RUNTIME_FUNCTION(Runtime_SetIteratorDetails) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSSetIterator, holder, 0);
Handle<FixedArray> details = isolate->factory()->NewFixedArray(4);
details->set(0, isolate->heap()->ToBoolean(holder->HasMore()));
details->set(1, holder->index());
details->set(2, holder->kind());
return *isolate->factory()->NewJSArrayWithElements(details);
Smi::cast(holder->index())->value());
}
@ -135,28 +120,11 @@ RUNTIME_FUNCTION(Runtime_MapIteratorClone) {
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
return *isolate->factory()->NewJSMapIterator(
handle(holder->map(), isolate),
handle(OrderedHashMap::cast(holder->table()), isolate),
Smi::cast(holder->index())->value(),
static_cast<JSMapIterator::Kind>(Smi::cast(holder->kind())->value()));
Smi::cast(holder->index())->value());
}
// The array returned contains the following information:
// 0: HasMore flag
// 1: Iteration index
// 2: Iteration kind
RUNTIME_FUNCTION(Runtime_MapIteratorDetails) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSMapIterator, holder, 0);
Handle<FixedArray> details = isolate->factory()->NewFixedArray(4);
details->set(0, isolate->heap()->ToBoolean(holder->HasMore()));
details->set(1, holder->index());
details->set(2, holder->kind());
return *isolate->factory()->NewJSArrayWithElements(details);
}
RUNTIME_FUNCTION(Runtime_GetWeakMapEntries) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
@ -260,20 +228,6 @@ RUNTIME_FUNCTION(Runtime_IsJSSet) {
return isolate->heap()->ToBoolean(obj->IsJSSet());
}
RUNTIME_FUNCTION(Runtime_IsJSMapIterator) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_CHECKED(Object, obj, 0);
return isolate->heap()->ToBoolean(obj->IsJSMapIterator());
}
RUNTIME_FUNCTION(Runtime_IsJSSetIterator) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_CHECKED(Object, obj, 0);
return isolate->heap()->ToBoolean(obj->IsJSSetIterator());
}
RUNTIME_FUNCTION(Runtime_IsJSWeakMap) {
SealHandleScope shs(isolate);
DCHECK_EQ(1, args.length());

View File

@ -147,18 +147,19 @@ static MaybeHandle<JSArray> GetIteratorInternalProperties(
Isolate* isolate, Handle<IteratorType> object) {
Factory* factory = isolate->factory();
Handle<IteratorType> iterator = Handle<IteratorType>::cast(object);
CHECK(iterator->kind()->IsSmi());
const char* kind = NULL;
switch (Smi::cast(iterator->kind())->value()) {
case IteratorType::kKindKeys:
switch (iterator->map()->instance_type()) {
case JS_MAP_KEY_ITERATOR_TYPE:
kind = "keys";
break;
case IteratorType::kKindValues:
kind = "values";
break;
case IteratorType::kKindEntries:
case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
kind = "entries";
break;
case JS_MAP_VALUE_ITERATOR_TYPE:
case JS_SET_VALUE_ITERATOR_TYPE:
kind = "values";
break;
default:
UNREACHABLE();
}

View File

@ -98,12 +98,10 @@ namespace internal {
F(SetGrow, 1, 1) \
F(SetShrink, 1, 1) \
F(SetIteratorClone, 1, 1) \
F(SetIteratorDetails, 1, 1) \
F(MapInitialize, 1, 1) \
F(MapShrink, 1, 1) \
F(MapGrow, 1, 1) \
F(MapIteratorClone, 1, 1) \
F(MapIteratorDetails, 1, 1) \
F(GetWeakMapEntries, 2, 1) \
F(WeakCollectionInitialize, 1, 1) \
F(WeakCollectionGet, 3, 1) \
@ -113,8 +111,6 @@ namespace internal {
F(GetWeakSetValues, 2, 1) \
F(IsJSMap, 1, 1) \
F(IsJSSet, 1, 1) \
F(IsJSMapIterator, 1, 1) \
F(IsJSSetIterator, 1, 1) \
F(IsJSWeakMap, 1, 1) \
F(IsJSWeakSet, 1, 1)

View File

@ -103,57 +103,60 @@ INSTANCE_TYPES = {
199: "JS_DATA_VIEW_TYPE",
200: "JS_SET_TYPE",
201: "JS_MAP_TYPE",
202: "JS_SET_ITERATOR_TYPE",
203: "JS_MAP_ITERATOR_TYPE",
204: "JS_WEAK_MAP_TYPE",
205: "JS_WEAK_SET_TYPE",
206: "JS_PROMISE_CAPABILITY_TYPE",
207: "JS_PROMISE_TYPE",
208: "JS_REGEXP_TYPE",
209: "JS_ERROR_TYPE",
210: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE",
211: "JS_STRING_ITERATOR_TYPE",
212: "JS_TYPED_ARRAY_KEY_ITERATOR_TYPE",
213: "JS_FAST_ARRAY_KEY_ITERATOR_TYPE",
214: "JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE",
215: "JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE",
216: "JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE",
217: "JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE",
218: "JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE",
219: "JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE",
220: "JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE",
221: "JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE",
222: "JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE",
223: "JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE",
224: "JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE",
225: "JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE",
226: "JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE",
227: "JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE",
228: "JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE",
229: "JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE",
230: "JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE",
231: "JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE",
232: "JS_INT8_ARRAY_VALUE_ITERATOR_TYPE",
233: "JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE",
234: "JS_INT16_ARRAY_VALUE_ITERATOR_TYPE",
235: "JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE",
236: "JS_INT32_ARRAY_VALUE_ITERATOR_TYPE",
237: "JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE",
238: "JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE",
239: "JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE",
240: "JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE",
241: "JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE",
242: "JS_FAST_ARRAY_VALUE_ITERATOR_TYPE",
243: "JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE",
244: "JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE",
245: "JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE",
246: "JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE",
247: "WASM_INSTANCE_TYPE",
248: "WASM_MEMORY_TYPE",
249: "WASM_MODULE_TYPE",
250: "WASM_TABLE_TYPE",
251: "JS_BOUND_FUNCTION_TYPE",
252: "JS_FUNCTION_TYPE",
202: "JS_SET_KEY_VALUE_ITERATOR_TYPE",
203: "JS_SET_VALUE_ITERATOR_TYPE",
204: "JS_MAP_KEY_ITERATOR_TYPE",
205: "JS_MAP_KEY_VALUE_ITERATOR_TYPE",
206: "JS_MAP_VALUE_ITERATOR_TYPE",
207: "JS_WEAK_MAP_TYPE",
208: "JS_WEAK_SET_TYPE",
209: "JS_PROMISE_CAPABILITY_TYPE",
210: "JS_PROMISE_TYPE",
211: "JS_REGEXP_TYPE",
212: "JS_ERROR_TYPE",
213: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE",
214: "JS_STRING_ITERATOR_TYPE",
215: "JS_TYPED_ARRAY_KEY_ITERATOR_TYPE",
216: "JS_FAST_ARRAY_KEY_ITERATOR_TYPE",
217: "JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE",
218: "JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE",
219: "JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE",
220: "JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE",
221: "JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE",
222: "JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE",
223: "JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE",
224: "JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE",
225: "JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE",
226: "JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE",
227: "JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE",
228: "JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE",
229: "JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE",
230: "JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE",
231: "JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE",
232: "JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE",
233: "JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE",
234: "JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE",
235: "JS_INT8_ARRAY_VALUE_ITERATOR_TYPE",
236: "JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE",
237: "JS_INT16_ARRAY_VALUE_ITERATOR_TYPE",
238: "JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE",
239: "JS_INT32_ARRAY_VALUE_ITERATOR_TYPE",
240: "JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE",
241: "JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE",
242: "JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE",
243: "JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE",
244: "JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE",
245: "JS_FAST_ARRAY_VALUE_ITERATOR_TYPE",
246: "JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE",
247: "JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE",
248: "JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE",
249: "JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE",
250: "WASM_INSTANCE_TYPE",
251: "WASM_MEMORY_TYPE",
252: "WASM_MODULE_TYPE",
253: "WASM_TABLE_TYPE",
254: "JS_BOUND_FUNCTION_TYPE",
255: "JS_FUNCTION_TYPE",
}
# List of known V8 maps.
@ -245,7 +248,7 @@ KNOWN_MAPS = {
0x03ee1: (190, "ExternalMap"),
0x03f39: (106, "NativeSourceStringMap"),
0x03f91: (152, "InterceptorInfoMap"),
0x03fe9: (206, "JSPromiseCapabilityMap"),
0x03fe9: (209, "JSPromiseCapabilityMap"),
0x04041: (149, "AccessorInfoMap"),
0x04099: (150, "AccessorPairMap"),
0x040f1: (151, "AccessCheckInfoMap"),