[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:
parent
ed8df4dd4c
commit
3f22832be7
27
src/api.cc
27
src/api.cc
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) \
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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) \
|
||||
|
@ -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) \
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -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');
|
||||
|
@ -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:
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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";
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -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|.
|
||||
|
@ -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());
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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"),
|
||||
|
Loading…
Reference in New Issue
Block a user