Commit b5843923 authored by Adam Klein's avatar Adam Klein Committed by Commit Bot

[generators] Remove generator_object_ member from Suspend AST node

Now that the BytecodeGenerator has a dedicated register holding
the generator object, BytecodeGenerator::VisitSuspend can
access the generator directly from that register. This reduces
by one the number of live registers at each suspend point.

Bug: v8:6351, v8:6460
Change-Id: I380a9d2bd8ca7eec6720e5392c1ca07dd0df0e2d
Reviewed-on: https://chromium-review.googlesource.com/522982
Commit-Queue: Adam Klein <adamk@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45710}
parent 218b4d30
......@@ -267,7 +267,6 @@ void AstExpressionRewriter::VisitAssignment(Assignment* node) {
void AstExpressionRewriter::VisitSuspend(Suspend* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, generator_object);
AST_REWRITE_PROPERTY(Expression, node, expression);
}
......
......@@ -246,7 +246,6 @@ void AstNumberingVisitor::VisitSuspend(Suspend* node) {
suspend_count_++;
IncrementNodeCount();
node->set_base_id(ReserveIdRange(Suspend::num_ids()));
Visit(node->generator_object());
Visit(node->expression());
}
......
......@@ -359,7 +359,6 @@ void AstTraversalVisitor<Subclass>::VisitAssignment(Assignment* expr) {
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitSuspend(Suspend* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->generator_object()));
RECURSE_EXPRESSION(Visit(expr->expression()));
}
......
......@@ -2512,7 +2512,6 @@ class Suspend final : public Expression {
// desugar yield*.
enum OnAbruptResume { kOnExceptionThrow, kOnExceptionRethrow, kNoControl };
Expression* generator_object() const { return generator_object_; }
Expression* expression() const { return expression_; }
OnAbruptResume on_abrupt_resume() const {
return OnAbruptResumeField::decode(bit_field_);
......@@ -2543,7 +2542,6 @@ class Suspend final : public Expression {
SuspendFlags::kAsyncGenerator;
}
void set_generator_object(Expression* e) { generator_object_ = e; }
void set_expression(Expression* e) { expression_ = e; }
void set_suspend_id(int id) { suspend_id_ = id; }
void set_suspend_type(SuspendFlags type) {
......@@ -2554,18 +2552,14 @@ class Suspend final : public Expression {
private:
friend class AstNodeFactory;
Suspend(Expression* generator_object, Expression* expression, int pos,
OnAbruptResume on_abrupt_resume, SuspendFlags flags)
: Expression(pos, kSuspend),
suspend_id_(-1),
generator_object_(generator_object),
expression_(expression) {
Suspend(Expression* expression, int pos, OnAbruptResume on_abrupt_resume,
SuspendFlags flags)
: Expression(pos, kSuspend), suspend_id_(-1), expression_(expression) {
bit_field_ |= OnAbruptResumeField::encode(on_abrupt_resume) |
FlagsField::encode(flags);
}
int suspend_id_;
Expression* generator_object_;
Expression* expression_;
class OnAbruptResumeField
......@@ -3555,12 +3549,11 @@ class AstNodeFactory final BASE_EMBEDDED {
return assign;
}
Suspend* NewSuspend(Expression* generator_object, Expression* expression,
int pos, Suspend::OnAbruptResume on_abrupt_resume,
Suspend* NewSuspend(Expression* expression, int pos,
Suspend::OnAbruptResume on_abrupt_resume,
SuspendFlags flags) {
if (!expression) expression = NewUndefinedLiteral(pos);
return new (zone_)
Suspend(generator_object, expression, pos, on_abrupt_resume, flags);
return new (zone_) Suspend(expression, pos, on_abrupt_resume, flags);
}
Throw* NewThrow(Expression* exception, int pos) {
......
......@@ -150,7 +150,6 @@ void ALAA::VisitObjectLiteral(ObjectLiteral* e) {
void ALAA::VisitArrayLiteral(ArrayLiteral* e) { VisitExpressions(e->values()); }
void ALAA::VisitSuspend(Suspend* stmt) {
Visit(stmt->generator_object());
Visit(stmt->expression());
}
......
......@@ -468,7 +468,6 @@ void AstTyper::VisitAssignment(Assignment* expr) {
}
void AstTyper::VisitSuspend(Suspend* expr) {
RECURSE(Visit(expr->generator_object()));
RECURSE(Visit(expr->expression()));
// We don't know anything about the result type.
......
......@@ -2521,7 +2521,7 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
}
}
void BytecodeGenerator::BuildGeneratorSuspend(Suspend* expr, Register generator,
void BytecodeGenerator::BuildGeneratorSuspend(Suspend* expr,
RegisterList registers_to_save) {
RegisterAllocationScope register_scope(this);
......@@ -2531,7 +2531,7 @@ void BytecodeGenerator::BuildGeneratorSuspend(Suspend* expr, Register generator,
// Save context, registers, and state. Then return.
builder()
->LoadLiteral(Smi::FromInt(expr->suspend_id()))
.SuspendGenerator(generator, registers_to_save, expr->flags());
.SuspendGenerator(generator_object_, registers_to_save, expr->flags());
if (expr->IsNonInitialAsyncGeneratorYield()) {
// AsyncGenerator yields (with the exception of the initial yield) delegate
......@@ -2541,7 +2541,7 @@ void BytecodeGenerator::BuildGeneratorSuspend(Suspend* expr, Register generator,
// AsyncGeneratorYield:
// perform AsyncGeneratorResolve(<generator>, <value>, false).
builder()
->MoveRegister(generator, args[0])
->MoveRegister(generator_object_, args[0])
.MoveRegister(value, args[1])
.LoadFalse()
.StoreAccumulatorInRegister(args[2])
......@@ -2553,7 +2553,7 @@ void BytecodeGenerator::BuildGeneratorSuspend(Suspend* expr, Register generator,
}
void BytecodeGenerator::BuildGeneratorResume(
Suspend* expr, Register generator, RegisterList registers_to_restore) {
Suspend* expr, RegisterList registers_to_restore) {
RegisterAllocationScope register_scope(this);
// Clobbers all registers.
......@@ -2575,13 +2575,13 @@ void BytecodeGenerator::BuildGeneratorResume(
? Runtime::kInlineAsyncGeneratorGetAwaitInputOrDebugPos
: Runtime::kInlineGeneratorGetInputOrDebugPos;
DCHECK(generator.is_valid());
builder()->CallRuntime(get_generator_input, generator);
builder()->CallRuntime(get_generator_input, generator_object_);
if (expr->on_abrupt_resume() != Suspend::kNoControl) {
builder()->StoreAccumulatorInRegister(input);
builder()->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator);
builder()->CallRuntime(Runtime::kInlineGeneratorGetResumeMode,
generator_object_);
// Now dispatch on resume mode.
STATIC_ASSERT(JSGeneratorObject::kNext + 1 == JSGeneratorObject::kReturn);
......@@ -2630,12 +2630,11 @@ void BytecodeGenerator::BuildGeneratorResume(
}
void BytecodeGenerator::VisitSuspend(Suspend* expr) {
Register generator = VisitForRegisterValue(expr->generator_object());
RegisterList registers(0, register_allocator()->next_register_index());
BuildGeneratorSuspend(expr, generator, registers);
BuildGeneratorSuspend(expr, registers);
builder()->Bind(generator_jump_table_, static_cast<int>(expr->suspend_id()));
// Upon resume, we continue here.
BuildGeneratorResume(expr, generator, registers);
BuildGeneratorResume(expr, registers);
}
void BytecodeGenerator::VisitThrow(Throw* expr) {
......
......@@ -136,10 +136,8 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void BuildNewLocalWithContext(Scope* scope);
void BuildGeneratorPrologue();
void BuildGeneratorSuspend(Suspend* expr, Register generator,
RegisterList registers_to_save);
void BuildGeneratorResume(Suspend* expr, Register generator,
RegisterList registers_to_restore);
void BuildGeneratorSuspend(Suspend* expr, RegisterList registers_to_save);
void BuildGeneratorResume(Suspend* expr, RegisterList registers_to_restore);
void VisitArgumentsObject(Variable* variable);
void VisitRestArgumentsArray(Variable* rest);
......
......@@ -1399,16 +1399,15 @@ class ParserBase {
}
inline SuspendExpressionT BuildSuspend(
ExpressionT generator, ExpressionT expr, int pos,
Suspend::OnAbruptResume on_abrupt_resume, SuspendFlags suspend_type) {
ExpressionT expr, int pos, Suspend::OnAbruptResume on_abrupt_resume,
SuspendFlags suspend_type) {
DCHECK_EQ(0,
static_cast<int>(suspend_type & ~SuspendFlags::kSuspendTypeMask));
if (V8_UNLIKELY(is_async_generator())) {
suspend_type = static_cast<SuspendFlags>(suspend_type |
SuspendFlags::kAsyncGenerator);
}
return factory()->NewSuspend(generator, expr, pos, on_abrupt_resume,
suspend_type);
return factory()->NewSuspend(expr, pos, on_abrupt_resume, suspend_type);
}
// Validation per ES6 object literals.
......@@ -2970,8 +2969,6 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression(
classifier()->RecordFormalParameterInitializerError(
scanner()->peek_location(), MessageTemplate::kYieldInParameter);
Expect(Token::YIELD, CHECK_OK);
ExpressionT generator_object =
factory()->NewVariableProxy(function_state_->generator_object_variable());
// The following initialization is necessary.
ExpressionT expression = impl()->EmptyExpression();
bool delegating = false; // yield*
......@@ -2999,7 +2996,7 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression(
}
if (delegating) {
return impl()->RewriteYieldStar(generator_object, expression, pos);
return impl()->RewriteYieldStar(expression, pos);
}
if (!is_async_generator()) {
......@@ -3010,9 +3007,8 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseYieldExpression(
// Hackily disambiguate o from o.next and o [Symbol.iterator]().
// TODO(verwaest): Come up with a better solution.
ExpressionT yield =
BuildSuspend(generator_object, expression, pos,
Suspend::kOnExceptionThrow, SuspendFlags::kYield);
ExpressionT yield = BuildSuspend(expression, pos, Suspend::kOnExceptionThrow,
SuspendFlags::kYield);
return yield;
}
......
......@@ -3177,17 +3177,12 @@ Variable* Parser::AsyncGeneratorAwaitVariable() {
}
Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) {
// We access the generator object twice: once for the {generator}
// member of the Suspend AST node, and once for the result of
// the initial yield.
Expression* yield_result =
factory()->NewVariableProxy(function_state_->generator_object_variable());
Expression* generator_object =
factory()->NewVariableProxy(function_state_->generator_object_variable());
// The position of the yield is important for reporting the exception
// caused by calling the .throw method on a generator suspended at the
// initial yield (i.e. right after generator instantiation).
return BuildSuspend(generator_object, yield_result, scope()->start_position(),
return BuildSuspend(yield_result, scope()->start_position(),
Suspend::kOnExceptionThrow, SuspendFlags::kYield);
}
......@@ -3922,8 +3917,8 @@ Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
Expression* do_expr = factory()->NewDoExpression(
do_block, AsyncGeneratorAwaitVariable(), nopos);
return BuildSuspend(generator_object, do_expr, await_pos,
Suspend::kOnExceptionRethrow, SuspendFlags::kAwait);
return BuildSuspend(do_expr, await_pos, Suspend::kOnExceptionRethrow,
SuspendFlags::kAwait);
}
// The parser emits calls to AsyncFunctionAwaitCaught or but the
......@@ -3942,8 +3937,7 @@ Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
Expression* do_expr =
factory()->NewDoExpression(do_block, PromiseVariable(), nopos);
return factory()->NewSuspend(generator_object, do_expr, await_pos,
Suspend::kOnExceptionRethrow,
return factory()->NewSuspend(do_expr, await_pos, Suspend::kOnExceptionRethrow,
SuspendFlags::kAwait);
}
......@@ -4288,8 +4282,7 @@ void Parser::SetFunctionName(Expression* value, const AstRawString* name) {
// output = %_Call(iteratorReturn, iterator, input);
// if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
Expression* Parser::RewriteYieldStar(Expression* generator,
Expression* iterable, int pos) {
Expression* Parser::RewriteYieldStar(Expression* iterable, int pos) {
const int nopos = kNoSourcePosition;
IteratorType type =
is_async_generator() ? IteratorType::kAsync : IteratorType::kNormal;
......@@ -4484,9 +4477,8 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
Statement* yield_output;
{
Expression* output_proxy = factory()->NewVariableProxy(var_output);
Suspend* yield =
BuildSuspend(generator, output_proxy, nopos, Suspend::kNoControl,
SuspendFlags::kYieldStar);
Suspend* yield = BuildSuspend(output_proxy, nopos, Suspend::kNoControl,
SuspendFlags::kYieldStar);
yield_output = factory()->NewExpressionStatement(yield, nopos);
}
......
......@@ -688,8 +688,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Block* block,
Expression* return_value, bool* ok);
Expression* RewriteYieldStar(Expression* generator, Expression* expression,
int pos);
Expression* RewriteYieldStar(Expression* expression, int pos);
void AddArrowFunctionFormalParameters(ParserFormalParameters* parameters,
Expression* params, int end_pos,
......
......@@ -642,8 +642,7 @@ class PreParserFactory {
// default value inside an arrow function parameter list.
return PreParserExpression::Assignment(left.variables_);
}
PreParserExpression NewSuspend(PreParserExpression generator_object,
PreParserExpression expression, int pos,
PreParserExpression NewSuspend(PreParserExpression expression, int pos,
Suspend::OnAbruptResume on_abrupt_resume,
SuspendFlags flags) {
return PreParserExpression::Default();
......@@ -1014,8 +1013,7 @@ class PreParser : public ParserBase<PreParser> {
PreParserStatement block,
PreParserExpression return_value,
bool* ok) {}
V8_INLINE PreParserExpression RewriteYieldStar(PreParserExpression generator,
PreParserExpression expression,
V8_INLINE PreParserExpression RewriteYieldStar(PreParserExpression expression,
int pos) {
return PreParserExpression::Default();
}
......
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