Commit 2e3ba516 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

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: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57192}
parent 77d65f9a
......@@ -929,6 +929,7 @@ torque_files = [
"src/builtins/array-unshift.tq",
"src/builtins/typed-array.tq",
"src/builtins/data-view.tq",
"src/builtins/iterator.tq",
"test/torque/test-torque.tq",
"third_party/v8/builtins/array-sort.tq",
]
......@@ -936,6 +937,7 @@ torque_files = [
torque_modules = [
"base",
"array",
"iterator",
"typed-array",
"data-view",
"test",
......
......@@ -1190,3 +1190,13 @@ extern macro TryIntPtrAdd(intptr, intptr): intptr
extern builtin ObjectToString(Context, Object): Object;
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;
}
......@@ -1847,10 +1847,10 @@ TF_BUILTIN(ArrayPrototypeFindIndex, ArrayBuiltinsAssembler) {
MissingPropertyMode::kUseUndefined, ForEachDirection::kForward);
}
class ArrayPopulatorAssembler : public CodeStubAssembler {
class ArrayPopulatorAssembler : public BaseBuiltinsFromDSLAssembler {
public:
explicit ArrayPopulatorAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
: BaseBuiltinsFromDSLAssembler(state) {}
TNode<Object> ConstructArrayLike(TNode<Context> context,
TNode<Object> receiver) {
......@@ -2008,8 +2008,8 @@ TF_BUILTIN(ArrayFrom, ArrayPopulatorAssembler) {
BIND(&loop);
{
// Loop while iterator is not done.
TNode<Object> next = CAST(iterator_assembler.IteratorStep(
context, iterator_record, &loop_done, fast_iterator_result_map));
TNode<Object> next = iterator_assembler.IteratorStep(
context, iterator_record, &loop_done, fast_iterator_result_map);
TVARIABLE(Object, value,
CAST(iterator_assembler.IteratorValue(
context, next, fast_iterator_result_map)));
......
......@@ -11,6 +11,7 @@
#include "src/heap/factory-inl.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/js-collection.h"
#include "torque-generated/builtins-base-from-dsl-gen.h"
namespace v8 {
namespace internal {
......@@ -18,10 +19,10 @@ namespace internal {
template <class T>
using TVariable = compiler::TypedCodeAssemblerVariable<T>;
class BaseCollectionsAssembler : public CodeStubAssembler {
class BaseCollectionsAssembler : public BaseBuiltinsFromDSLAssembler {
public:
explicit BaseCollectionsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
: BaseBuiltinsFromDSLAssembler(state) {}
virtual ~BaseCollectionsAssembler() = default;
......@@ -328,8 +329,8 @@ void BaseCollectionsAssembler::AddConstructorEntriesFromIterable(
Goto(&loop);
BIND(&loop);
{
TNode<Object> next = CAST(iterator_assembler.IteratorStep(
context, iterator, &exit, fast_iterator_result_map));
TNode<Object> next = iterator_assembler.IteratorStep(
context, iterator, &exit, fast_iterator_result_map);
TNode<Object> next_value = CAST(iterator_assembler.IteratorValue(
context, next, fast_iterator_result_map));
AddConstructorEntry(variant, context, collection, add_func, next_value,
......
......@@ -11,10 +11,13 @@
#include "src/builtins/builtins.h"
#include "src/code-stub-assembler.h"
#include "src/heap/factory-inl.h"
#include "torque-generated/builtins-base-from-dsl-gen.h"
namespace v8 {
namespace internal {
typedef BaseBuiltinsFromDSLAssembler::IteratorRecord IteratorRecord;
using compiler::Node;
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* fast_iterator_result_map, Label* if_exception, Variable* exception) {
DCHECK_NOT_NULL(if_done);
......@@ -124,7 +127,7 @@ Node* IteratorBuiltinsAssembler::IteratorStep(
}
BIND(&return_result);
return result;
return UncheckedCast<Object>(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
// algorithm does not include redundant steps which are never reachable from
// the spec IteratorClose algorithm.
DCHECK_NOT_NULL(if_exception);
DCHECK_NOT_NULL(exception);
DCHECK((if_exception != nullptr && exception != nullptr) ||
IsExceptionHandlerActive());
CSA_ASSERT(this, IsNotTheHole(exception->value()));
CSA_ASSERT(this, IsJSReceiver(iterator.object));
......@@ -216,7 +219,7 @@ TNode<JSArray> IteratorBuiltinsAssembler::IterableToList(
BIND(&loop_start);
{
// 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
// i. Let nextValue be ? IteratorValue(next).
TNode<Object> next_value = CAST(IteratorValue(context, next));
......
......@@ -5,17 +5,17 @@
#ifndef 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 internal {
using compiler::Node;
class IteratorBuiltinsAssembler : public CodeStubAssembler {
class IteratorBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
public:
explicit IteratorBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
: BaseBuiltinsFromDSLAssembler(state) {}
// Returns object[Symbol.iterator].
TNode<Object> GetIteratorMethod(Node* context, Node* object);
......@@ -34,10 +34,16 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
// iterator result.
// `fast_iterator_result_map` refers to the map for the JSIteratorResult
// object, loaded from the native context.
Node* IteratorStep(Node* context, const IteratorRecord& iterator,
Label* if_done, Node* fast_iterator_result_map = nullptr,
Label* if_exception = nullptr,
Variable* exception = nullptr);
TNode<Object> IteratorStep(Node* context, const IteratorRecord& iterator,
Label* if_done,
Node* fast_iterator_result_map = 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
// Return the `value` field from an iterator.
......@@ -50,7 +56,8 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
// https://tc39.github.io/ecma262/#sec-iteratorclose
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,
Variable* exception);
......
......@@ -5,16 +5,16 @@
#ifndef 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/objects/promise.h"
#include "torque-generated/builtins-base-from-dsl-gen.h"
namespace v8 {
namespace internal {
typedef compiler::CodeAssemblerState CodeAssemblerState;
class PromiseBuiltinsAssembler : public CodeStubAssembler {
class PromiseBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
public:
enum PromiseResolvingFunctionContextSlot {
// The promise which resolve/reject callbacks fulfill.
......@@ -70,7 +70,7 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler {
};
explicit PromiseBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
: BaseBuiltinsFromDSLAssembler(state) {}
// These allocate and initialize a promise with pending state and
// undefined fields.
//
......
// 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);
}
......@@ -93,17 +93,6 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
HEAP_MUTABLE_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
#define CSA_CHECK(csa, x) \
(csa)->Check( \
......
......@@ -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 {}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment