Add a Torque module exposing iterators

This is preparation to support the Torque port of Object.fromEntries,
including tests to make sure that the interface of the iterator functions
is correct and compiles when used.

Change-Id: I2a30ef80a80f42d4744a92746c8cd383abc10c19
Reviewed-on: https://chromium-review.googlesource.com/c/1303726
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57192}
This commit is contained in:
Daniel Clifford 2018-10-31 15:59:13 +01:00 committed by Commit Bot
parent 77d65f9a1f
commit 2e3ba516cf
10 changed files with 101 additions and 35 deletions

View File

@ -929,6 +929,7 @@ torque_files = [
"src/builtins/array-unshift.tq", "src/builtins/array-unshift.tq",
"src/builtins/typed-array.tq", "src/builtins/typed-array.tq",
"src/builtins/data-view.tq", "src/builtins/data-view.tq",
"src/builtins/iterator.tq",
"test/torque/test-torque.tq", "test/torque/test-torque.tq",
"third_party/v8/builtins/array-sort.tq", "third_party/v8/builtins/array-sort.tq",
] ]
@ -936,6 +937,7 @@ torque_files = [
torque_modules = [ torque_modules = [
"base", "base",
"array", "array",
"iterator",
"typed-array", "typed-array",
"data-view", "data-view",
"test", "test",

View File

@ -1190,3 +1190,13 @@ extern macro TryIntPtrAdd(intptr, intptr): intptr
extern builtin ObjectToString(Context, Object): Object; extern builtin ObjectToString(Context, Object): Object;
extern builtin StringRepeat(Context, String, Number): String; extern builtin StringRepeat(Context, String, Number): String;
// Returned from IteratorBuiltinsAssembler::GetIterator(). Struct is declared
// here to simplify use in other generated builtins.
struct IteratorRecord {
// iteratorRecord.[[Iterator]]
object: JSReceiver;
// iteratorRecord.[[NextMethod]]
next: Object;
}

View File

@ -1847,10 +1847,10 @@ TF_BUILTIN(ArrayPrototypeFindIndex, ArrayBuiltinsAssembler) {
MissingPropertyMode::kUseUndefined, ForEachDirection::kForward); MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
} }
class ArrayPopulatorAssembler : public CodeStubAssembler { class ArrayPopulatorAssembler : public BaseBuiltinsFromDSLAssembler {
public: public:
explicit ArrayPopulatorAssembler(compiler::CodeAssemblerState* state) explicit ArrayPopulatorAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {} : BaseBuiltinsFromDSLAssembler(state) {}
TNode<Object> ConstructArrayLike(TNode<Context> context, TNode<Object> ConstructArrayLike(TNode<Context> context,
TNode<Object> receiver) { TNode<Object> receiver) {
@ -2008,8 +2008,8 @@ TF_BUILTIN(ArrayFrom, ArrayPopulatorAssembler) {
BIND(&loop); BIND(&loop);
{ {
// Loop while iterator is not done. // Loop while iterator is not done.
TNode<Object> next = CAST(iterator_assembler.IteratorStep( TNode<Object> next = iterator_assembler.IteratorStep(
context, iterator_record, &loop_done, fast_iterator_result_map)); context, iterator_record, &loop_done, fast_iterator_result_map);
TVARIABLE(Object, value, TVARIABLE(Object, value,
CAST(iterator_assembler.IteratorValue( CAST(iterator_assembler.IteratorValue(
context, next, fast_iterator_result_map))); context, next, fast_iterator_result_map)));

View File

@ -11,6 +11,7 @@
#include "src/heap/factory-inl.h" #include "src/heap/factory-inl.h"
#include "src/objects/hash-table-inl.h" #include "src/objects/hash-table-inl.h"
#include "src/objects/js-collection.h" #include "src/objects/js-collection.h"
#include "torque-generated/builtins-base-from-dsl-gen.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -18,10 +19,10 @@ namespace internal {
template <class T> template <class T>
using TVariable = compiler::TypedCodeAssemblerVariable<T>; using TVariable = compiler::TypedCodeAssemblerVariable<T>;
class BaseCollectionsAssembler : public CodeStubAssembler { class BaseCollectionsAssembler : public BaseBuiltinsFromDSLAssembler {
public: public:
explicit BaseCollectionsAssembler(compiler::CodeAssemblerState* state) explicit BaseCollectionsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {} : BaseBuiltinsFromDSLAssembler(state) {}
virtual ~BaseCollectionsAssembler() = default; virtual ~BaseCollectionsAssembler() = default;
@ -328,8 +329,8 @@ void BaseCollectionsAssembler::AddConstructorEntriesFromIterable(
Goto(&loop); Goto(&loop);
BIND(&loop); BIND(&loop);
{ {
TNode<Object> next = CAST(iterator_assembler.IteratorStep( TNode<Object> next = iterator_assembler.IteratorStep(
context, iterator, &exit, fast_iterator_result_map)); context, iterator, &exit, fast_iterator_result_map);
TNode<Object> next_value = CAST(iterator_assembler.IteratorValue( TNode<Object> next_value = CAST(iterator_assembler.IteratorValue(
context, next, fast_iterator_result_map)); context, next, fast_iterator_result_map));
AddConstructorEntry(variant, context, collection, add_func, next_value, AddConstructorEntry(variant, context, collection, add_func, next_value,

View File

@ -11,10 +11,13 @@
#include "src/builtins/builtins.h" #include "src/builtins/builtins.h"
#include "src/code-stub-assembler.h" #include "src/code-stub-assembler.h"
#include "src/heap/factory-inl.h" #include "src/heap/factory-inl.h"
#include "torque-generated/builtins-base-from-dsl-gen.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
typedef BaseBuiltinsFromDSLAssembler::IteratorRecord IteratorRecord;
using compiler::Node; using compiler::Node;
TNode<Object> IteratorBuiltinsAssembler::GetIteratorMethod(Node* context, TNode<Object> IteratorBuiltinsAssembler::GetIteratorMethod(Node* context,
@ -74,7 +77,7 @@ IteratorRecord IteratorBuiltinsAssembler::GetIterator(Node* context,
} }
} }
Node* IteratorBuiltinsAssembler::IteratorStep( TNode<Object> IteratorBuiltinsAssembler::IteratorStep(
Node* context, const IteratorRecord& iterator, Label* if_done, Node* context, const IteratorRecord& iterator, Label* if_done,
Node* fast_iterator_result_map, Label* if_exception, Variable* exception) { Node* fast_iterator_result_map, Label* if_exception, Variable* exception) {
DCHECK_NOT_NULL(if_done); DCHECK_NOT_NULL(if_done);
@ -124,7 +127,7 @@ Node* IteratorBuiltinsAssembler::IteratorStep(
} }
BIND(&return_result); BIND(&return_result);
return result; return UncheckedCast<Object>(result);
} }
Node* IteratorBuiltinsAssembler::IteratorValue(Node* context, Node* result, Node* IteratorBuiltinsAssembler::IteratorValue(Node* context, Node* result,
@ -164,8 +167,8 @@ void IteratorBuiltinsAssembler::IteratorCloseOnException(
// Perform ES #sec-iteratorclose when an exception occurs. This simpler // Perform ES #sec-iteratorclose when an exception occurs. This simpler
// algorithm does not include redundant steps which are never reachable from // algorithm does not include redundant steps which are never reachable from
// the spec IteratorClose algorithm. // the spec IteratorClose algorithm.
DCHECK_NOT_NULL(if_exception); DCHECK((if_exception != nullptr && exception != nullptr) ||
DCHECK_NOT_NULL(exception); IsExceptionHandlerActive());
CSA_ASSERT(this, IsNotTheHole(exception->value())); CSA_ASSERT(this, IsNotTheHole(exception->value()));
CSA_ASSERT(this, IsJSReceiver(iterator.object)); CSA_ASSERT(this, IsJSReceiver(iterator.object));
@ -216,7 +219,7 @@ TNode<JSArray> IteratorBuiltinsAssembler::IterableToList(
BIND(&loop_start); BIND(&loop_start);
{ {
// a. Set next to ? IteratorStep(iteratorRecord). // a. Set next to ? IteratorStep(iteratorRecord).
TNode<Object> next = CAST(IteratorStep(context, iterator_record, &done)); TNode<Object> next = IteratorStep(context, iterator_record, &done);
// b. If next is not false, then // b. If next is not false, then
// i. Let nextValue be ? IteratorValue(next). // i. Let nextValue be ? IteratorValue(next).
TNode<Object> next_value = CAST(IteratorValue(context, next)); TNode<Object> next_value = CAST(IteratorValue(context, next));

View File

@ -5,17 +5,17 @@
#ifndef V8_BUILTINS_BUILTINS_ITERATOR_GEN_H_ #ifndef V8_BUILTINS_BUILTINS_ITERATOR_GEN_H_
#define V8_BUILTINS_BUILTINS_ITERATOR_GEN_H_ #define V8_BUILTINS_BUILTINS_ITERATOR_GEN_H_
#include "src/code-stub-assembler.h" #include "torque-generated/builtins-base-from-dsl-gen.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
using compiler::Node; using compiler::Node;
class IteratorBuiltinsAssembler : public CodeStubAssembler { class IteratorBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
public: public:
explicit IteratorBuiltinsAssembler(compiler::CodeAssemblerState* state) explicit IteratorBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {} : BaseBuiltinsFromDSLAssembler(state) {}
// Returns object[Symbol.iterator]. // Returns object[Symbol.iterator].
TNode<Object> GetIteratorMethod(Node* context, Node* object); TNode<Object> GetIteratorMethod(Node* context, Node* object);
@ -34,10 +34,16 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
// iterator result. // iterator result.
// `fast_iterator_result_map` refers to the map for the JSIteratorResult // `fast_iterator_result_map` refers to the map for the JSIteratorResult
// object, loaded from the native context. // object, loaded from the native context.
Node* IteratorStep(Node* context, const IteratorRecord& iterator, TNode<Object> IteratorStep(Node* context, const IteratorRecord& iterator,
Label* if_done, Node* fast_iterator_result_map = nullptr, Label* if_done,
Label* if_exception = nullptr, Node* fast_iterator_result_map = nullptr,
Variable* exception = nullptr); Label* if_exception = nullptr,
Variable* exception = nullptr);
TNode<Object> IteratorStep(Node* context, const IteratorRecord& iterator,
Node* fast_iterator_result_map, Label* if_done) {
return IteratorStep(context, iterator, if_done, fast_iterator_result_map);
}
// https://tc39.github.io/ecma262/#sec-iteratorvalue // https://tc39.github.io/ecma262/#sec-iteratorvalue
// Return the `value` field from an iterator. // Return the `value` field from an iterator.
@ -50,7 +56,8 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
// https://tc39.github.io/ecma262/#sec-iteratorclose // https://tc39.github.io/ecma262/#sec-iteratorclose
void IteratorCloseOnException(Node* context, const IteratorRecord& iterator, void IteratorCloseOnException(Node* context, const IteratorRecord& iterator,
Label* if_exception, Variable* exception); Label* if_exception = nullptr,
Variable* exception = nullptr);
void IteratorCloseOnException(Node* context, const IteratorRecord& iterator, void IteratorCloseOnException(Node* context, const IteratorRecord& iterator,
Variable* exception); Variable* exception);

View File

@ -5,16 +5,16 @@
#ifndef V8_BUILTINS_BUILTINS_PROMISE_GEN_H_ #ifndef V8_BUILTINS_BUILTINS_PROMISE_GEN_H_
#define V8_BUILTINS_BUILTINS_PROMISE_GEN_H_ #define V8_BUILTINS_BUILTINS_PROMISE_GEN_H_
#include "src/code-stub-assembler.h"
#include "src/contexts.h" #include "src/contexts.h"
#include "src/objects/promise.h" #include "src/objects/promise.h"
#include "torque-generated/builtins-base-from-dsl-gen.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
typedef compiler::CodeAssemblerState CodeAssemblerState; typedef compiler::CodeAssemblerState CodeAssemblerState;
class PromiseBuiltinsAssembler : public CodeStubAssembler { class PromiseBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
public: public:
enum PromiseResolvingFunctionContextSlot { enum PromiseResolvingFunctionContextSlot {
// The promise which resolve/reject callbacks fulfill. // The promise which resolve/reject callbacks fulfill.
@ -70,7 +70,7 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler {
}; };
explicit PromiseBuiltinsAssembler(compiler::CodeAssemblerState* state) explicit PromiseBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {} : BaseBuiltinsFromDSLAssembler(state) {}
// These allocate and initialize a promise with pending state and // These allocate and initialize a promise with pending state and
// undefined fields. // undefined fields.
// //

28
src/builtins/iterator.tq Normal file
View File

@ -0,0 +1,28 @@
// Copyright 2018 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.
module iterator {
extern macro GetIteratorMethod(implicit context: Context)(Object): Object;
extern macro GetIterator(implicit context: Context)(Object): IteratorRecord;
extern macro IteratorStep(implicit context: Context)(IteratorRecord): Object
labels Done;
extern macro IteratorStep(implicit context: Context)(IteratorRecord, Map):
Object
labels Done;
extern macro IteratorValue(implicit context: Context)(Object): Object;
extern macro IteratorValue(implicit context: Context)(Object, Map): Object;
extern macro IteratorCloseOnException(implicit context: Context)(
IteratorRecord);
extern macro IterableToList(implicit context: Context)(
Object, Object): JSArray;
extern builtin IterableToListMayPreserveHoles(implicit context: Context)(
Object, Object);
extern builtin IterableToListWithSymbolLookup(implicit context: Context)(
Object);
}

View File

@ -93,17 +93,6 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(V) \ HEAP_MUTABLE_IMMOVABLE_OBJECT_LIST(V) \
HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(V) HEAP_IMMUTABLE_IMMOVABLE_OBJECT_LIST(V)
// Returned from IteratorBuiltinsAssembler::GetIterator(). Struct is declared
// here to simplify use in other generated builtins.
struct IteratorRecord {
public:
// iteratorRecord.[[Iterator]]
compiler::TNode<JSReceiver> object;
// iteratorRecord.[[NextMethod]]
compiler::TNode<Object> next;
};
#ifdef DEBUG #ifdef DEBUG
#define CSA_CHECK(csa, x) \ #define CSA_CHECK(csa, x) \
(csa)->Check( \ (csa)->Check( \

View File

@ -642,3 +642,29 @@ module test {
} }
} }
} }
// Until we fully support namespaces, put the test for iterators in the
// iterator module so that the macros and builtins are found.
module iterator {
// This test doesn't actually test the functionality of iterators,
// it's only purpose is to make sure tha the CSA macros in the
// IteratorBuiltinsAssembler match the signatures provided in
// iterator.tq.
macro TestIterator(implicit context: Context)(o: Object, map: Map) {
try {
const t1: Object = GetIteratorMethod(o);
const t2: IteratorRecord = GetIterator(o);
const t3: Object = IteratorStep(t2) otherwise Fail;
const t4: Object = IteratorStep(t2, map) otherwise Fail;
const t5: Object = IteratorValue(t4);
const t6: Object = IteratorValue(t4, map);
IteratorCloseOnException(t2);
const t7: JSArray = IterableToList(t1, t1);
}
label Fail {}
}
}