[builtins] implement Array.prototype[@@iterator] in TFJ builtins

Implements the variations of CreateArrayIterator() in TFJ builtins
(ArrayPrototypeValues, ArrayPrototypeEntries and ArrayPrototypeKeys), and
provides two new Object types with numerous maps which identify certain
behaviours, which will be useful for inlining.

Removes src/js/array-iterator.js entirely

Also adds support for printing Symbol literals inserted by the Parser during
desugaring when FLAG_print_builtin_ast is set to true.

BUG=v8:5388
R=bmeurer@chromium.org, cbruni@chromium.org
TBR=ulan@chromium.org

Review-Url: https://codereview.chromium.org/2405253006
Cr-Commit-Position: refs/heads/master@{#40373}
This commit is contained in:
caitp 2016-10-17 19:42:42 -07:00 committed by Commit bot
parent f2a5c65b1f
commit 86d0dd362f
22 changed files with 1537 additions and 185 deletions

View File

@ -418,7 +418,6 @@ action("js2c") {
"src/js/collection-iterator.js",
"src/js/promise.js",
"src/js/messages.js",
"src/js/array-iterator.js",
"src/js/templates.js",
"src/js/spread.js",
"src/js/proxy.js",

View File

@ -220,6 +220,43 @@ AstType::bitset AstBitsetType::Lub(i::Map* map) {
case JS_SET_ITERATOR_TYPE:
case JS_MAP_ITERATOR_TYPE:
case JS_STRING_ITERATOR_TYPE:
case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE:
case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE:
case JS_WEAK_MAP_TYPE:
case JS_WEAK_SET_TYPE:
case JS_PROMISE_TYPE:

View File

@ -529,6 +529,18 @@ void AstPrinter::PrintLiteral(Handle<Object> value, bool quote) {
}
} else if (object->IsFixedArray()) {
Print("FixedArray");
} else if (object->IsSymbol()) {
// Symbols can only occur as literals if they were inserted by the parser.
Symbol* symbol = Symbol::cast(object);
if (symbol->name()->IsString()) {
int length = 0;
String* string = String::cast(symbol->name());
std::unique_ptr<char[]> desc = string->ToCString(
ALLOW_NULLS, FAST_STRING_TRAVERSAL, 0, string->length(), &length);
Print("Symbol(%*s)", length, desc.get());
} else {
Print("Symbol()");
}
} else {
Print("<unknown literal %p>", static_cast<void*>(object));
}

View File

@ -1310,6 +1310,91 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
native_context()->set_is_arraylike(*is_arraylike);
}
{ // --- A r r a y I t e r a t o r ---
Handle<JSObject> iterator_prototype(
native_context()->initial_iterator_prototype());
Handle<JSObject> array_iterator_prototype =
factory->NewJSObject(isolate->object_function(), TENURED);
JSObject::ForceSetPrototype(array_iterator_prototype, iterator_prototype);
JSObject::AddProperty(
array_iterator_prototype, factory->to_string_tag_symbol(),
factory->ArrayIterator_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
Handle<JSFunction> next = InstallFunction(
array_iterator_prototype, "next", JS_OBJECT_TYPE, JSObject::kHeaderSize,
MaybeHandle<JSObject>(), Builtins::kArrayIteratorPrototypeNext);
// Set the expected parameters for %ArrayIteratorPrototype%.next to 0 (not
// including the receiver), as required by the builtin.
next->shared()->set_internal_formal_parameter_count(0);
// Set the length for the function to satisfy ECMA-262.
next->shared()->set_length(0);
Handle<JSFunction> array_iterator_function = CreateFunction(
isolate, factory->ArrayIterator_string(),
JS_FAST_ARRAY_VALUE_ITERATOR_TYPE, JSArrayIterator::kSize,
array_iterator_prototype, Builtins::kIllegal);
array_iterator_function->shared()->set_instance_class_name(
isolate->heap()->ArrayIterator_string());
Handle<Map> initial_map(array_iterator_function->initial_map(), isolate);
#define ARRAY_ITERATOR_LIST(V) \
V(TYPED_ARRAY, KEY, typed_array, key) \
V(FAST_ARRAY, KEY, fast_array, key) \
V(GENERIC_ARRAY, KEY, array, key) \
V(UINT8_ARRAY, KEY_VALUE, uint8_array, key_value) \
V(INT8_ARRAY, KEY_VALUE, int8_array, key_value) \
V(UINT16_ARRAY, KEY_VALUE, uint16_array, key_value) \
V(INT16_ARRAY, KEY_VALUE, int16_array, key_value) \
V(UINT32_ARRAY, KEY_VALUE, uint32_array, key_value) \
V(INT32_ARRAY, KEY_VALUE, int32_array, key_value) \
V(FLOAT32_ARRAY, KEY_VALUE, float32_array, key_value) \
V(FLOAT64_ARRAY, KEY_VALUE, float64_array, key_value) \
V(UINT8_CLAMPED_ARRAY, KEY_VALUE, uint8_clamped_array, key_value) \
V(FAST_SMI_ARRAY, KEY_VALUE, fast_smi_array, key_value) \
V(FAST_HOLEY_SMI_ARRAY, KEY_VALUE, fast_holey_smi_array, key_value) \
V(FAST_ARRAY, KEY_VALUE, fast_array, key_value) \
V(FAST_HOLEY_ARRAY, KEY_VALUE, fast_holey_array, key_value) \
V(FAST_DOUBLE_ARRAY, KEY_VALUE, fast_double_array, key_value) \
V(FAST_HOLEY_DOUBLE_ARRAY, KEY_VALUE, fast_holey_double_array, key_value) \
V(GENERIC_ARRAY, KEY_VALUE, array, key_value) \
V(UINT8_ARRAY, VALUE, uint8_array, value) \
V(INT8_ARRAY, VALUE, int8_array, value) \
V(UINT16_ARRAY, VALUE, uint16_array, value) \
V(INT16_ARRAY, VALUE, int16_array, value) \
V(UINT32_ARRAY, VALUE, uint32_array, value) \
V(INT32_ARRAY, VALUE, int32_array, value) \
V(FLOAT32_ARRAY, VALUE, float32_array, value) \
V(FLOAT64_ARRAY, VALUE, float64_array, value) \
V(UINT8_CLAMPED_ARRAY, VALUE, uint8_clamped_array, value) \
V(FAST_SMI_ARRAY, VALUE, fast_smi_array, value) \
V(FAST_HOLEY_SMI_ARRAY, VALUE, fast_holey_smi_array, value) \
V(FAST_ARRAY, VALUE, fast_array, value) \
V(FAST_HOLEY_ARRAY, VALUE, fast_holey_array, value) \
V(FAST_DOUBLE_ARRAY, VALUE, fast_double_array, value) \
V(FAST_HOLEY_DOUBLE_ARRAY, VALUE, fast_holey_double_array, value) \
V(GENERIC_ARRAY, VALUE, array, value)
#define CREATE_ARRAY_ITERATOR_MAP(PREFIX, SUFFIX, prefix, suffix) \
do { \
const InstanceType type = JS_##PREFIX##_##SUFFIX##_ITERATOR_TYPE; \
Handle<Map> map = \
Map::Copy(initial_map, "JS_" #PREFIX "_" #SUFFIX "_ITERATOR_TYPE"); \
map->set_instance_type(type); \
native_context()->set_##prefix##_##suffix##_iterator_map(*map); \
} while (0);
ARRAY_ITERATOR_LIST(CREATE_ARRAY_ITERATOR_MAP)
#undef CREATE_ARRAY_ITERATOR_MAP
#undef ARRAY_ITERATOR_LIST
}
{ // --- N u m b e r ---
Handle<JSFunction> number_fun = InstallFunction(
global, "Number", JS_VALUE_TYPE, JSValue::kSize,
@ -2092,6 +2177,17 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallGetter(prototype, factory->length_string(),
Builtins::kTypedArrayPrototypeLength, true,
kTypedArrayLength);
// Install "keys", "values" and "entries" methods on the {prototype}.
SimpleInstallFunction(prototype, factory->entries_string(),
Builtins::kTypedArrayPrototypeEntries, 0, true);
SimpleInstallFunction(prototype, factory->keys_string(),
Builtins::kTypedArrayPrototypeKeys, 0, true);
Handle<JSFunction> iterator =
SimpleInstallFunction(prototype, factory->values_string(),
Builtins::kTypedArrayPrototypeValues, 0, true);
JSObject::AddProperty(prototype, factory->iterator_symbol(), iterator,
DONT_ENUM);
}
{ // -- T y p e d A r r a y s

View File

@ -6,6 +6,7 @@
#include "src/builtins/builtins-utils.h"
#include "src/code-factory.h"
#include "src/contexts.h"
#include "src/elements.h"
namespace v8 {
@ -2067,5 +2068,523 @@ void Builtins::Generate_ArrayIndexOf(CodeStubAssembler* assembler) {
array, search_element, start_from));
}
namespace {
template <IterationKind kIterationKind>
void Generate_ArrayPrototypeIterationMethod(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable;
Node* receiver = assembler->Parameter(0);
Node* context = assembler->Parameter(3);
Variable var_array(assembler, MachineRepresentation::kTagged);
Variable var_map(assembler, MachineRepresentation::kTagged);
Variable var_type(assembler, MachineRepresentation::kWord32);
Label if_isnotobject(assembler, Label::kDeferred);
Label create_array_iterator(assembler);
assembler->GotoIf(assembler->TaggedIsSmi(receiver), &if_isnotobject);
var_array.Bind(receiver);
var_map.Bind(assembler->LoadMap(receiver));
var_type.Bind(assembler->LoadMapInstanceType(var_map.value()));
assembler->Branch(assembler->IsJSReceiverInstanceType(var_type.value()),
&create_array_iterator, &if_isnotobject);
assembler->Bind(&if_isnotobject);
{
Callable callable = CodeFactory::ToObject(assembler->isolate());
Node* result = assembler->CallStub(callable, context, receiver);
var_array.Bind(result);
var_map.Bind(assembler->LoadMap(result));
var_type.Bind(assembler->LoadMapInstanceType(var_map.value()));
assembler->Goto(&create_array_iterator);
}
assembler->Bind(&create_array_iterator);
assembler->Return(assembler->CreateArrayIterator(
var_array.value(), var_map.value(), var_type.value(), context,
kIterationKind));
}
} // namespace
void Builtins::Generate_ArrayPrototypeValues(CodeStubAssembler* assembler) {
Generate_ArrayPrototypeIterationMethod<IterationKind::kValues>(assembler);
}
void Builtins::Generate_ArrayPrototypeEntries(CodeStubAssembler* assembler) {
Generate_ArrayPrototypeIterationMethod<IterationKind::kEntries>(assembler);
}
void Builtins::Generate_ArrayPrototypeKeys(CodeStubAssembler* assembler) {
Generate_ArrayPrototypeIterationMethod<IterationKind::kKeys>(assembler);
}
void Builtins::Generate_ArrayIteratorPrototypeNext(
CodeStubAssembler* assembler) {
typedef compiler::Node Node;
typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable;
Node* iterator = assembler->Parameter(0);
Node* context = assembler->Parameter(3);
Variable var_value(assembler, MachineRepresentation::kTagged);
Variable var_done(assembler, MachineRepresentation::kTagged);
// Required, or else `throw_bad_receiver` fails a DCHECK due to these
// variables not being bound along all paths, despite not being used.
var_done.Bind(assembler->TrueConstant());
var_value.Bind(assembler->UndefinedConstant());
Label throw_bad_receiver(assembler, Label::kDeferred);
Label set_done(assembler);
Label allocate_key_result(assembler);
Label allocate_entry_if_needed(assembler);
Label allocate_iterator_result(assembler);
Label generic_values(assembler);
// If O does not have all of the internal slots of an Array Iterator Instance
// (22.1.5.3), throw a TypeError exception
assembler->GotoIf(assembler->TaggedIsSmi(iterator), &throw_bad_receiver);
Node* instance_type = assembler->LoadInstanceType(iterator);
assembler->GotoIf(
assembler->Uint32LessThan(
assembler->Int32Constant(LAST_ARRAY_ITERATOR_TYPE -
FIRST_ARRAY_ITERATOR_TYPE),
assembler->Int32Sub(instance_type, assembler->Int32Constant(
FIRST_ARRAY_ITERATOR_TYPE))),
&throw_bad_receiver);
// Let a be O.[[IteratedObject]].
Node* array = assembler->LoadObjectField(
iterator, JSArrayIterator::kIteratedObjectOffset);
// Let index be O.[[ArrayIteratorNextIndex]].
Node* index =
assembler->LoadObjectField(iterator, JSArrayIterator::kNextIndexOffset);
Node* orig_map = assembler->LoadObjectField(
iterator, JSArrayIterator::kIteratedObjectMapOffset);
Node* array_map = assembler->LoadMap(array);
Label if_isfastarray(assembler), if_isnotfastarray(assembler);
assembler->Branch(assembler->WordEqual(orig_map, array_map), &if_isfastarray,
&if_isnotfastarray);
assembler->Bind(&if_isfastarray);
{
assembler->Assert(
assembler->Word32Equal(assembler->LoadMapInstanceType(array_map),
assembler->Int32Constant(JS_ARRAY_TYPE)));
Node* length = assembler->LoadObjectField(array, JSArray::kLengthOffset);
assembler->Assert(assembler->TaggedIsSmi(length));
assembler->Assert(assembler->TaggedIsSmi(index));
assembler->GotoUnless(assembler->SmiBelow(index, length), &set_done);
Node* one = assembler->SmiConstant(Smi::FromInt(1));
assembler->StoreObjectFieldNoWriteBarrier(
iterator, JSArrayIterator::kNextIndexOffset,
assembler->IntPtrAdd(assembler->BitcastTaggedToWord(index),
assembler->BitcastTaggedToWord(one)));
var_done.Bind(assembler->FalseConstant());
Node* elements = assembler->LoadElements(array);
static int32_t kInstanceType[] = {
JS_FAST_ARRAY_KEY_ITERATOR_TYPE,
JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE,
JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE,
JS_FAST_ARRAY_VALUE_ITERATOR_TYPE,
JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE,
JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE,
JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE,
};
Label packed_object_values(assembler), holey_object_values(assembler),
packed_double_values(assembler), holey_double_values(assembler);
Label* kInstanceTypeHandlers[] = {
&allocate_key_result, &packed_object_values, &holey_object_values,
&packed_object_values, &holey_object_values, &packed_double_values,
&holey_double_values, &packed_object_values, &holey_object_values,
&packed_object_values, &holey_object_values, &packed_double_values,
&holey_double_values};
assembler->Switch(instance_type, &throw_bad_receiver, kInstanceType,
kInstanceTypeHandlers, arraysize(kInstanceType));
assembler->Bind(&packed_object_values);
{
var_value.Bind(assembler->LoadFixedArrayElement(
elements, index, 0, CodeStubAssembler::SMI_PARAMETERS));
assembler->Goto(&allocate_entry_if_needed);
}
assembler->Bind(&packed_double_values);
{
Node* value = assembler->LoadFixedDoubleArrayElement(
elements, index, MachineType::Float64(), 0,
CodeStubAssembler::SMI_PARAMETERS);
var_value.Bind(assembler->AllocateHeapNumberWithValue(value));
assembler->Goto(&allocate_entry_if_needed);
}
assembler->Bind(&holey_object_values);
{
// Check the array_protector cell, and take the slow path if it's invalid.
Node* invalid =
assembler->SmiConstant(Smi::FromInt(Isolate::kArrayProtectorInvalid));
Node* cell = assembler->LoadRoot(Heap::kArrayProtectorRootIndex);
Node* cell_value =
assembler->LoadObjectField(cell, PropertyCell::kValueOffset);
assembler->GotoIf(assembler->WordEqual(cell_value, invalid),
&generic_values);
var_value.Bind(assembler->UndefinedConstant());
Node* value = assembler->LoadFixedArrayElement(
elements, index, 0, CodeStubAssembler::SMI_PARAMETERS);
assembler->GotoIf(
assembler->WordEqual(value, assembler->TheHoleConstant()),
&allocate_entry_if_needed);
var_value.Bind(value);
assembler->Goto(&allocate_entry_if_needed);
}
assembler->Bind(&holey_double_values);
{
// Check the array_protector cell, and take the slow path if it's invalid.
Node* invalid =
assembler->SmiConstant(Smi::FromInt(Isolate::kArrayProtectorInvalid));
Node* cell = assembler->LoadRoot(Heap::kArrayProtectorRootIndex);
Node* cell_value =
assembler->LoadObjectField(cell, PropertyCell::kValueOffset);
assembler->GotoIf(assembler->WordEqual(cell_value, invalid),
&generic_values);
var_value.Bind(assembler->UndefinedConstant());
Node* value = assembler->LoadFixedDoubleArrayElement(
elements, index, MachineType::Float64(), 0,
CodeStubAssembler::SMI_PARAMETERS, &allocate_entry_if_needed);
var_value.Bind(assembler->AllocateHeapNumberWithValue(value));
assembler->Goto(&allocate_entry_if_needed);
}
}
assembler->Bind(&if_isnotfastarray);
{
Label if_istypedarray(assembler), if_isgeneric(assembler);
// If a is undefined, return CreateIterResultObject(undefined, true)
assembler->GotoIf(
assembler->WordEqual(array, assembler->UndefinedConstant()),
&allocate_iterator_result);
Node* array_type = assembler->LoadInstanceType(array);
assembler->Branch(
assembler->Word32Equal(array_type,
assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
&if_istypedarray, &if_isgeneric);
assembler->Bind(&if_isgeneric);
{
Node* length = nullptr;
{
Variable var_length(assembler, MachineRepresentation::kTagged);
Label if_isarray(assembler), if_isnotarray(assembler), done(assembler);
assembler->Branch(
assembler->Word32Equal(array_type,
assembler->Int32Constant(JS_ARRAY_TYPE)),
&if_isarray, &if_isnotarray);
assembler->Bind(&if_isarray);
{
var_length.Bind(
assembler->LoadObjectField(array, JSArray::kLengthOffset));
assembler->Goto(&done);
}
assembler->Bind(&if_isnotarray);
{
Node* length_string = assembler->HeapConstant(
assembler->isolate()->factory()->length_string());
Callable get_property =
CodeFactory::GetProperty(assembler->isolate());
Node* length =
assembler->CallStub(get_property, context, array, length_string);
Callable to_length = CodeFactory::ToLength(assembler->isolate());
var_length.Bind(assembler->CallStub(to_length, context, length));
assembler->Goto(&done);
}
assembler->Bind(&done);
length = var_length.value();
}
assembler->GotoUnlessNumberLessThan(index, length, &set_done);
assembler->StoreObjectField(iterator, JSArrayIterator::kNextIndexOffset,
assembler->NumberInc(index));
var_done.Bind(assembler->FalseConstant());
assembler->Branch(
assembler->Uint32LessThanOrEqual(
instance_type,
assembler->Int32Constant(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE)),
&allocate_key_result, &generic_values);
assembler->Bind(&generic_values);
{
Callable get_property = CodeFactory::GetProperty(assembler->isolate());
var_value.Bind(
assembler->CallStub(get_property, context, array, index));
assembler->Goto(&allocate_entry_if_needed);
}
}
assembler->Bind(&if_istypedarray);
{
Node* length = nullptr;
{
Variable var_length(assembler, MachineRepresentation::kTagged);
Label if_isdetached(assembler, Label::kDeferred),
if_isnotdetached(assembler), done(assembler);
Node* buffer =
assembler->LoadObjectField(array, JSTypedArray::kBufferOffset);
assembler->Branch(assembler->IsDetachedBuffer(buffer), &if_isdetached,
&if_isnotdetached);
assembler->Bind(&if_isnotdetached);
{
var_length.Bind(
assembler->LoadObjectField(array, JSTypedArray::kLengthOffset));
assembler->Goto(&done);
}
assembler->Bind(&if_isdetached);
{
var_length.Bind(assembler->SmiConstant(Smi::kZero));
assembler->Goto(&done);
}
assembler->Bind(&done);
length = var_length.value();
}
assembler->Assert(assembler->TaggedIsSmi(length));
assembler->Assert(assembler->TaggedIsSmi(index));
assembler->GotoUnless(assembler->SmiBelow(index, length), &set_done);
Node* one = assembler->SmiConstant(Smi::FromInt(1));
assembler->StoreObjectFieldNoWriteBarrier(
iterator, JSArrayIterator::kNextIndexOffset,
assembler->IntPtrAdd(assembler->BitcastTaggedToWord(index),
assembler->BitcastTaggedToWord(one)));
var_done.Bind(assembler->FalseConstant());
Node* elements = assembler->LoadElements(array);
Node* base_ptr = assembler->LoadObjectField(
elements, FixedTypedArrayBase::kBasePointerOffset);
Node* external_ptr = assembler->LoadObjectField(
elements, FixedTypedArrayBase::kExternalPointerOffset);
Node* data_ptr = assembler->IntPtrAdd(base_ptr, external_ptr);
static int32_t kInstanceType[] = {
JS_TYPED_ARRAY_KEY_ITERATOR_TYPE,
JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE,
JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE,
JS_INT8_ARRAY_VALUE_ITERATOR_TYPE,
JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE,
JS_INT16_ARRAY_VALUE_ITERATOR_TYPE,
JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE,
JS_INT32_ARRAY_VALUE_ITERATOR_TYPE,
JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE,
JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE,
};
Label uint8_values(assembler), int8_values(assembler),
uint16_values(assembler), int16_values(assembler),
uint32_values(assembler), int32_values(assembler),
float32_values(assembler), float64_values(assembler);
Label* kInstanceTypeHandlers[] = {
&allocate_key_result, &uint8_values, &uint8_values,
&int8_values, &uint16_values, &int16_values,
&uint32_values, &int32_values, &float32_values,
&float64_values, &uint8_values, &uint8_values,
&int8_values, &uint16_values, &int16_values,
&uint32_values, &int32_values, &float32_values,
&float64_values,
};
var_done.Bind(assembler->FalseConstant());
assembler->Switch(instance_type, &throw_bad_receiver, kInstanceType,
kInstanceTypeHandlers, arraysize(kInstanceType));
assembler->Bind(&uint8_values);
{
Node* value_uint8 = assembler->LoadFixedTypedArrayElement(
data_ptr, index, UINT8_ELEMENTS, CodeStubAssembler::SMI_PARAMETERS);
var_value.Bind(assembler->SmiFromWord(value_uint8));
assembler->Goto(&allocate_entry_if_needed);
}
assembler->Bind(&int8_values);
{
Node* value_int8 = assembler->LoadFixedTypedArrayElement(
data_ptr, index, INT8_ELEMENTS, CodeStubAssembler::SMI_PARAMETERS);
var_value.Bind(assembler->SmiFromWord(value_int8));
assembler->Goto(&allocate_entry_if_needed);
}
assembler->Bind(&uint16_values);
{
Node* value_uint16 = assembler->LoadFixedTypedArrayElement(
data_ptr, index, UINT16_ELEMENTS,
CodeStubAssembler::SMI_PARAMETERS);
var_value.Bind(assembler->SmiFromWord(value_uint16));
assembler->Goto(&allocate_entry_if_needed);
}
assembler->Bind(&int16_values);
{
Node* value_int16 = assembler->LoadFixedTypedArrayElement(
data_ptr, index, INT16_ELEMENTS, CodeStubAssembler::SMI_PARAMETERS);
var_value.Bind(assembler->SmiFromWord(value_int16));
assembler->Goto(&allocate_entry_if_needed);
}
assembler->Bind(&uint32_values);
{
Node* value_uint32 = assembler->LoadFixedTypedArrayElement(
data_ptr, index, UINT32_ELEMENTS,
CodeStubAssembler::SMI_PARAMETERS);
var_value.Bind(assembler->ChangeUint32ToTagged(value_uint32));
assembler->Goto(&allocate_entry_if_needed);
}
assembler->Bind(&int32_values);
{
Node* value_int32 = assembler->LoadFixedTypedArrayElement(
data_ptr, index, INT32_ELEMENTS, CodeStubAssembler::SMI_PARAMETERS);
var_value.Bind(assembler->ChangeInt32ToTagged(value_int32));
assembler->Goto(&allocate_entry_if_needed);
}
assembler->Bind(&float32_values);
{
Node* value_float32 = assembler->LoadFixedTypedArrayElement(
data_ptr, index, FLOAT32_ELEMENTS,
CodeStubAssembler::SMI_PARAMETERS);
var_value.Bind(assembler->AllocateHeapNumberWithValue(
assembler->ChangeFloat32ToFloat64(value_float32)));
assembler->Goto(&allocate_entry_if_needed);
}
assembler->Bind(&float64_values);
{
Node* value_float64 = assembler->LoadFixedTypedArrayElement(
data_ptr, index, FLOAT64_ELEMENTS,
CodeStubAssembler::SMI_PARAMETERS);
var_value.Bind(assembler->AllocateHeapNumberWithValue(value_float64));
assembler->Goto(&allocate_entry_if_needed);
}
}
}
assembler->Bind(&set_done);
{
assembler->StoreObjectFieldNoWriteBarrier(
iterator, JSArrayIterator::kIteratedObjectOffset,
assembler->UndefinedConstant());
assembler->Goto(&allocate_iterator_result);
}
assembler->Bind(&allocate_key_result);
{
var_value.Bind(index);
var_done.Bind(assembler->FalseConstant());
assembler->Goto(&allocate_iterator_result);
}
assembler->Bind(&allocate_entry_if_needed);
{
assembler->GotoIf(
assembler->Int32GreaterThan(
instance_type,
assembler->Int32Constant(LAST_ARRAY_KEY_VALUE_ITERATOR_TYPE)),
&allocate_iterator_result);
Node* elements = assembler->AllocateFixedArray(FAST_ELEMENTS,
assembler->Int32Constant(2));
assembler->StoreFixedArrayElement(elements, assembler->Int32Constant(0),
index, SKIP_WRITE_BARRIER);
assembler->StoreFixedArrayElement(elements, assembler->Int32Constant(1),
var_value.value(), SKIP_WRITE_BARRIER);
Node* entry = assembler->Allocate(JSArray::kSize);
Node* map = assembler->LoadContextElement(
assembler->LoadNativeContext(context),
Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX);
assembler->StoreMapNoWriteBarrier(entry, map);
assembler->StoreObjectFieldRoot(entry, JSArray::kPropertiesOffset,
Heap::kEmptyFixedArrayRootIndex);
assembler->StoreObjectFieldNoWriteBarrier(entry, JSArray::kElementsOffset,
elements);
assembler->StoreObjectFieldNoWriteBarrier(
entry, JSArray::kLengthOffset, assembler->SmiConstant(Smi::FromInt(2)));
var_value.Bind(entry);
assembler->Goto(&allocate_iterator_result);
}
assembler->Bind(&allocate_iterator_result);
{
Node* result = assembler->Allocate(JSIteratorResult::kSize);
Node* map =
assembler->LoadContextElement(assembler->LoadNativeContext(context),
Context::ITERATOR_RESULT_MAP_INDEX);
assembler->StoreMapNoWriteBarrier(result, map);
assembler->StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset,
Heap::kEmptyFixedArrayRootIndex);
assembler->StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset,
Heap::kEmptyFixedArrayRootIndex);
assembler->StoreObjectFieldNoWriteBarrier(
result, JSIteratorResult::kValueOffset, var_value.value());
assembler->StoreObjectFieldNoWriteBarrier(
result, JSIteratorResult::kDoneOffset, var_done.value());
assembler->Return(result);
}
assembler->Bind(&throw_bad_receiver);
{
// The {receiver} is not a valid JSArrayIterator.
Node* result = assembler->CallRuntime(
Runtime::kThrowIncompatibleMethodReceiver, context,
assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
"Array Iterator.prototype.next", TENURED)),
iterator);
assembler->Return(result);
}
}
} // namespace internal
} // namespace v8

View File

@ -42,16 +42,9 @@ void Generate_TypedArrayProtoypeGetter(CodeStubAssembler* assembler,
// Check if the {receiver}'s JSArrayBuffer was neutered.
Node* receiver_buffer =
assembler->LoadObjectField(receiver, JSTypedArray::kBufferOffset);
Node* receiver_buffer_bit_field = assembler->LoadObjectField(
receiver_buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32());
Label if_receiverisneutered(assembler, Label::kDeferred);
assembler->GotoUnless(
assembler->Word32Equal(
assembler->Word32And(
receiver_buffer_bit_field,
assembler->Int32Constant(JSArrayBuffer::WasNeutered::kMask)),
assembler->Int32Constant(0)),
&if_receiverisneutered);
assembler->GotoIf(assembler->IsDetachedBuffer(receiver_buffer),
&if_receiverisneutered);
assembler->Return(assembler->LoadObjectField(receiver, object_offset));
assembler->Bind(&if_receiverisneutered);
@ -98,5 +91,79 @@ void Builtins::Generate_TypedArrayPrototypeLength(
JSTypedArray::kLengthOffset);
}
namespace {
template <IterationKind kIterationKind>
void Generate_TypedArrayPrototypeIterationMethod(CodeStubAssembler* assembler,
const char* method_name) {
typedef compiler::Node Node;
typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable;
Node* receiver = assembler->Parameter(0);
Node* context = assembler->Parameter(3);
Label throw_bad_receiver(assembler, Label::kDeferred);
Label throw_typeerror(assembler, Label::kDeferred);
assembler->GotoIf(assembler->TaggedIsSmi(receiver), &throw_bad_receiver);
Node* map = assembler->LoadMap(receiver);
Node* instance_type = assembler->LoadMapInstanceType(map);
assembler->GotoIf(
assembler->Word32NotEqual(instance_type,
assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
&throw_bad_receiver);
// Check if the {receiver}'s JSArrayBuffer was neutered.
Node* receiver_buffer =
assembler->LoadObjectField(receiver, JSTypedArray::kBufferOffset);
Label if_receiverisneutered(assembler, Label::kDeferred);
assembler->GotoIf(assembler->IsDetachedBuffer(receiver_buffer),
&if_receiverisneutered);
assembler->Return(assembler->CreateArrayIterator(receiver, map, instance_type,
context, kIterationKind));
Variable var_message(assembler, MachineRepresentation::kTagged);
assembler->Bind(&throw_bad_receiver);
var_message.Bind(
assembler->SmiConstant(Smi::FromInt(MessageTemplate::kNotTypedArray)));
assembler->Goto(&throw_typeerror);
assembler->Bind(&if_receiverisneutered);
var_message.Bind(assembler->SmiConstant(
Smi::FromInt(MessageTemplate::kDetachedOperation)));
assembler->Goto(&throw_typeerror);
assembler->Bind(&throw_typeerror);
{
Node* arg1 = assembler->HeapConstant(
assembler->isolate()->factory()->NewStringFromAsciiChecked(method_name,
TENURED));
Node* result = assembler->CallRuntime(Runtime::kThrowTypeError, context,
var_message.value(), arg1);
assembler->Return(result);
}
}
} // namespace
void Builtins::Generate_TypedArrayPrototypeValues(
CodeStubAssembler* assembler) {
Generate_TypedArrayPrototypeIterationMethod<IterationKind::kValues>(
assembler, "%TypedArray%.prototype.values()");
}
void Builtins::Generate_TypedArrayPrototypeEntries(
CodeStubAssembler* assembler) {
Generate_TypedArrayPrototypeIterationMethod<IterationKind::kEntries>(
assembler, "%TypedArray%.prototype.entries()");
}
void Builtins::Generate_TypedArrayPrototypeKeys(CodeStubAssembler* assembler) {
Generate_TypedArrayPrototypeIterationMethod<IterationKind::kKeys>(
assembler, "%TypedArray%.prototype.keys()");
}
} // namespace internal
} // namespace v8

View File

@ -223,6 +223,14 @@ namespace internal {
CPP(ArraySlice) \
CPP(ArraySplice) \
CPP(ArrayUnshift) \
/* ES6 #sec-array.prototype.entries */ \
TFJ(ArrayPrototypeEntries, 1) \
/* ES6 #sec-array.prototype.keys */ \
TFJ(ArrayPrototypeKeys, 1) \
/* ES6 #sec-array.prototype.values */ \
TFJ(ArrayPrototypeValues, 1) \
/* ES6 #sec-%arrayiteratorprototype%.next */ \
TFJ(ArrayIteratorPrototypeNext, 1) \
\
/* ArrayBuffer */ \
CPP(ArrayBufferConstructor) \
@ -670,6 +678,12 @@ namespace internal {
TFJ(TypedArrayPrototypeByteOffset, 1) \
/* ES6 section 22.2.3.18 get %TypedArray%.prototype.length */ \
TFJ(TypedArrayPrototypeLength, 1) \
/* ES6 #sec-%typedarray%.prototype.entries */ \
TFJ(TypedArrayPrototypeEntries, 1) \
/* ES6 #sec-%typedarray%.prototype.keys */ \
TFJ(TypedArrayPrototypeKeys, 1) \
/* ES6 #sec-%typedarray%.prototype.values */ \
TFJ(TypedArrayPrototypeValues, 1) \
\
CPP(ModuleNamespaceIterator) \
CPP(FixedArrayIteratorNext)

View File

@ -1052,6 +1052,44 @@ Node* CodeStubAssembler::LoadFixedArrayElement(Node* object, Node* index_node,
return Load(MachineType::AnyTagged(), object, offset);
}
Node* CodeStubAssembler::LoadFixedTypedArrayElement(
Node* data_pointer, Node* index_node, ElementsKind elements_kind,
ParameterMode parameter_mode) {
Node* offset =
ElementOffsetFromIndex(index_node, elements_kind, parameter_mode, 0);
MachineType type;
switch (elements_kind) {
case UINT8_ELEMENTS: /* fall through */
case UINT8_CLAMPED_ELEMENTS:
type = MachineType::Uint8();
break;
case INT8_ELEMENTS:
type = MachineType::Int8();
break;
case UINT16_ELEMENTS:
type = MachineType::Uint16();
break;
case INT16_ELEMENTS:
type = MachineType::Int16();
break;
case UINT32_ELEMENTS:
type = MachineType::Uint32();
break;
case INT32_ELEMENTS:
type = MachineType::Int32();
break;
case FLOAT32_ELEMENTS:
type = MachineType::Float32();
break;
case FLOAT64_ELEMENTS:
type = MachineType::Float64();
break;
default:
UNREACHABLE();
}
return Load(type, data_pointer, offset);
}
Node* CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement(
Node* object, Node* index_node, int additional_offset,
ParameterMode parameter_mode) {
@ -6146,6 +6184,120 @@ void CodeStubAssembler::BuildFastFixedArrayForEach(
: IndexAdvanceMode::kPost);
}
void CodeStubAssembler::BranchIfNumericRelationalComparison(
RelationalComparisonMode mode, compiler::Node* lhs, compiler::Node* rhs,
Label* if_true, Label* if_false) {
typedef compiler::Node Node;
Label end(this);
Variable result(this, MachineRepresentation::kTagged);
// Shared entry for floating point comparison.
Label do_fcmp(this);
Variable var_fcmp_lhs(this, MachineRepresentation::kFloat64),
var_fcmp_rhs(this, MachineRepresentation::kFloat64);
// Check if the {lhs} is a Smi or a HeapObject.
Label if_lhsissmi(this), if_lhsisnotsmi(this);
Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
Bind(&if_lhsissmi);
{
// Check if {rhs} is a Smi or a HeapObject.
Label if_rhsissmi(this), if_rhsisnotsmi(this);
Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
Bind(&if_rhsissmi);
{
// Both {lhs} and {rhs} are Smi, so just perform a fast Smi comparison.
switch (mode) {
case kLessThan:
BranchIfSmiLessThan(lhs, rhs, if_true, if_false);
break;
case kLessThanOrEqual:
BranchIfSmiLessThanOrEqual(lhs, rhs, if_true, if_false);
break;
case kGreaterThan:
BranchIfSmiLessThan(rhs, lhs, if_true, if_false);
break;
case kGreaterThanOrEqual:
BranchIfSmiLessThanOrEqual(rhs, lhs, if_true, if_false);
break;
}
}
Bind(&if_rhsisnotsmi);
{
Assert(WordEqual(LoadMap(rhs), HeapNumberMapConstant()));
// Convert the {lhs} and {rhs} to floating point values, and
// perform a floating point comparison.
var_fcmp_lhs.Bind(SmiToFloat64(lhs));
var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs));
Goto(&do_fcmp);
}
}
Bind(&if_lhsisnotsmi);
{
Assert(WordEqual(LoadMap(lhs), HeapNumberMapConstant()));
// Check if {rhs} is a Smi or a HeapObject.
Label if_rhsissmi(this), if_rhsisnotsmi(this);
Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
Bind(&if_rhsissmi);
{
// Convert the {lhs} and {rhs} to floating point values, and
// perform a floating point comparison.
var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs));
var_fcmp_rhs.Bind(SmiToFloat64(rhs));
Goto(&do_fcmp);
}
Bind(&if_rhsisnotsmi);
{
Assert(WordEqual(LoadMap(rhs), HeapNumberMapConstant()));
// Convert the {lhs} and {rhs} to floating point values, and
// perform a floating point comparison.
var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs));
var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs));
Goto(&do_fcmp);
}
}
Bind(&do_fcmp);
{
// Load the {lhs} and {rhs} floating point values.
Node* lhs = var_fcmp_lhs.value();
Node* rhs = var_fcmp_rhs.value();
// Perform a fast floating point comparison.
switch (mode) {
case kLessThan:
BranchIfFloat64LessThan(lhs, rhs, if_true, if_false);
break;
case kLessThanOrEqual:
BranchIfFloat64LessThanOrEqual(lhs, rhs, if_true, if_false);
break;
case kGreaterThan:
BranchIfFloat64GreaterThan(lhs, rhs, if_true, if_false);
break;
case kGreaterThanOrEqual:
BranchIfFloat64GreaterThanOrEqual(lhs, rhs, if_true, if_false);
break;
}
}
}
void CodeStubAssembler::GotoUnlessNumberLessThan(compiler::Node* lhs,
compiler::Node* rhs,
Label* if_false) {
Label if_true(this);
BranchIfNumericRelationalComparison(kLessThan, lhs, rhs, &if_true, if_false);
Bind(&if_true);
}
compiler::Node* CodeStubAssembler::RelationalComparison(
RelationalComparisonMode mode, compiler::Node* lhs, compiler::Node* rhs,
compiler::Node* context) {
@ -7490,5 +7642,227 @@ compiler::Node* CodeStubAssembler::InstanceOf(compiler::Node* object,
return result.value();
}
compiler::Node* CodeStubAssembler::NumberInc(compiler::Node* value) {
Variable var_result(this, MachineRepresentation::kTagged),
var_finc_value(this, MachineRepresentation::kFloat64);
Label if_issmi(this), if_isnotsmi(this), do_finc(this), end(this);
Branch(TaggedIsSmi(value), &if_issmi, &if_isnotsmi);
Bind(&if_issmi);
{
// Try fast Smi addition first.
Node* one = SmiConstant(Smi::FromInt(1));
Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(value),
BitcastTaggedToWord(one));
Node* overflow = Projection(1, pair);
// Check if the Smi addition overflowed.
Label if_overflow(this), if_notoverflow(this);
Branch(overflow, &if_overflow, &if_notoverflow);
Bind(&if_notoverflow);
var_result.Bind(Projection(0, pair));
Goto(&end);
Bind(&if_overflow);
{
var_finc_value.Bind(SmiToFloat64(value));
Goto(&do_finc);
}
}
Bind(&if_isnotsmi);
{
// Check if the value is a HeapNumber.
Assert(IsHeapNumberMap(LoadMap(value)));
// Load the HeapNumber value.
var_finc_value.Bind(LoadHeapNumberValue(value));
Goto(&do_finc);
}
Bind(&do_finc);
{
Node* finc_value = var_finc_value.value();
Node* one = Float64Constant(1.0);
Node* finc_result = Float64Add(finc_value, one);
var_result.Bind(ChangeFloat64ToTagged(finc_result));
Goto(&end);
}
Bind(&end);
return var_result.value();
}
compiler::Node* CodeStubAssembler::CreateArrayIterator(
compiler::Node* array, compiler::Node* array_map,
compiler::Node* array_type, compiler::Node* context, IterationKind mode) {
int kBaseMapIndex;
switch (mode) {
case IterationKind::kKeys:
kBaseMapIndex = Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX;
break;
case IterationKind::kValues:
kBaseMapIndex = Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX;
break;
case IterationKind::kEntries:
kBaseMapIndex = Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
break;
}
// Fast Array iterator map index:
// (kBaseIndex + kFastIteratorOffset) + ElementsKind (for JSArrays)
// kBaseIndex + (ElementsKind - UINT8_ELEMENTS) (for JSTypedArrays)
const int kFastIteratorOffset =
Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX -
Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX;
STATIC_ASSERT(kFastIteratorOffset ==
(Context::FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX -
Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX));
// Slow Array iterator map index: (kBaseIndex + kSlowIteratorOffset)
const int kSlowIteratorOffset =
Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX -
Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX;
STATIC_ASSERT(kSlowIteratorOffset ==
(Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX -
Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX));
// Assert: Type(array) is Object
Assert(IsJSReceiverInstanceType(array_type));
Variable var_result(this, MachineRepresentation::kTagged);
Variable var_map_index(this, MachineType::PointerRepresentation());
Variable var_array_map(this, MachineRepresentation::kTagged);
Label return_result(this);
Label allocate_iterator(this);
if (mode == IterationKind::kKeys) {
// There are only two key iterator maps, branch depending on whether or not
// the receiver is a TypedArray or not.
Label if_isarray(this), if_istypedarray(this), if_isgeneric(this);
Label* kInstanceTypeHandlers[] = {&if_isarray, &if_istypedarray};
static int32_t kInstanceType[] = {JS_ARRAY_TYPE, JS_TYPED_ARRAY_TYPE};
Switch(array_type, &if_isgeneric, kInstanceType, kInstanceTypeHandlers,
arraysize(kInstanceType));
Bind(&if_isarray);
{
var_map_index.Bind(
IntPtrConstant(Context::FAST_ARRAY_KEY_ITERATOR_MAP_INDEX));
var_array_map.Bind(array_map);
Goto(&allocate_iterator);
}
Bind(&if_istypedarray);
{
var_map_index.Bind(
IntPtrConstant(Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX));
var_array_map.Bind(UndefinedConstant());
Goto(&allocate_iterator);
}
Bind(&if_isgeneric);
{
var_map_index.Bind(
IntPtrConstant(Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX));
var_array_map.Bind(UndefinedConstant());
Goto(&allocate_iterator);
}
} else {
Label if_istypedarray(this), if_isgeneric(this);
Branch(Word32Equal(array_type, Int32Constant(JS_TYPED_ARRAY_TYPE)),
&if_istypedarray, &if_isgeneric);
Bind(&if_isgeneric);
{
Label if_isfast(this), if_isslow(this);
BranchIfFastJSArray(array, context, &if_isfast, &if_isslow);
Bind(&if_isfast);
{
Node* map_index =
IntPtrAdd(IntPtrConstant(kBaseMapIndex + kFastIteratorOffset),
LoadMapElementsKind(array_map));
Assert(IntPtrGreaterThanOrEqual(
map_index, IntPtrConstant(kBaseMapIndex + kFastIteratorOffset)));
Assert(IntPtrLessThan(
map_index, IntPtrConstant(kBaseMapIndex + kSlowIteratorOffset)));
var_map_index.Bind(map_index);
var_array_map.Bind(array_map);
Goto(&allocate_iterator);
}
Bind(&if_isslow);
{
Node* map_index = IntPtrAdd(IntPtrConstant(kBaseMapIndex),
IntPtrConstant(kSlowIteratorOffset));
var_map_index.Bind(map_index);
var_array_map.Bind(UndefinedConstant());
Goto(&allocate_iterator);
}
}
Bind(&if_istypedarray);
{
Node* map_index =
IntPtrAdd(IntPtrConstant(kBaseMapIndex - UINT8_ELEMENTS),
LoadMapElementsKind(array_map));
Assert(IntPtrLessThan(
map_index, IntPtrConstant(kBaseMapIndex + kFastIteratorOffset)));
Assert(
IntPtrGreaterThanOrEqual(map_index, IntPtrConstant(kBaseMapIndex)));
var_map_index.Bind(map_index);
var_array_map.Bind(UndefinedConstant());
Goto(&allocate_iterator);
}
}
Bind(&allocate_iterator);
{
Node* map =
LoadFixedArrayElement(LoadNativeContext(context), var_map_index.value(),
0, CodeStubAssembler::INTPTR_PARAMETERS);
var_result.Bind(AllocateJSArrayIterator(array, var_array_map.value(), map));
Goto(&return_result);
}
Bind(&return_result);
return var_result.value();
}
compiler::Node* CodeStubAssembler::AllocateJSArrayIterator(
compiler::Node* array, compiler::Node* array_map, compiler::Node* map) {
Node* iterator = Allocate(JSArrayIterator::kSize);
StoreMapNoWriteBarrier(iterator, map);
StoreObjectFieldRoot(iterator, JSArrayIterator::kPropertiesOffset,
Heap::kEmptyFixedArrayRootIndex);
StoreObjectFieldRoot(iterator, JSArrayIterator::kElementsOffset,
Heap::kEmptyFixedArrayRootIndex);
StoreObjectFieldNoWriteBarrier(iterator,
JSArrayIterator::kIteratedObjectOffset, array);
StoreObjectFieldNoWriteBarrier(iterator, JSArrayIterator::kNextIndexOffset,
SmiConstant(Smi::FromInt(0)));
StoreObjectFieldNoWriteBarrier(
iterator, JSArrayIterator::kIteratedObjectMapOffset, array_map);
return iterator;
}
compiler::Node* CodeStubAssembler::IsDetachedBuffer(compiler::Node* buffer) {
AssertInstanceType(buffer, JS_ARRAY_BUFFER_TYPE);
Node* buffer_bit_field = LoadObjectField(
buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32());
Node* was_neutered_mask = Int32Constant(JSArrayBuffer::WasNeutered::kMask);
return Word32NotEqual(Word32And(buffer_bit_field, was_neutered_mask),
Int32Constant(0));
}
} // namespace internal
} // namespace v8

View File

@ -20,6 +20,8 @@ class StubCache;
enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
enum class IterationKind { kKeys, kValues, kEntries };
#define HEAP_CONSTANT_LIST(V) \
V(BooleanMap, BooleanMap) \
V(empty_string, EmptyString) \
@ -140,6 +142,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
WordOr(BitcastTaggedToWord(a), BitcastTaggedToWord(b)));
}
// Smi | HeapNumber operations.
compiler::Node* NumberInc(compiler::Node* value);
// Allocate an object of the given size.
compiler::Node* Allocate(compiler::Node* size, AllocationFlags flags = kNone);
compiler::Node* Allocate(int size, AllocationFlags flags = kNone);
@ -296,6 +301,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* LoadDoubleWithHoleCheck(
compiler::Node* base, compiler::Node* offset, Label* if_hole,
MachineType machine_type = MachineType::Float64());
compiler::Node* LoadFixedTypedArrayElement(
compiler::Node* data_pointer, compiler::Node* index_node,
ElementsKind elements_kind,
ParameterMode parameter_mode = INTEGER_PARAMETERS);
// Context manipulation
compiler::Node* LoadContextElement(compiler::Node* context, int slot_index);
@ -407,6 +416,17 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
ParameterMode mode = INTEGER_PARAMETERS,
AllocationFlags flags = kNone);
// Perform CreateArrayIterator (ES6 #sec-createarrayiterator).
compiler::Node* CreateArrayIterator(compiler::Node* array,
compiler::Node* array_map,
compiler::Node* array_type,
compiler::Node* context,
IterationKind mode);
compiler::Node* AllocateJSArrayIterator(compiler::Node* array,
compiler::Node* array_map,
compiler::Node* map);
void FillFixedArrayWithValue(ElementsKind kind, compiler::Node* array,
compiler::Node* from_index,
compiler::Node* to_index,
@ -908,6 +928,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* lhs, compiler::Node* rhs,
compiler::Node* context);
void BranchIfNumericRelationalComparison(RelationalComparisonMode mode,
compiler::Node* lhs,
compiler::Node* rhs, Label* if_true,
Label* if_false);
void GotoUnlessNumberLessThan(compiler::Node* lhs, compiler::Node* rhs,
Label* if_false);
enum ResultMode { kDontNegateResult, kNegateResult };
compiler::Node* Equal(ResultMode mode, compiler::Node* lhs,
@ -927,6 +955,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* InstanceOf(compiler::Node* object, compiler::Node* callable,
compiler::Node* context);
// TypedArray/ArrayBuffer helpers
compiler::Node* IsDetachedBuffer(compiler::Node* buffer);
private:
enum ElementSupport { kOnlyProperties, kSupportElements };

View File

@ -215,6 +215,43 @@ Type::bitset BitsetType::Lub(i::Map* map) {
case JS_SET_ITERATOR_TYPE:
case JS_MAP_ITERATOR_TYPE:
case JS_STRING_ITERATOR_TYPE:
case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE:
case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE:
case JS_WEAK_MAP_TYPE:
case JS_WEAK_SET_TYPE:
case JS_PROMISE_TYPE:

View File

@ -112,6 +112,73 @@ enum ContextLookupFlags {
wasm_compile_error_function) \
V(WASM_RUNTIME_ERROR_FUNCTION_INDEX, JSFunction, wasm_runtime_error_function)
#define NATIVE_CONTEXT_JS_ARRAY_ITERATOR_MAPS(V) \
V(TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX, Map, typed_array_key_iterator_map) \
V(FAST_ARRAY_KEY_ITERATOR_MAP_INDEX, Map, fast_array_key_iterator_map) \
V(GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX, Map, array_key_iterator_map) \
\
V(UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
uint8_array_key_value_iterator_map) \
V(INT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
int8_array_key_value_iterator_map) \
V(UINT16_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
uint16_array_key_value_iterator_map) \
V(INT16_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
int16_array_key_value_iterator_map) \
V(UINT32_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
uint32_array_key_value_iterator_map) \
V(INT32_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
int32_array_key_value_iterator_map) \
V(FLOAT32_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
float32_array_key_value_iterator_map) \
V(FLOAT64_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
float64_array_key_value_iterator_map) \
V(UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
uint8_clamped_array_key_value_iterator_map) \
\
V(FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
fast_smi_array_key_value_iterator_map) \
V(FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
fast_holey_smi_array_key_value_iterator_map) \
V(FAST_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
fast_array_key_value_iterator_map) \
V(FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
fast_holey_array_key_value_iterator_map) \
V(FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
fast_double_array_key_value_iterator_map) \
V(FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
fast_holey_double_array_key_value_iterator_map) \
V(GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX, Map, \
array_key_value_iterator_map) \
\
V(UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, uint8_array_value_iterator_map) \
V(INT8_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, int8_array_value_iterator_map) \
V(UINT16_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, \
uint16_array_value_iterator_map) \
V(INT16_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, int16_array_value_iterator_map) \
V(UINT32_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, \
uint32_array_value_iterator_map) \
V(INT32_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, int32_array_value_iterator_map) \
V(FLOAT32_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, \
float32_array_value_iterator_map) \
V(FLOAT64_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, \
float64_array_value_iterator_map) \
V(UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, \
uint8_clamped_array_value_iterator_map) \
\
V(FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, \
fast_smi_array_value_iterator_map) \
V(FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, \
fast_holey_smi_array_value_iterator_map) \
V(FAST_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, fast_array_value_iterator_map) \
V(FAST_HOLEY_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, \
fast_holey_array_value_iterator_map) \
V(FAST_DOUBLE_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, \
fast_double_array_value_iterator_map) \
V(FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, \
fast_holey_double_array_value_iterator_map) \
V(GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX, Map, array_value_iterator_map)
#define NATIVE_CONTEXT_FIELDS(V) \
V(GLOBAL_PROXY_INDEX, JSObject, global_proxy_object) \
V(EMBEDDER_DATA_INDEX, FixedArray, embedder_data) \
@ -256,7 +323,8 @@ enum ContextLookupFlags {
V(UINT8X16_FUNCTION_INDEX, JSFunction, uint8x16_function) \
V(CURRENT_MODULE_INDEX, Module, current_module) \
NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(V) \
NATIVE_CONTEXT_IMPORTED_FIELDS(V)
NATIVE_CONTEXT_IMPORTED_FIELDS(V) \
NATIVE_CONTEXT_JS_ARRAY_ITERATOR_MAPS(V)
// A table of all script contexts. Every loaded top-level script with top-level
// lexical declarations contributes its ScriptContext into this table.
@ -369,7 +437,7 @@ class Context: public FixedArray {
static inline Context* cast(Object* context);
// The default context slot layout; indices are FixedArray slot indices.
enum {
enum Field {
// These slots are in all contexts.
CLOSURE_INDEX,
PREVIOUS_INDEX,
@ -575,6 +643,8 @@ class Context: public FixedArray {
STATIC_ASSERT(EMBEDDER_DATA_INDEX == Internals::kContextEmbedderDataIndex);
};
typedef Context::Field ContextField;
} // namespace internal
} // namespace v8

View File

@ -12,6 +12,7 @@
V(Arguments_string, "Arguments") \
V(arguments_to_string, "[object Arguments]") \
V(Array_string, "Array") \
V(ArrayIterator_string, "Array Iterator") \
V(assign_string, "assign") \
V(array_to_string, "[object Array]") \
V(boolean_to_string, "[object Boolean]") \
@ -96,6 +97,7 @@
V(isView_string, "isView") \
V(KeyedLoadMonomorphic_string, "KeyedLoadMonomorphic") \
V(KeyedStoreMonomorphic_string, "KeyedStoreMonomorphic") \
V(keys_string, "keys") \
V(lastIndex_string, "lastIndex") \
V(length_string, "length") \
V(line_string, "line") \

View File

@ -122,6 +122,43 @@ StaticVisitorBase::VisitorId StaticVisitorBase::GetVisitorId(
case JS_SET_ITERATOR_TYPE:
case JS_MAP_ITERATOR_TYPE:
case JS_STRING_ITERATOR_TYPE:
case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE:
case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE:
case JS_PROMISE_TYPE:
case JS_BOUND_FUNCTION_TYPE:
return GetVisitorIdForSize(kVisitJSObject, kVisitJSObjectGeneric,

View File

@ -1,168 +0,0 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(function(global, utils) {
"use strict";
%CheckIsBootstrapping();
// -----------------------------------------------------------------------
// Imports
var arrayIterationKindSymbol =
utils.ImportNow("array_iteration_kind_symbol");
var arrayIteratorNextIndexSymbol =
utils.ImportNow("array_iterator_next_symbol");
var arrayIteratorObjectSymbol =
utils.ImportNow("array_iterator_object_symbol");
var GlobalArray = global.Array;
var IteratorPrototype = utils.ImportNow("IteratorPrototype");
var iteratorSymbol = utils.ImportNow("iterator_symbol");
var toStringTagSymbol = utils.ImportNow("to_string_tag_symbol");
var GlobalTypedArray = %object_get_prototype_of(global.Uint8Array);
// -----------------------------------------------------------------------
function ArrayIterator() {}
// TODO(wingo): Update section numbers when ES6 has stabilized. The
// section numbers below are already out of date as of the May 2014
// draft.
// 15.4.5.1 CreateArrayIterator Abstract Operation
function CreateArrayIterator(array, kind) {
var object = TO_OBJECT(array);
var iterator = new ArrayIterator;
SET_PRIVATE(iterator, arrayIteratorObjectSymbol, object);
SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, 0);
SET_PRIVATE(iterator, arrayIterationKindSymbol, kind);
return iterator;
}
// 22.1.5.2.2 %ArrayIteratorPrototype%[@@iterator]
function ArrayIteratorIterator() {
return this;
}
// ES6 section 22.1.5.2.1 %ArrayIteratorPrototype%.next( )
function ArrayIteratorNext() {
var iterator = this;
var value = UNDEFINED;
var done = true;
if (!IS_RECEIVER(iterator) ||
!HAS_DEFINED_PRIVATE(iterator, arrayIteratorNextIndexSymbol)) {
throw %make_type_error(kIncompatibleMethodReceiver,
'Array Iterator.prototype.next', this);
}
var array = GET_PRIVATE(iterator, arrayIteratorObjectSymbol);
if (!IS_UNDEFINED(array)) {
var index = GET_PRIVATE(iterator, arrayIteratorNextIndexSymbol);
var itemKind = GET_PRIVATE(iterator, arrayIterationKindSymbol);
var length = TO_UINT32(array.length);
// "sparse" is never used.
if (index >= length) {
SET_PRIVATE(iterator, arrayIteratorObjectSymbol, UNDEFINED);
} else {
SET_PRIVATE(iterator, arrayIteratorNextIndexSymbol, index + 1);
if (itemKind == ITERATOR_KIND_VALUES) {
value = array[index];
} else if (itemKind == ITERATOR_KIND_ENTRIES) {
value = [index, array[index]];
} else {
value = index;
}
done = false;
}
}
return %_CreateIterResultObject(value, done);
}
function ArrayEntries() {
return CreateArrayIterator(this, ITERATOR_KIND_ENTRIES);
}
function ArrayValues() {
return CreateArrayIterator(this, ITERATOR_KIND_VALUES);
}
function ArrayKeys() {
return CreateArrayIterator(this, ITERATOR_KIND_KEYS);
}
// TODO(littledan): Check for detached TypedArray in these three methods
function TypedArrayEntries() {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
return %_Call(ArrayEntries, this);
}
function TypedArrayValues() {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
return %_Call(ArrayValues, this);
}
function TypedArrayKeys() {
if (!IS_TYPEDARRAY(this)) throw %make_type_error(kNotTypedArray);
return %_Call(ArrayKeys, this);
}
%FunctionSetPrototype(ArrayIterator, {__proto__: IteratorPrototype});
%FunctionSetInstanceClassName(ArrayIterator, 'Array Iterator');
utils.InstallFunctions(ArrayIterator.prototype, DONT_ENUM, [
'next', ArrayIteratorNext
]);
utils.SetFunctionName(ArrayIteratorIterator, iteratorSymbol);
%AddNamedProperty(ArrayIterator.prototype, toStringTagSymbol,
"Array Iterator", READ_ONLY | DONT_ENUM);
utils.InstallFunctions(GlobalArray.prototype, DONT_ENUM, [
// No 'values' since it breaks webcompat: http://crbug.com/409858
'entries', ArrayEntries,
'keys', ArrayKeys
]);
// TODO(adam): Remove these calls once 'values' is in the above
// InstallFunctions block, as they'll be redundant.
utils.SetFunctionName(ArrayValues, 'values');
%FunctionRemovePrototype(ArrayValues);
%SetNativeFlag(ArrayValues);
%AddNamedProperty(GlobalArray.prototype, iteratorSymbol, ArrayValues,
DONT_ENUM);
utils.InstallFunctions(GlobalTypedArray.prototype, DONT_ENUM, [
'entries', TypedArrayEntries,
'keys', TypedArrayKeys,
'values', TypedArrayValues
]);
%AddNamedProperty(GlobalTypedArray.prototype,
iteratorSymbol, TypedArrayValues, DONT_ENUM);
// -------------------------------------------------------------------
// Exports
utils.Export(function(to) {
to.ArrayValues = ArrayValues;
});
%InstallToContext(["array_values_iterator", ArrayValues]);
})

View File

@ -1539,6 +1539,8 @@ var getFunction = function(name, jsBuiltin, len) {
return f;
};
var ArrayValues = getFunction("values", null, 0);
// Set up non-enumerable functions of the Array.prototype object and
// set their names.
// Manipulate the length of some of the functions to meet
@ -1568,9 +1570,14 @@ utils.InstallFunctions(GlobalArray.prototype, DONT_ENUM, [
"find", getFunction("find", ArrayFind, 1),
"findIndex", getFunction("findIndex", ArrayFindIndex, 1),
"fill", getFunction("fill", ArrayFill, 1),
"includes", getFunction("includes", null, 1)
"includes", getFunction("includes", null, 1),
"keys", getFunction("keys", null, 0),
"entries", getFunction("entries", null, 0),
iteratorSymbol, ArrayValues
]);
%FunctionSetName(ArrayValues, "values");
utils.InstallGetter(GlobalArray, speciesSymbol, ArraySpecies);
%FinishArrayPrototypeSetup(GlobalArray.prototype);
@ -1614,6 +1621,7 @@ utils.Export(function(to) {
to.ArrayJoin = ArrayJoin;
to.ArrayPush = ArrayPush;
to.ArrayToString = ArrayToString;
to.ArrayValues = ArrayValues;
to.InnerArrayCopyWithin = InnerArrayCopyWithin;
to.InnerArrayEvery = InnerArrayEvery;
to.InnerArrayFill = InnerArrayFill;
@ -1638,6 +1646,7 @@ utils.Export(function(to) {
"array_splice", ArraySplice,
"array_slice", ArraySlice,
"array_unshift", ArrayUnshift,
"array_values_iterator", ArrayValues,
]);
});

View File

@ -477,6 +477,43 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3) {
case JS_SET_ITERATOR_TYPE:
case JS_MAP_ITERATOR_TYPE:
case JS_STRING_ITERATOR_TYPE:
case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE:
case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE:
case JS_REGEXP_TYPE:
case JS_GLOBAL_PROXY_TYPE:
case JS_GLOBAL_OBJECT_TYPE:

View File

@ -158,6 +158,44 @@ void HeapObject::HeapObjectVerify() {
case JS_MAP_ITERATOR_TYPE:
JSMapIterator::cast(this)->JSMapIteratorVerify();
break;
case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE:
case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE:
case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
case JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE:
JSArrayIterator::cast(this)->JSArrayIteratorVerify();
break;
case JS_STRING_ITERATOR_TYPE:
JSStringIterator::cast(this)->JSStringIteratorVerify();
break;
@ -788,6 +826,16 @@ void JSWeakMap::JSWeakMapVerify() {
CHECK(table()->IsHashTable() || table()->IsUndefined(GetIsolate()));
}
void JSArrayIterator::JSArrayIteratorVerify() {
CHECK(IsJSArrayIterator());
JSObjectVerify();
CHECK(object()->IsJSReceiver() || object()->IsUndefined(GetIsolate()));
CHECK_GE(index()->Number(), 0);
CHECK_LE(index()->Number(), kMaxSafeInteger);
CHECK(object_map()->IsMap() || object_map()->IsUndefined(GetIsolate()));
}
void JSStringIterator::JSStringIteratorVerify() {
CHECK(IsJSStringIterator());
JSObjectVerify();

View File

@ -690,6 +690,12 @@ bool HeapObject::IsJSObject() const {
bool HeapObject::IsJSProxy() const { return map()->IsJSProxyMap(); }
bool HeapObject::IsJSArrayIterator() const {
InstanceType instance_type = map()->instance_type();
return (instance_type >= FIRST_ARRAY_ITERATOR_TYPE &&
instance_type <= LAST_ARRAY_ITERATOR_TYPE);
}
TYPE_CHECKER(JSSet, JS_SET_TYPE)
TYPE_CHECKER(JSMap, JS_MAP_TYPE)
TYPE_CHECKER(JSSetIterator, JS_SET_ITERATOR_TYPE)
@ -3338,6 +3344,7 @@ CAST_ACCESSOR(JSRegExp)
CAST_ACCESSOR(JSSet)
CAST_ACCESSOR(JSSetIterator)
CAST_ACCESSOR(JSStringIterator)
CAST_ACCESSOR(JSArrayIterator)
CAST_ACCESSOR(JSTypedArray)
CAST_ACCESSOR(JSValue)
CAST_ACCESSOR(JSWeakCollection)
@ -8357,6 +8364,10 @@ static inline Handle<Object> MakeEntryPair(Isolate* isolate, Handle<Name> key,
ACCESSORS(JSIteratorResult, value, Object, kValueOffset)
ACCESSORS(JSIteratorResult, done, Object, kDoneOffset)
ACCESSORS(JSArrayIterator, object, Object, kIteratedObjectOffset)
ACCESSORS(JSArrayIterator, index, Object, kNextIndexOffset)
ACCESSORS(JSArrayIterator, object_map, Object, kIteratedObjectMapOffset)
ACCESSORS(JSStringIterator, string, String, kStringOffset)
SMI_ACCESSORS(JSStringIterator, index, kNextIndexOffset)

View File

@ -444,6 +444,46 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(JS_ERROR_TYPE) \
V(JS_STRING_ITERATOR_TYPE) \
\
V(JS_TYPED_ARRAY_KEY_ITERATOR_TYPE) \
V(JS_FAST_ARRAY_KEY_ITERATOR_TYPE) \
V(JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE) \
\
V(JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
\
V(JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
V(JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE) \
\
V(JS_INT8_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_INT16_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_INT32_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE) \
\
V(JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_FAST_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE) \
V(JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE) \
\
V(JS_BOUND_FUNCTION_TYPE) \
V(JS_FUNCTION_TYPE) \
V(DEBUG_INFO_TYPE) \
@ -747,6 +787,47 @@ enum InstanceType {
JS_REGEXP_TYPE,
JS_ERROR_TYPE,
JS_STRING_ITERATOR_TYPE,
JS_TYPED_ARRAY_KEY_ITERATOR_TYPE,
JS_FAST_ARRAY_KEY_ITERATOR_TYPE,
JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE,
JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE,
JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE,
JS_INT8_ARRAY_VALUE_ITERATOR_TYPE,
JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE,
JS_INT16_ARRAY_VALUE_ITERATOR_TYPE,
JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE,
JS_INT32_ARRAY_VALUE_ITERATOR_TYPE,
JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE,
JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE,
JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE,
JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE,
JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE,
JS_FAST_ARRAY_VALUE_ITERATOR_TYPE,
JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE,
JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE,
JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE,
JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE,
JS_BOUND_FUNCTION_TYPE,
JS_FUNCTION_TYPE, // LAST_JS_OBJECT_TYPE, LAST_JS_RECEIVER_TYPE
@ -783,6 +864,18 @@ enum InstanceType {
// an empty fixed array as elements backing store. This is true for string
// wrappers.
LAST_CUSTOM_ELEMENTS_RECEIVER = JS_VALUE_TYPE,
FIRST_ARRAY_KEY_ITERATOR_TYPE = JS_TYPED_ARRAY_KEY_ITERATOR_TYPE,
LAST_ARRAY_KEY_ITERATOR_TYPE = JS_GENERIC_ARRAY_KEY_ITERATOR_TYPE,
FIRST_ARRAY_KEY_VALUE_ITERATOR_TYPE = JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE,
LAST_ARRAY_KEY_VALUE_ITERATOR_TYPE = JS_GENERIC_ARRAY_KEY_VALUE_ITERATOR_TYPE,
FIRST_ARRAY_VALUE_ITERATOR_TYPE = JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE,
LAST_ARRAY_VALUE_ITERATOR_TYPE = JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE,
FIRST_ARRAY_ITERATOR_TYPE = FIRST_ARRAY_KEY_ITERATOR_TYPE,
LAST_ARRAY_ITERATOR_TYPE = LAST_ARRAY_VALUE_ITERATOR_TYPE,
};
STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType);
@ -1028,6 +1121,7 @@ template <class C> inline bool Is(Object* obj);
V(JSArrayBufferView) \
V(JSCollection) \
V(JSTypedArray) \
V(JSArrayIterator) \
V(JSDataView) \
V(JSProxy) \
V(JSError) \
@ -10515,6 +10609,32 @@ class JSMap : public JSCollection {
DISALLOW_IMPLICIT_CONSTRUCTORS(JSMap);
};
class JSArrayIterator : public JSObject {
public:
DECLARE_PRINTER(JSArrayIterator)
DECLARE_VERIFIER(JSArrayIterator)
DECLARE_CAST(JSArrayIterator)
// [object]: the [[IteratedObject]] internal field.
DECL_ACCESSORS(object, Object)
// [index]: The [[ArrayIteratorNextIndex]] internal field.
DECL_ACCESSORS(index, Object)
// [map]: The Map of the [[IteratedObject]] field at the time the iterator is
// allocated.
DECL_ACCESSORS(object_map, Object)
static const int kIteratedObjectOffset = JSObject::kHeaderSize;
static const int kNextIndexOffset = kIteratedObjectOffset + kPointerSize;
static const int kIteratedObjectMapOffset = kNextIndexOffset + kPointerSize;
static const int kSize = kIteratedObjectMapOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayIterator);
};
class JSStringIterator : public JSObject {
public:
// Dispatched behavior.

View File

@ -71,6 +71,10 @@ RUNTIME_FUNCTION(Runtime_SpecialArrayFunctions) {
InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
InstallBuiltin(isolate, holder, "includes", Builtins::kArrayIncludes, 2);
InstallBuiltin(isolate, holder, "indexOf", Builtins::kArrayIndexOf, 2);
InstallBuiltin(isolate, holder, "keys", Builtins::kArrayPrototypeKeys, 0);
InstallBuiltin(isolate, holder, "values", Builtins::kArrayPrototypeValues, 0);
InstallBuiltin(isolate, holder, "entries", Builtins::kArrayPrototypeEntries,
0);
return *holder;
}

View File

@ -2238,7 +2238,6 @@
'js/collection-iterator.js',
'js/promise.js',
'js/messages.js',
'js/array-iterator.js',
'js/templates.js',
'js/spread.js',
'js/proxy.js',

View File

@ -193,7 +193,6 @@
# https://bugs.chromium.org/p/v8/issues/detail?id=4648
'built-ins/TypedArray/prototype/copyWithin/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/entries/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/every/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/fill/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/filter/detached-buffer': [FAIL],
@ -203,7 +202,6 @@
'built-ins/TypedArray/prototype/includes/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/indexOf/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/join/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/keys/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/lastIndexOf/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/map/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/reverse/detached-buffer': [FAIL],
@ -213,7 +211,6 @@
'built-ins/TypedArray/prototype/subarray/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/toLocaleString/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/toString/detached-buffer': [FAIL],
'built-ins/TypedArray/prototype/values/detached-buffer': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=4034
'built-ins/ThrowTypeError/unique-per-realm-function-proto': [FAIL],