Commit 163b5d70 authored by Michael Achenbach's avatar Michael Achenbach Committed by Commit Bot

Revert "[esnext] load `iterator.next` only once at beginning of iteration"

This reverts commit bf4cc9ee.

Reason for revert: Breaks windows with msvc and linux with gcc
https://build.chromium.org/p/client.v8/builders/V8%20Win64%20-%20msvc/builds/841
https://build.chromium.org/p/client.v8/builders/V8%20Linux%20gcc%204.8/builds/17265

Original change's description:
> [esnext] load `iterator.next` only once at beginning of iteration
> 
> https://github.com/tc39/ecma262/pull/988 gained concensus during the
> september 2017 TC39 meetings. This moves the load of the "next" method
> to the very beginning of the iteration protocol, rather than during
> each iteration step.
> 
> This impacts:
> 
> - yield*
> - for-of loops
> - spread arguments
> - array spreads
> 
> In the v8 implementation, this also affects async iteration versions of
> these things (the sole exception being the Async-From-Sync iterator,
> which requires a few more changes to work with this, likely done in a
> followup patch).
> 
> This change introduces a new AST node, ResolvedProperty, which can be used
> as a callee by Call nodes to produce the same bytecode as Property calls,
> without observably re-loading the property. This is used in several
> AST-desugarings involving the iteration protocol.
> 
> BUG=v8:6861, v8:5699
> R=​rmcilroy@chromium.org, neis@chromium.org, adamk@chromium.org
> 
> Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
> Change-Id: Ib81106a0182687fc5efea0bc32302ad06376773b
> Reviewed-on: https://chromium-review.googlesource.com/687997
> Commit-Queue: Caitlin Potter <caitp@igalia.com>
> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
> Reviewed-by: Adam Klein <adamk@chromium.org>
> Reviewed-by: Georg Neis <neis@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#50452}

TBR=rmcilroy@chromium.org,adamk@chromium.org,neis@chromium.org,caitp@igalia.com,caitp@chromium.org

Change-Id: I1797c0d596dfd6850d6f0f505f591a7a990dd1f1
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: v8:6861, v8:5699
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/857616Reviewed-by: 's avatarMichael Achenbach <machenbach@chromium.org>
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50454}
parent 5c56e27d
......@@ -195,11 +195,6 @@ void AstNumberingVisitor::VisitProperty(Property* node) {
Visit(node->obj());
}
void AstNumberingVisitor::VisitResolvedProperty(ResolvedProperty* node) {
Visit(node->object());
Visit(node->property());
}
void AstNumberingVisitor::VisitAssignment(Assignment* node) {
Visit(node->target());
Visit(node->value());
......@@ -256,7 +251,6 @@ void AstNumberingVisitor::VisitForInStatement(ForInStatement* node) {
void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
Visit(node->assign_iterator()); // Not part of loop.
Visit(node->assign_next());
node->set_first_suspend_id(suspend_count_);
Visit(node->next_result());
Visit(node->result_done());
......
......@@ -392,14 +392,6 @@ void AstTraversalVisitor<Subclass>::VisitProperty(Property* expr) {
RECURSE_EXPRESSION(Visit(expr->key()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitResolvedProperty(
ResolvedProperty* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(VisitVariableProxy(expr->object()));
RECURSE_EXPRESSION(VisitVariableProxy(expr->property()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitCall(Call* expr) {
PROCESS_EXPRESSION(expr);
......
......@@ -805,10 +805,6 @@ Call::CallType Call::GetCallType() const {
}
}
if (expression()->IsResolvedProperty()) {
return RESOLVED_PROPERTY_CALL;
}
return OTHER_CALL;
}
......
......@@ -94,7 +94,6 @@ namespace internal {
V(Literal) \
V(NativeFunctionLiteral) \
V(Property) \
V(ResolvedProperty) \
V(RewritableExpression) \
V(Spread) \
V(SuperCallReference) \
......@@ -591,13 +590,11 @@ class ForInStatement final : public ForEachStatement {
class ForOfStatement final : public ForEachStatement {
public:
void Initialize(Statement* body, Variable* iterator,
Expression* assign_iterator, Expression* assign_next,
Expression* next_result, Expression* result_done,
Expression* assign_each) {
Expression* assign_iterator, Expression* next_result,
Expression* result_done, Expression* assign_each) {
ForEachStatement::Initialize(body);
iterator_ = iterator;
assign_iterator_ = assign_iterator;
assign_next_ = assign_next;
next_result_ = next_result;
result_done_ = result_done;
assign_each_ = assign_each;
......@@ -612,9 +609,6 @@ class ForOfStatement final : public ForEachStatement {
return assign_iterator_;
}
// iteratorRecord.next = iterator.next
Expression* assign_next() const { return assign_next_; }
// result = iterator.next() // with type check
Expression* next_result() const {
return next_result_;
......@@ -630,12 +624,6 @@ class ForOfStatement final : public ForEachStatement {
return assign_each_;
}
void set_assign_iterator(Expression* e) { assign_iterator_ = e; }
void set_assign_next(Expression* e) { assign_next_ = e; }
void set_next_result(Expression* e) { next_result_ = e; }
void set_result_done(Expression* e) { result_done_ = e; }
void set_assign_each(Expression* e) { assign_each_ = e; }
private:
friend class AstNodeFactory;
......@@ -649,7 +637,6 @@ class ForOfStatement final : public ForEachStatement {
Variable* iterator_;
Expression* assign_iterator_;
Expression* assign_next_;
Expression* next_result_;
Expression* result_done_;
Expression* assign_each_;
......@@ -1620,25 +1607,6 @@ class Property final : public Expression {
Expression* key_;
};
// ResolvedProperty pairs a receiver field with a value field. It allows Call
// to support arbitrary receivers while still taking advantage of TypeFeedback.
class ResolvedProperty final : public Expression {
public:
VariableProxy* object() const { return object_; }
VariableProxy* property() const { return property_; }
void set_object(VariableProxy* e) { object_ = e; }
void set_property(VariableProxy* e) { property_ = e; }
private:
friend class AstNodeFactory;
ResolvedProperty(VariableProxy* obj, VariableProxy* property, int pos)
: Expression(pos, kResolvedProperty), object_(obj), property_(property) {}
VariableProxy* object_;
VariableProxy* property_;
};
class Call final : public Expression {
public:
......@@ -1665,7 +1633,6 @@ class Call final : public Expression {
NAMED_SUPER_PROPERTY_CALL,
KEYED_SUPER_PROPERTY_CALL,
SUPER_CALL,
RESOLVED_PROPERTY_CALL,
OTHER_CALL
};
......@@ -2137,6 +2104,7 @@ class YieldStar final : public Suspend {
// - One for awaiting the iterator result yielded by the delegated iterator
// (await_delegated_iterator_output_suspend_id)
int await_iterator_close_suspend_id() const {
DCHECK_NE(-1, await_iterator_close_suspend_id_);
return await_iterator_close_suspend_id_;
}
void set_await_iterator_close_suspend_id(int id) {
......@@ -2144,6 +2112,7 @@ class YieldStar final : public Suspend {
}
int await_delegated_iterator_output_suspend_id() const {
DCHECK_NE(-1, await_delegated_iterator_output_suspend_id_);
return await_delegated_iterator_output_suspend_id_;
}
void set_await_delegated_iterator_output_suspend_id(int id) {
......@@ -3028,12 +2997,6 @@ class AstNodeFactory final BASE_EMBEDDED {
return new (zone_) Property(obj, key, pos);
}
ResolvedProperty* NewResolvedProperty(VariableProxy* obj,
VariableProxy* property,
int pos = kNoSourcePosition) {
return new (zone_) ResolvedProperty(obj, property, pos);
}
Call* NewCall(Expression* expression, ZoneList<Expression*>* arguments,
int pos, Call::PossiblyEval possibly_eval = Call::NOT_EVAL) {
return new (zone_) Call(expression, arguments, pos, possibly_eval);
......
......@@ -326,7 +326,6 @@ void CallPrinter::VisitProperty(Property* node) {
}
}
void CallPrinter::VisitResolvedProperty(ResolvedProperty* node) {}
void CallPrinter::VisitCall(Call* node) {
bool was_found = false;
......@@ -1250,14 +1249,6 @@ void AstPrinter::VisitProperty(Property* node) {
}
}
void AstPrinter::VisitResolvedProperty(ResolvedProperty* node) {
EmbeddedVector<char, 128> buf;
SNPrintF(buf, "RESOLVED-PROPERTY");
IndentedScope indent(this, buf.start(), node->position());
PrintIndentedVisit("RECEIVER", node->object());
PrintIndentedVisit("PROPERTY", node->property());
}
void AstPrinter::VisitCall(Call* node) {
EmbeddedVector<char, 128> buf;
......
......@@ -232,9 +232,10 @@ void BaseCollectionsAssembler::AddConstructorEntriesFromIterable(
TNode<Object> add_func = GetAddFunction(variant, context, collection);
IteratorBuiltinsAssembler iterator_assembler(this->state());
IteratorRecord iterator = iterator_assembler.GetIterator(context, iterable);
TNode<Object> iterator =
CAST(iterator_assembler.GetIterator(context, iterable));
CSA_ASSERT(this, Word32BinaryNot(IsUndefined(iterator.object)));
CSA_ASSERT(this, Word32BinaryNot(IsUndefined(iterator)));
TNode<Object> fast_iterator_result_map =
LoadContextElement(native_context, Context::ITERATOR_RESULT_MAP_INDEX);
......
......@@ -11,8 +11,7 @@ namespace internal {
using compiler::Node;
IteratorRecord IteratorBuiltinsAssembler::GetIterator(Node* context,
Node* object,
Node* IteratorBuiltinsAssembler::GetIterator(Node* context, Node* object,
Label* if_exception,
Variable* exception) {
Node* method = GetProperty(context, object, factory()->iterator_symbol());
......@@ -22,9 +21,9 @@ IteratorRecord IteratorBuiltinsAssembler::GetIterator(Node* context,
Node* iterator = CallJS(callable, context, method, object);
GotoIfException(iterator, if_exception, exception);
Label get_next(this), if_notobject(this, Label::kDeferred);
Label done(this), if_notobject(this, Label::kDeferred);
GotoIf(TaggedIsSmi(iterator), &if_notobject);
Branch(IsJSReceiver(iterator), &get_next, &if_notobject);
Branch(IsJSReceiver(iterator), &done, &if_notobject);
BIND(&if_notobject);
{
......@@ -35,21 +34,24 @@ IteratorRecord IteratorBuiltinsAssembler::GetIterator(Node* context,
Unreachable();
}
BIND(&get_next);
Node* const next = GetProperty(context, iterator, factory()->next_string());
GotoIfException(next, if_exception, exception);
return IteratorRecord{TNode<JSReceiver>::UncheckedCast(iterator),
TNode<Object>::UncheckedCast(next)};
BIND(&done);
return iterator;
}
Node* IteratorBuiltinsAssembler::IteratorStep(
Node* context, const IteratorRecord& iterator, Label* if_done,
Node* fast_iterator_result_map, Label* if_exception, Variable* exception) {
Node* IteratorBuiltinsAssembler::IteratorStep(Node* context, Node* iterator,
Label* if_done,
Node* fast_iterator_result_map,
Label* if_exception,
Variable* exception) {
DCHECK_NOT_NULL(if_done);
// IteratorNext
Node* next_method = GetProperty(context, iterator, factory()->next_string());
GotoIfException(next_method, if_exception, exception);
// 1. a. Let result be ? Invoke(iterator, "next", « »).
Callable callable = CodeFactory::Call(isolate());
Node* result = CallJS(callable, context, iterator.next, iterator.object);
Node* result = CallJS(callable, context, next_method, iterator);
GotoIfException(result, if_exception, exception);
// 3. If Type(result) is not Object, throw a TypeError exception.
......@@ -127,8 +129,9 @@ Node* IteratorBuiltinsAssembler::IteratorValue(Node* context, Node* result,
return var_value.value();
}
void IteratorBuiltinsAssembler::IteratorCloseOnException(
Node* context, const IteratorRecord& iterator, Label* if_exception,
void IteratorBuiltinsAssembler::IteratorCloseOnException(Node* context,
Node* iterator,
Label* if_exception,
Variable* exception) {
// Perform ES #sec-iteratorclose when an exception occurs. This simpler
// algorithm does not include redundant steps which are never reachable from
......@@ -136,11 +139,10 @@ void IteratorBuiltinsAssembler::IteratorCloseOnException(
DCHECK_NOT_NULL(if_exception);
DCHECK_NOT_NULL(exception);
CSA_ASSERT(this, IsNotTheHole(exception->value()));
CSA_ASSERT(this, IsJSReceiver(iterator.object));
CSA_ASSERT(this, IsJSReceiver(iterator));
// Let return be ? GetMethod(iterator, "return").
Node* method =
GetProperty(context, iterator.object, factory()->return_string());
Node* method = GetProperty(context, iterator, factory()->return_string());
GotoIfException(method, if_exception, exception);
// If return is undefined, return Completion(completion).
......@@ -150,7 +152,7 @@ void IteratorBuiltinsAssembler::IteratorCloseOnException(
// Let innerResult be Call(return, iterator, « »).
// If an exception occurs, the original exception remains bound
Node* inner_result =
CallJS(CodeFactory::Call(isolate()), context, method, iterator.object);
CallJS(CodeFactory::Call(isolate()), context, method, iterator);
GotoIfException(inner_result, if_exception, nullptr);
// (If completion.[[Type]] is throw) return Completion(completion).
......@@ -158,8 +160,9 @@ void IteratorBuiltinsAssembler::IteratorCloseOnException(
}
}
void IteratorBuiltinsAssembler::IteratorCloseOnException(
Node* context, const IteratorRecord& iterator, Variable* exception) {
void IteratorBuiltinsAssembler::IteratorCloseOnException(Node* context,
Node* iterator,
Variable* exception) {
Label rethrow(this, Label::kDeferred);
IteratorCloseOnException(context, iterator, &rethrow, exception);
......
......@@ -19,8 +19,7 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
// https://tc39.github.io/ecma262/#sec-getiterator --- never used for
// @@asyncIterator.
IteratorRecord GetIterator(Node* context, Node* object,
Label* if_exception = nullptr,
Node* GetIterator(Node* context, Node* object, Label* if_exception = nullptr,
Variable* exception = nullptr);
// https://tc39.github.io/ecma262/#sec-iteratorstep
......@@ -28,8 +27,8 @@ 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,
Node* IteratorStep(Node* context, Node* iterator, Label* if_done,
Node* fast_iterator_result_map = nullptr,
Label* if_exception = nullptr,
Variable* exception = nullptr);
......@@ -43,9 +42,9 @@ class IteratorBuiltinsAssembler : public CodeStubAssembler {
Variable* exception = nullptr);
// https://tc39.github.io/ecma262/#sec-iteratorclose
void IteratorCloseOnException(Node* context, const IteratorRecord& iterator,
void IteratorCloseOnException(Node* context, Node* iterator,
Label* if_exception, Variable* exception);
void IteratorCloseOnException(Node* context, const IteratorRecord& iterator,
void IteratorCloseOnException(Node* context, Node* iterator,
Variable* exception);
};
......
......@@ -1807,9 +1807,8 @@ TF_BUILTIN(PerformNativePromiseThen, PromiseBuiltinsAssembler) {
}
Node* PromiseBuiltinsAssembler::PerformPromiseAll(
Node* context, Node* constructor, Node* capability,
const IteratorRecord& iterator, Label* if_exception,
Variable* var_exception) {
Node* context, Node* constructor, Node* capability, Node* iterator,
Label* if_exception, Variable* var_exception) {
IteratorBuiltinsAssembler iter_assembler(state());
Label close_iterator(this);
......@@ -2015,7 +2014,7 @@ TF_BUILTIN(PromiseAll, PromiseBuiltinsAssembler) {
// Let iterator be GetIterator(iterable).
// IfAbruptRejectPromise(iterator, promiseCapability).
Node* const iterable = Parameter(Descriptor::kIterable);
IteratorRecord iterator = iter_assembler.GetIterator(
Node* const iterator = iter_assembler.GetIterator(
context, iterable, &reject_promise, &var_exception);
// Let result be PerformPromiseAll(iteratorRecord, C, promiseCapability).
......@@ -2152,7 +2151,7 @@ TF_BUILTIN(PromiseRace, PromiseBuiltinsAssembler) {
// Let iterator be GetIterator(iterable).
// IfAbruptRejectPromise(iterator, promiseCapability).
Node* const iterable = Parameter(Descriptor::kIterable);
IteratorRecord iterator = iter_assembler.GetIterator(
Node* const iterator = iter_assembler.GetIterator(
context, iterable, &reject_promise, &var_exception);
// Let result be PerformPromiseRace(iteratorRecord, C, promiseCapability).
......
......@@ -157,7 +157,7 @@ class PromiseBuiltinsAssembler : public CodeStubAssembler {
Node* CreateThrowerFunction(Node* reason, Node* native_context);
Node* PerformPromiseAll(Node* context, Node* constructor, Node* capability,
const IteratorRecord& record, Label* if_exception,
Node* iterator, Label* if_exception,
Variable* var_exception);
Node* IncrementSmiCell(Node* cell, Label* if_overflow = nullptr);
......
......@@ -71,17 +71,6 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
promise_default_resolve_handler_symbol, \
PromiseDefaultResolveHandlerSymbol)
// 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;
};
// Provides JavaScript-specific "macro-assembler" functionality on top of the
// CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler,
// it's possible to add JavaScript-specific useful CodeAssembler "macros"
......
This diff is collapsed.
......@@ -151,24 +151,9 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void BuildAwait(int suspend_id);
void BuildGetIterator(Expression* iterable, IteratorType hint);
// Create an IteratorRecord with pre-allocated registers holding the next
// method and iterator object.
IteratorRecord BuildGetIteratorRecord(Expression* iterable,
Register iterator_next,
Register iterator_object,
IteratorType hint);
// Create an IteratorRecord allocating new registers to hold the next method
// and iterator object.
IteratorRecord BuildGetIteratorRecord(Expression* iterable,
IteratorType hint);
void BuildIteratorNext(const IteratorRecord& iterator, Register next_result);
void BuildIteratorClose(const IteratorRecord& iterator, int suspend_id = -1);
void BuildCallIteratorMethod(Register iterator, const AstRawString* method,
RegisterList receiver_and_args,
BytecodeLabel* if_called,
BytecodeLabels* if_notcalled);
void BuildArrayLiteralSpread(Spread* spread, Register array);
......
......@@ -1889,11 +1889,13 @@ void Parser::DeclareFunctionNameVar(const AstRawString* function_name,
// !%_IsJSReceiver(result = Await(iterator.next())) &&
// %ThrowIteratorResultNotAnObject(result)
// [endif]
Expression* Parser::BuildIteratorNextResult(VariableProxy* iterator,
VariableProxy* next,
Expression* Parser::BuildIteratorNextResult(Expression* iterator,
Variable* result, IteratorType type,
int pos) {
Expression* next_property = factory()->NewResolvedProperty(iterator, next);
Expression* next_literal = factory()->NewStringLiteral(
ast_value_factory()->next_string(), kNoSourcePosition);
Expression* next_property =
factory()->NewProperty(iterator, next_literal, kNoSourcePosition);
ZoneList<Expression*>* next_arguments =
new (zone()) ZoneList<Expression*>(0, zone());
Expression* next_call =
......@@ -2096,7 +2098,6 @@ Statement* Parser::InitializeForOfStatement(
auto avfactory = ast_value_factory();
Variable* iterator = NewTemporary(avfactory->dot_iterator_string());
Variable* next = NewTemporary(avfactory->empty_string());
Variable* result = NewTemporary(avfactory->dot_result_string());
Variable* completion = NewTemporary(avfactory->empty_string());
......@@ -2109,17 +2110,6 @@ Statement* Parser::InitializeForOfStatement(
iterable->position());
}
Expression* assign_next;
{
assign_next = factory()->NewAssignment(
Token::ASSIGN, factory()->NewVariableProxy(next),
factory()->NewProperty(factory()->NewVariableProxy(iterator),
factory()->NewStringLiteral(
avfactory->next_string(), kNoSourcePosition),
kNoSourcePosition),
kNoSourcePosition);
}
// [if (IteratorType == kNormal)]
// !%_IsJSReceiver(result = iterator.next()) &&
// %ThrowIteratorResultNotAnObject(result)
......@@ -2129,10 +2119,9 @@ Statement* Parser::InitializeForOfStatement(
// [endif]
Expression* next_result;
{
VariableProxy* iterator_proxy = factory()->NewVariableProxy(iterator);
VariableProxy* next_proxy = factory()->NewVariableProxy(next);
next_result = BuildIteratorNextResult(iterator_proxy, next_proxy, result,
type, next_result_pos);
Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
next_result =
BuildIteratorNextResult(iterator_proxy, result, type, next_result_pos);
}
// result.done
......@@ -2202,8 +2191,8 @@ Statement* Parser::InitializeForOfStatement(
body = block;
}
for_of->Initialize(body, iterator, assign_iterator, assign_next, next_result,
result_done, assign_each);
for_of->Initialize(body, iterator, assign_iterator, next_result, result_done,
assign_each);
return finalize ? FinalizeForOfStatement(for_of, completion, type, nopos)
: for_of;
}
......
......@@ -402,14 +402,13 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Expression* RewriteDestructuringAssignment(Assignment* assignment);
// [if (IteratorType == kAsync)]
// !%_IsJSReceiver(result = Await(next.[[Call]](iterator, « »)) &&
// !%_IsJSReceiver(result = Await(iterator.next()) &&
// %ThrowIteratorResultNotAnObject(result)
// [else]
// !%_IsJSReceiver(result = next.[[Call]](iterator, « »)) &&
// !%_IsJSReceiver(result = iterator.next()) &&
// %ThrowIteratorResultNotAnObject(result)
// [endif]
Expression* BuildIteratorNextResult(VariableProxy* iterator,
VariableProxy* next, Variable* result,
Expression* BuildIteratorNextResult(Expression* iterator, Variable* result,
IteratorType type, int pos);
// Initialize the components of a for-in / for-of statement.
......
......@@ -445,11 +445,6 @@ void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
auto iterator = CreateTempVar(factory()->NewGetIterator(
factory()->NewVariableProxy(temp), current_value_, IteratorType::kNormal,
current_value_->position()));
auto next = CreateTempVar(factory()->NewProperty(
factory()->NewVariableProxy(iterator),
factory()->NewStringLiteral(ast_value_factory()->next_string(),
kNoSourcePosition),
kNoSourcePosition));
auto done =
CreateTempVar(factory()->NewBooleanLiteral(false, kNoSourcePosition));
auto result = CreateTempVar();
......@@ -530,8 +525,7 @@ void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
next_block->statements()->Add(
factory()->NewExpressionStatement(
parser_->BuildIteratorNextResult(
factory()->NewVariableProxy(iterator),
factory()->NewVariableProxy(next), result,
factory()->NewVariableProxy(iterator), result,
IteratorType::kNormal, kNoSourcePosition),
kNoSourcePosition),
zone());
......@@ -605,7 +599,6 @@ void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
// result = IteratorNext(iterator);
Statement* get_next = factory()->NewExpressionStatement(
parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
factory()->NewVariableProxy(next),
result, IteratorType::kNormal, nopos),
nopos);
......@@ -763,7 +756,6 @@ NOT_A_PATTERN(ImportCallExpression)
NOT_A_PATTERN(Literal)
NOT_A_PATTERN(NativeFunctionLiteral)
NOT_A_PATTERN(RegExpLiteral)
NOT_A_PATTERN(ResolvedProperty)
NOT_A_PATTERN(ReturnStatement)
NOT_A_PATTERN(SloppyBlockFunctionStatement)
NOT_A_PATTERN(Spread)
......
......@@ -9,10 +9,10 @@ function testFunction() {
var arr = |_|[1];
var all = |_|[];
for (var |_|k in |_|arr) { all.|C|push(k); }
for (var |C|k of |_|arr) { all.|C|push(k); }
for (var |_|k of |_|arr) { all.|C|push(k); }
for (var |_|k in |_|obj) { all.|C|push(k); }
for (let |_|k in |_|arr) { all.|C|push(k); }
for (let |C|k of |_|arr) { all.|C|push(k); }
for (let |_|k of |_|arr) { all.|C|push(k); }
for (let |_|k in |_|obj) { all.|C|push(k); }
var iterable = |_|{
......@@ -28,9 +28,9 @@ function testFunction() {
};|R|
}
};
for (var |C|k of |_|iterable) { all.|C|push(k); }
for (var |_|k of |_|iterable) { all.|C|push(k); }
|_|iterable.i = 0;
for (let |C|k of |_|iterable) { all.|C|push(k); }
for (let |_|k of |_|iterable) { all.|C|push(k); }
|R|}
(anonymous) (expr.js:0:0)
......
......@@ -95,10 +95,10 @@ function testForLoop() {
|R|}
function testForOfLoop() {
for (var |C|k of |_|[]) {}
for (var |C|k of |_|[1]) |_|k;
for (var |_|k of |_|[]) {}
for (var |_|k of |_|[1]) |_|k;
var a = |_|[];
for (var |C|k of |_|a) {}
for (var |_|k of |_|a) {}
|R|}
function testForInLoop() {
......
......@@ -37,8 +37,6 @@
var r2 = testMax(1, 2);
// .next() is only loaded once during the iteration prologue (see
// https://github.com/tc39/ecma262/pull/988/ and v8:6861)
assertEquals(1, called);
assertEquals(3, called);
assertEquals(2, r2);
})();
......@@ -220,11 +220,13 @@ assertThrows('fold(sum, 0, unreachable({}))', TypeError);
assertThrows('fold(sum, 0, unreachable(false))', TypeError);
assertThrows('fold(sum, 0, unreachable(37))', TypeError);
// "next" is looked up only once during the iteration prologue (see
// https://github.com/tc39/ecma262/pull/988)
assertEquals(45, fold(sum, 0, remove_next_after(integers_until(10), 5)));
// "next" is looked up each time.
assertThrows('fold(sum, 0, remove_next_after(integers_until(10), 5))',
TypeError);
// It is not called at any other time.
assertEquals(45,
fold(sum, 0, remove_next_after(integers_until(10), 10)));
// It is not looked up too many times.
assertEquals(45,
fold(sum, 0, poison_next_after(integers_until(10), 10)));
......
......@@ -376,11 +376,6 @@ testSpreadCallsStrict();
a[3] = 4;
var called = 0;
// .next method is only accessed during iteration prologue (see
// https://github.com/tc39/ecma262/pull/988)
let ArrayIteratorPrototype = Array.prototype[Symbol.iterator]().__proto__;
let ArrayIteratorPrototypeNextDescriptor =
Object.getOwnPropertyDescriptor(ArrayIteratorPrototype, 'next');
Object.defineProperty(Array.prototype, 2, {
get: function() {
var ai = a[Symbol.iterator]();
......@@ -389,8 +384,7 @@ testSpreadCallsStrict();
get: function() {
called++;
return original_next;
},
configurable: true
}
});
return 3;
},
......@@ -398,10 +392,8 @@ testSpreadCallsStrict();
});
assertEquals(10, sum(...a));
assertEquals(0, called);
assertEquals(2, called);
Object.defineProperty(ArrayIteratorPrototype, 'next',
ArrayIteratorPrototypeNextDescriptor);
Object.defineProperty(Array.prototype, 2, {});
})();
......@@ -438,9 +430,9 @@ testSpreadCallsStrict();
countArgs(...a);
// .next method is only accessed during iteration prologue (see
// https://github.com/tc39/ecma262/pull/988)
assertEquals(1, called);
// should be called 4 times; 3 for the values, 1 for the final
// {value: undefined, done: true} pair
assertEquals(4, called);
})();
(function testArrayIteratorPrototypeModified() {
......
......@@ -48,9 +48,7 @@
var r2 = testArgumentsPoint(1, 2);
// .next() is only loaded once during the iteration prologue (see
// https://github.com/tc39/ecma262/pull/988/ and v8:6861)
assertEquals(1, called);
assertEquals(3, called);
assertInstanceof(r2, ArgumentsPoint);
assertInstanceof(r2, Point);
assertEquals(r2.x, 1);
......
......@@ -341,30 +341,16 @@ function TestTypedArray(constr, elementSize, typicalElement) {
// Modified %ArrayIteratorPrototype%.next() method is honoured (v8:5699)
const ArrayIteratorPrototype = Object.getPrototypeOf([][Symbol.iterator]());
const ArrayIteratorPrototypeNextDescriptor =
Object.getOwnPropertyDescriptor(ArrayIteratorPrototype, 'next');
const ArrayIteratorPrototypeNext = ArrayIteratorPrototype.next;
ArrayIteratorPrototype.next = function() {
return { done: true };
};
genArr = new constr([1, 2, 3]);
assertEquals(0, genArr.length);
ArrayIteratorPrototype.next = ArrayIteratorPrototypeNext;
// Modified %ArrayIteratorPrototype%.next() is only loaded during the iterator
// prologue.
let nextMethod = ArrayIteratorPrototypeNext;
let getNextCount = 0;
Object.defineProperty(ArrayIteratorPrototype, 'next', {
get() {
getNextCount++;
return nextMethod;
},
set(v) { nextMethod = v; },
configurable: true
});
// Modified %ArrayIteratorPrototype%.next() during iteration is honoured as
// well.
genArr = new constr(Object.defineProperty([1, , 3], 1, {
get() {
ArrayIteratorPrototype.next = function() {
......@@ -373,13 +359,9 @@ function TestTypedArray(constr, elementSize, typicalElement) {
return 2;
}
}));
Object.defineProperty(ArrayIteratorPrototype, 'next',
ArrayIteratorPrototypeNextDescriptor);
assertEquals(1, getNextCount);
assertEquals(3, genArr.length);
assertEquals(2, genArr.length);
assertEquals(1, genArr[0]);
assertEquals(2, genArr[1]);
assertEquals(3, genArr[2]);
ArrayIteratorPrototype.next = ArrayIteratorPrototypeNext;
}
......
......@@ -423,8 +423,19 @@
'built-ins/Proxy/ownKeys/return-duplicate-symbol-entries-throws': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=6861
'language/statements/for-of/iterator-next-reference': [FAIL],
'language/expressions/async-generator/named-yield-star-async-next': [FAIL],
'language/expressions/async-generator/yield-star-async-next': [FAIL],
'language/expressions/class/async-gen-method-yield-star-async-next': [FAIL],
'language/expressions/class/async-gen-method-static-yield-star-async-next': [FAIL],
'language/expressions/object/method-definition/async-gen-yield-star-async-next': [FAIL],
'language/statements/async-generator/yield-star-async-next': [FAIL],
'language/statements/class/async-gen-method-yield-star-async-next': [FAIL],
'language/statements/class/async-gen-method-static-yield-star-async-next': [FAIL],
'language/expressions/object/method-definition/async-gen-yield-star-sync-next': [FAIL],
'language/expressions/class/async-gen-method-static-yield-star-sync-next': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=6861
'language/expressions/async-generator/yield-star-sync-next': [FAIL],
'language/statements/class/async-gen-method-static-yield-star-sync-next': [FAIL],
'language/expressions/async-generator/named-yield-star-sync-next': [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