| Index: src/ast/ast.h
|
| diff --git a/src/ast/ast.h b/src/ast/ast.h
|
| index 6a0393cb6cd76b7f12dca3840915ae727dafd8e5..1bbe28d6f82ac7dc9a6dac26056f19d74291fd1c 100644
|
| --- a/src/ast/ast.h
|
| +++ b/src/ast/ast.h
|
| @@ -251,6 +251,7 @@ class Statement : public AstNode {
|
|
|
| bool IsEmpty() { return AsEmptyStatement() != NULL; }
|
| virtual bool IsJump() const { return false; }
|
| + virtual void MarkTail() {}
|
| };
|
|
|
|
|
| @@ -315,6 +316,9 @@ class Expression : public AstNode {
|
| kTest
|
| };
|
|
|
| + // Mark this expression as being in tail position.
|
| + virtual void MarkTail() {}
|
| +
|
| // True iff the expression is a valid reference expression.
|
| virtual bool IsValidReferenceExpression() const { return false; }
|
|
|
| @@ -471,6 +475,10 @@ class Block final : public BreakableStatement {
|
| && labels() == NULL; // Good enough as an approximation...
|
| }
|
|
|
| + void MarkTail() override {
|
| + if (!statements_.is_empty()) statements_.last()->MarkTail();
|
| + }
|
| +
|
| Scope* scope() const { return scope_; }
|
| void set_scope(Scope* scope) { scope_ = scope; }
|
|
|
| @@ -499,6 +507,8 @@ class DoExpression final : public Expression {
|
| Block* block() { return block_; }
|
| VariableProxy* result() { return result_; }
|
|
|
| + void MarkTail() override { block_->MarkTail(); }
|
| +
|
| protected:
|
| DoExpression(Zone* zone, Block* block, VariableProxy* result, int pos)
|
| : Expression(zone, pos), block_(block), result_(result) {
|
| @@ -934,6 +944,7 @@ class ExpressionStatement final : public Statement {
|
| void set_expression(Expression* e) { expression_ = e; }
|
| Expression* expression() const { return expression_; }
|
| bool IsJump() const override { return expression_->IsThrow(); }
|
| + void MarkTail() override { expression_->MarkTail(); }
|
|
|
| protected:
|
| ExpressionStatement(Zone* zone, Expression* expression, int pos)
|
| @@ -1012,6 +1023,8 @@ class WithStatement final : public Statement {
|
| BailoutId ToObjectId() const { return BailoutId(local_id(0)); }
|
| BailoutId EntryId() const { return BailoutId(local_id(1)); }
|
|
|
| + void MarkTail() override { statement_->MarkTail(); }
|
| +
|
| protected:
|
| WithStatement(Zone* zone, Scope* scope, Expression* expression,
|
| Statement* statement, int pos)
|
| @@ -1053,6 +1066,10 @@ class CaseClause final : public Expression {
|
| BailoutId EntryId() const { return BailoutId(local_id(0)); }
|
| TypeFeedbackId CompareId() { return TypeFeedbackId(local_id(1)); }
|
|
|
| + void MarkTail() override {
|
| + if (!statements_->is_empty()) statements_->last()->MarkTail();
|
| + }
|
| +
|
| Type* compare_type() { return compare_type_; }
|
| void set_compare_type(Type* type) { compare_type_ = type; }
|
|
|
| @@ -1083,6 +1100,10 @@ class SwitchStatement final : public BreakableStatement {
|
| Expression* tag() const { return tag_; }
|
| ZoneList<CaseClause*>* cases() const { return cases_; }
|
|
|
| + void MarkTail() override {
|
| + if (!cases_->is_empty()) cases_->last()->MarkTail();
|
| + }
|
| +
|
| protected:
|
| SwitchStatement(Zone* zone, ZoneList<const AstRawString*>* labels, int pos)
|
| : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos),
|
| @@ -1119,6 +1140,11 @@ class IfStatement final : public Statement {
|
| && HasElseStatement() && else_statement()->IsJump();
|
| }
|
|
|
| + void MarkTail() override {
|
| + then_statement_->MarkTail();
|
| + else_statement_->MarkTail();
|
| + }
|
| +
|
| void set_base_id(int id) { base_id_ = id; }
|
| static int num_ids() { return parent_num_ids() + 3; }
|
| BailoutId IfId() const { return BailoutId(local_id(0)); }
|
| @@ -1188,6 +1214,8 @@ class TryCatchStatement final : public TryStatement {
|
| Block* catch_block() const { return catch_block_; }
|
| void set_catch_block(Block* b) { catch_block_ = b; }
|
|
|
| + void MarkTail() override { catch_block_->MarkTail(); }
|
| +
|
| protected:
|
| TryCatchStatement(Zone* zone, Block* try_block, Scope* scope,
|
| Variable* variable, Block* catch_block, int pos)
|
| @@ -1210,6 +1238,8 @@ class TryFinallyStatement final : public TryStatement {
|
| Block* finally_block() const { return finally_block_; }
|
| void set_finally_block(Block* b) { finally_block_ = b; }
|
|
|
| + void MarkTail() override { finally_block_->MarkTail(); }
|
| +
|
| protected:
|
| TryFinallyStatement(Zone* zone, Block* try_block, Block* finally_block,
|
| int pos)
|
| @@ -1910,6 +1940,11 @@ class Call final : public Expression {
|
| bit_field_ = IsUninitializedField::update(bit_field_, b);
|
| }
|
|
|
| + bool is_tail() const { return IsTailField::decode(bit_field_); }
|
| + void MarkTail() override {
|
| + bit_field_ = IsTailField::update(bit_field_, true);
|
| + }
|
| +
|
| enum CallType {
|
| POSSIBLY_EVAL_CALL,
|
| GLOBAL_CALL,
|
| @@ -1955,6 +1990,7 @@ class Call final : public Expression {
|
| Handle<JSFunction> target_;
|
| Handle<AllocationSite> allocation_site_;
|
| class IsUninitializedField : public BitField8<bool, 0, 1> {};
|
| + class IsTailField : public BitField8<bool, 1, 1> {};
|
| uint8_t bit_field_;
|
| };
|
|
|
| @@ -2111,6 +2147,17 @@ class BinaryOperation final : public Expression {
|
| allocation_site_ = allocation_site;
|
| }
|
|
|
| + void MarkTail() override {
|
| + switch (op()) {
|
| + case Token::COMMA:
|
| + case Token::AND:
|
| + case Token::OR:
|
| + right_->MarkTail();
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| +
|
| // The short-circuit logical operations need an AST ID for their
|
| // right-hand subexpression.
|
| static int num_ids() { return parent_num_ids() + 2; }
|
| @@ -2302,6 +2349,11 @@ class Conditional final : public Expression {
|
| Expression* then_expression() const { return then_expression_; }
|
| Expression* else_expression() const { return else_expression_; }
|
|
|
| + void MarkTail() override {
|
| + then_expression_->MarkTail();
|
| + else_expression_->MarkTail();
|
| + }
|
| +
|
| static int num_ids() { return parent_num_ids() + 2; }
|
| BailoutId ThenId() const { return BailoutId(local_id(0)); }
|
| BailoutId ElseId() const { return BailoutId(local_id(1)); }
|
|
|