Add a generic mechanism for expression rewriting

R=rossberg@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1565153002

Cr-Commit-Position: refs/heads/master@{#33200}
This commit is contained in:
nikolaos 2016-01-11 04:41:44 -08:00 committed by Commit bot
parent 0840e20764
commit e54927244a
5 changed files with 592 additions and 0 deletions

View File

@ -628,6 +628,8 @@ source_set("v8_base") {
"src/assembler.h",
"src/assert-scope.h",
"src/assert-scope.cc",
"src/ast/ast-expression-rewriter.cc",
"src/ast/ast-expression-rewriter.h",
"src/ast/ast-expression-visitor.cc",
"src/ast/ast-expression-visitor.h",
"src/ast/ast-literal-reindexer.cc",

View File

@ -0,0 +1,409 @@
// Copyright 2015 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.
#include "src/ast/ast.h"
#include "src/ast/ast-expression-rewriter.h"
namespace v8 {
namespace internal {
// ----------------------------------------------------------------------------
// Implementation of AstExpressionRewriter
// The AST is traversed but no actual rewriting takes place, unless the
// Visit methods are overriden in subclasses.
#define REWRITE_THIS(node) \
do { \
if (!RewriteExpression(node)) return; \
} while (false)
#define NOTHING() DCHECK_NULL(replacement_)
void AstExpressionRewriter::VisitDeclarations(
ZoneList<Declaration*>* declarations) {
for (int i = 0; i < declarations->length(); i++) {
AST_REWRITE_LIST_ELEMENT(Declaration, declarations, i);
}
}
void AstExpressionRewriter::VisitStatements(ZoneList<Statement*>* statements) {
for (int i = 0; i < statements->length(); i++) {
AST_REWRITE_LIST_ELEMENT(Statement, statements, i);
// Not stopping when a jump statement is found.
}
}
void AstExpressionRewriter::VisitExpressions(
ZoneList<Expression*>* expressions) {
for (int i = 0; i < expressions->length(); i++) {
// The variable statement visiting code may pass NULL expressions
// to this code. Maybe this should be handled by introducing an
// undefined expression or literal? Revisit this code if this
// changes
if (expressions->at(i) != nullptr) {
AST_REWRITE_LIST_ELEMENT(Expression, expressions, i);
}
}
}
void AstExpressionRewriter::VisitVariableDeclaration(
VariableDeclaration* node) {
// Not visiting `proxy_`.
NOTHING();
}
void AstExpressionRewriter::VisitFunctionDeclaration(
FunctionDeclaration* node) {
// Not visiting `proxy_`.
AST_REWRITE_PROPERTY(FunctionLiteral, node, fun);
}
void AstExpressionRewriter::VisitImportDeclaration(ImportDeclaration* node) {
// Not visiting `proxy_`.
NOTHING();
}
void AstExpressionRewriter::VisitExportDeclaration(ExportDeclaration* node) {
// Not visiting `proxy_`.
NOTHING();
}
void AstExpressionRewriter::VisitBlock(Block* node) {
VisitStatements(node->statements());
}
void AstExpressionRewriter::VisitExpressionStatement(
ExpressionStatement* node) {
AST_REWRITE_PROPERTY(Expression, node, expression);
}
void AstExpressionRewriter::VisitEmptyStatement(EmptyStatement* node) {
NOTHING();
}
void AstExpressionRewriter::VisitSloppyBlockFunctionStatement(
SloppyBlockFunctionStatement* node) {
AST_REWRITE_PROPERTY(Statement, node, statement);
}
void AstExpressionRewriter::VisitIfStatement(IfStatement* node) {
AST_REWRITE_PROPERTY(Expression, node, condition);
AST_REWRITE_PROPERTY(Statement, node, then_statement);
AST_REWRITE_PROPERTY(Statement, node, else_statement);
}
void AstExpressionRewriter::VisitContinueStatement(ContinueStatement* node) {
NOTHING();
}
void AstExpressionRewriter::VisitBreakStatement(BreakStatement* node) {
NOTHING();
}
void AstExpressionRewriter::VisitReturnStatement(ReturnStatement* node) {
AST_REWRITE_PROPERTY(Expression, node, expression);
}
void AstExpressionRewriter::VisitWithStatement(WithStatement* node) {
AST_REWRITE_PROPERTY(Expression, node, expression);
AST_REWRITE_PROPERTY(Statement, node, statement);
}
void AstExpressionRewriter::VisitSwitchStatement(SwitchStatement* node) {
AST_REWRITE_PROPERTY(Expression, node, tag);
ZoneList<CaseClause*>* clauses = node->cases();
for (int i = 0; i < clauses->length(); i++) {
AST_REWRITE_LIST_ELEMENT(CaseClause, clauses, i);
}
}
void AstExpressionRewriter::VisitDoWhileStatement(DoWhileStatement* node) {
AST_REWRITE_PROPERTY(Expression, node, cond);
AST_REWRITE_PROPERTY(Statement, node, body);
}
void AstExpressionRewriter::VisitWhileStatement(WhileStatement* node) {
AST_REWRITE_PROPERTY(Expression, node, cond);
AST_REWRITE_PROPERTY(Statement, node, body);
}
void AstExpressionRewriter::VisitForStatement(ForStatement* node) {
if (node->init() != nullptr) {
AST_REWRITE_PROPERTY(Statement, node, init);
}
if (node->cond() != nullptr) {
AST_REWRITE_PROPERTY(Expression, node, cond);
}
if (node->next() != nullptr) {
AST_REWRITE_PROPERTY(Statement, node, next);
}
AST_REWRITE_PROPERTY(Statement, node, body);
}
void AstExpressionRewriter::VisitForInStatement(ForInStatement* node) {
AST_REWRITE_PROPERTY(Expression, node, each);
AST_REWRITE_PROPERTY(Expression, node, subject);
AST_REWRITE_PROPERTY(Statement, node, body);
}
void AstExpressionRewriter::VisitForOfStatement(ForOfStatement* node) {
AST_REWRITE_PROPERTY(Expression, node, each);
AST_REWRITE_PROPERTY(Expression, node, assign_iterator);
AST_REWRITE_PROPERTY(Expression, node, next_result);
AST_REWRITE_PROPERTY(Expression, node, result_done);
AST_REWRITE_PROPERTY(Expression, node, assign_each);
AST_REWRITE_PROPERTY(Expression, node, subject);
AST_REWRITE_PROPERTY(Statement, node, body);
}
void AstExpressionRewriter::VisitTryCatchStatement(TryCatchStatement* node) {
AST_REWRITE_PROPERTY(Block, node, try_block);
// Not visiting the variable.
AST_REWRITE_PROPERTY(Block, node, catch_block);
}
void AstExpressionRewriter::VisitTryFinallyStatement(
TryFinallyStatement* node) {
AST_REWRITE_PROPERTY(Block, node, try_block);
AST_REWRITE_PROPERTY(Block, node, finally_block);
}
void AstExpressionRewriter::VisitDebuggerStatement(DebuggerStatement* node) {
NOTHING();
}
void AstExpressionRewriter::VisitFunctionLiteral(FunctionLiteral* node) {
REWRITE_THIS(node);
VisitDeclarations(node->scope()->declarations());
ZoneList<Statement*>* body = node->body();
if (body != nullptr) VisitStatements(body);
}
void AstExpressionRewriter::VisitClassLiteral(ClassLiteral* node) {
REWRITE_THIS(node);
// Not visiting `class_variable_proxy_`.
if (node->extends() != nullptr) {
AST_REWRITE_PROPERTY(Expression, node, extends);
}
AST_REWRITE_PROPERTY(FunctionLiteral, node, constructor);
ZoneList<typename ClassLiteral::Property*>* properties = node->properties();
for (int i = 0; i < properties->length(); i++) {
VisitObjectLiteralProperty(properties->at(i));
}
}
void AstExpressionRewriter::VisitNativeFunctionLiteral(
NativeFunctionLiteral* node) {
REWRITE_THIS(node);
NOTHING();
}
void AstExpressionRewriter::VisitConditional(Conditional* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, condition);
AST_REWRITE_PROPERTY(Expression, node, then_expression);
AST_REWRITE_PROPERTY(Expression, node, else_expression);
}
void AstExpressionRewriter::VisitVariableProxy(VariableProxy* node) {
REWRITE_THIS(node);
NOTHING();
}
void AstExpressionRewriter::VisitLiteral(Literal* node) {
REWRITE_THIS(node);
NOTHING();
}
void AstExpressionRewriter::VisitRegExpLiteral(RegExpLiteral* node) {
REWRITE_THIS(node);
NOTHING();
}
void AstExpressionRewriter::VisitObjectLiteral(ObjectLiteral* node) {
REWRITE_THIS(node);
ZoneList<typename ObjectLiteral::Property*>* properties = node->properties();
for (int i = 0; i < properties->length(); i++) {
VisitObjectLiteralProperty(properties->at(i));
}
}
void AstExpressionRewriter::VisitObjectLiteralProperty(
ObjectLiteralProperty* property) {
if (property == nullptr) return;
AST_REWRITE_PROPERTY(Expression, property, key);
AST_REWRITE_PROPERTY(Expression, property, value);
}
void AstExpressionRewriter::VisitArrayLiteral(ArrayLiteral* node) {
REWRITE_THIS(node);
VisitExpressions(node->values());
}
void AstExpressionRewriter::VisitAssignment(Assignment* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, target);
AST_REWRITE_PROPERTY(Expression, node, value);
}
void AstExpressionRewriter::VisitYield(Yield* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, generator_object);
AST_REWRITE_PROPERTY(Expression, node, expression);
}
void AstExpressionRewriter::VisitThrow(Throw* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, exception);
}
void AstExpressionRewriter::VisitProperty(Property* node) {
REWRITE_THIS(node);
if (node == nullptr) return;
AST_REWRITE_PROPERTY(Expression, node, obj);
AST_REWRITE_PROPERTY(Expression, node, key);
}
void AstExpressionRewriter::VisitCall(Call* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, expression);
VisitExpressions(node->arguments());
}
void AstExpressionRewriter::VisitCallNew(CallNew* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, expression);
VisitExpressions(node->arguments());
}
void AstExpressionRewriter::VisitCallRuntime(CallRuntime* node) {
REWRITE_THIS(node);
VisitExpressions(node->arguments());
}
void AstExpressionRewriter::VisitUnaryOperation(UnaryOperation* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, expression);
}
void AstExpressionRewriter::VisitCountOperation(CountOperation* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, expression);
}
void AstExpressionRewriter::VisitBinaryOperation(BinaryOperation* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, left);
AST_REWRITE_PROPERTY(Expression, node, right);
}
void AstExpressionRewriter::VisitCompareOperation(CompareOperation* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, left);
AST_REWRITE_PROPERTY(Expression, node, right);
}
void AstExpressionRewriter::VisitSpread(Spread* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, expression);
}
void AstExpressionRewriter::VisitThisFunction(ThisFunction* node) {
REWRITE_THIS(node);
NOTHING();
}
void AstExpressionRewriter::VisitSuperPropertyReference(
SuperPropertyReference* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(VariableProxy, node, this_var);
AST_REWRITE_PROPERTY(Expression, node, home_object);
}
void AstExpressionRewriter::VisitSuperCallReference(SuperCallReference* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(VariableProxy, node, this_var);
AST_REWRITE_PROPERTY(VariableProxy, node, new_target_var);
AST_REWRITE_PROPERTY(VariableProxy, node, this_function_var);
}
void AstExpressionRewriter::VisitCaseClause(CaseClause* node) {
if (!node->is_default()) {
AST_REWRITE_PROPERTY(Expression, node, label);
}
VisitStatements(node->statements());
}
void AstExpressionRewriter::VisitEmptyParentheses(EmptyParentheses* node) {
NOTHING();
}
void AstExpressionRewriter::VisitDoExpression(DoExpression* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Block, node, block);
AST_REWRITE_PROPERTY(VariableProxy, node, result);
}
void AstExpressionRewriter::VisitRewritableAssignmentExpression(
RewritableAssignmentExpression* node) {
REWRITE_THIS(node);
AST_REWRITE_PROPERTY(Expression, node, expression);
}
} // namespace internal
} // namespace v8

View File

@ -0,0 +1,54 @@
// Copyright 2015 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.
#ifndef V8_AST_AST_EXPRESSION_REWRITER_H_
#define V8_AST_AST_EXPRESSION_REWRITER_H_
#include "src/allocation.h"
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/effects.h"
#include "src/type-info.h"
#include "src/types.h"
#include "src/zone.h"
namespace v8 {
namespace internal {
// A rewriting Visitor over a CompilationInfo's AST that invokes
// VisitExpression on each expression node.
class AstExpressionRewriter : public AstVisitor {
public:
explicit AstExpressionRewriter(Isolate* isolate) : AstVisitor() {
InitializeAstRewriter(isolate);
}
explicit AstExpressionRewriter(uintptr_t stack_limit) : AstVisitor() {
InitializeAstRewriter(stack_limit);
}
~AstExpressionRewriter() override {}
void VisitDeclarations(ZoneList<Declaration*>* declarations) override;
void VisitStatements(ZoneList<Statement*>* statements) override;
void VisitExpressions(ZoneList<Expression*>* expressions) override;
virtual void VisitObjectLiteralProperty(ObjectLiteralProperty* property);
protected:
virtual bool RewriteExpression(Expression* expr) = 0;
private:
DEFINE_AST_REWRITER_SUBCLASS_MEMBERS();
#define DECLARE_VISIT(type) void Visit##type(type* node) override;
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
DISALLOW_COPY_AND_ASSIGN(AstExpressionRewriter);
};
} // namespace internal
} // namespace v8
#endif // V8_AST_AST_EXPRESSION_REWRITER_H_

View File

@ -501,7 +501,9 @@ class DoExpression final : public Expression {
DECLARE_NODE_TYPE(DoExpression)
Block* block() { return block_; }
void set_block(Block* b) { block_ = b; }
VariableProxy* result() { return result_; }
void set_result(VariableProxy* v) { result_ = v; }
void MarkTail() override { block_->MarkTail(); }
@ -579,6 +581,7 @@ class FunctionDeclaration final : public Declaration {
DECLARE_NODE_TYPE(FunctionDeclaration)
FunctionLiteral* fun() const { return fun_; }
void set_fun(FunctionLiteral* f) { fun_ = f; }
InitializationFlag initialization() const override {
return kCreatedInitialized;
}
@ -702,6 +705,7 @@ class DoWhileStatement final : public IterationStatement {
}
Expression* cond() const { return cond_; }
void set_cond(Expression* e) { cond_ = e; }
static int num_ids() { return parent_num_ids() + 2; }
BailoutId ContinueId() const override { return BailoutId(local_id(0)); }
@ -730,6 +734,7 @@ class WhileStatement final : public IterationStatement {
}
Expression* cond() const { return cond_; }
void set_cond(Expression* e) { cond_ = e; }
static int num_ids() { return parent_num_ids() + 1; }
BailoutId ContinueId() const override { return EntryId(); }
@ -766,6 +771,10 @@ class ForStatement final : public IterationStatement {
Expression* cond() const { return cond_; }
Statement* next() const { return next_; }
void set_init(Statement* s) { init_ = s; }
void set_cond(Expression* e) { cond_ = e; }
void set_next(Statement* s) { next_ = s; }
static int num_ids() { return parent_num_ids() + 2; }
BailoutId ContinueId() const override { return BailoutId(local_id(0)); }
BailoutId StackCheckId() const override { return BodyId(); }
@ -804,6 +813,9 @@ class ForEachStatement : public IterationStatement {
Expression* each() const { return each_; }
Expression* subject() const { return subject_; }
void set_each(Expression* e) { each_ = e; }
void set_subject(Expression* e) { subject_ = e; }
void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
FeedbackVectorSlotCache* cache) override;
FeedbackVectorSlot EachFeedbackSlot() const { return each_slot_; }
@ -908,6 +920,11 @@ class ForOfStatement final : public ForEachStatement {
return assign_each_;
}
void set_assign_iterator(Expression* e) { assign_iterator_ = 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; }
BailoutId ContinueId() const override { return EntryId(); }
BailoutId StackCheckId() const override { return BackEdgeId(); }
@ -996,6 +1013,8 @@ class ReturnStatement final : public JumpStatement {
Expression* expression() const { return expression_; }
void set_expression(Expression* e) { expression_ = e; }
protected:
explicit ReturnStatement(Zone* zone, Expression* expression, int pos)
: JumpStatement(zone, pos), expression_(expression) { }
@ -1011,6 +1030,7 @@ class WithStatement final : public Statement {
Scope* scope() { return scope_; }
Expression* expression() const { return expression_; }
void set_expression(Expression* e) { expression_ = e; }
Statement* statement() const { return statement_; }
void set_statement(Statement* s) { statement_ = s; }
@ -1055,6 +1075,7 @@ class CaseClause final : public Expression {
CHECK(!is_default());
return label_;
}
void set_label(Expression* e) { label_ = e; }
Label* body_target() { return &body_target_; }
ZoneList<Statement*>* statements() const { return statements_; }
@ -1096,6 +1117,8 @@ class SwitchStatement final : public BreakableStatement {
Expression* tag() const { return tag_; }
ZoneList<CaseClause*>* cases() const { return cases_; }
void set_tag(Expression* t) { tag_ = t; }
void MarkTail() override {
if (!cases_->is_empty()) cases_->last()->MarkTail();
}
@ -1128,6 +1151,7 @@ class IfStatement final : public Statement {
Statement* then_statement() const { return then_statement_; }
Statement* else_statement() const { return else_statement_; }
void set_condition(Expression* e) { condition_ = e; }
void set_then_statement(Statement* s) { then_statement_ = s; }
void set_else_statement(Statement* s) { else_statement_ = s; }
@ -1422,6 +1446,9 @@ class ObjectLiteralProperty final : public ZoneObject {
Expression* value() { return value_; }
Kind kind() { return kind_; }
void set_key(Expression* e) { key_ = e; }
void set_value(Expression* e) { value_ = e; }
// Type feedback information.
bool IsMonomorphic() { return !receiver_type_.is_null(); }
Handle<Map> GetReceiverType() { return receiver_type_; }
@ -1795,6 +1822,9 @@ class Property final : public Expression {
Expression* obj() const { return obj_; }
Expression* key() const { return key_; }
void set_obj(Expression* e) { obj_ = e; }
void set_key(Expression* e) { key_ = e; }
static int num_ids() { return parent_num_ids() + 1; }
BailoutId LoadId() const { return BailoutId(local_id(0)); }
@ -1886,6 +1916,8 @@ class Call final : public Expression {
Expression* expression() const { return expression_; }
ZoneList<Expression*>* arguments() const { return arguments_; }
void set_expression(Expression* e) { expression_ = e; }
// Type feedback information.
void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
FeedbackVectorSlotCache* cache) override;
@ -2005,6 +2037,8 @@ class CallNew final : public Expression {
Expression* expression() const { return expression_; }
ZoneList<Expression*>* arguments() const { return arguments_; }
void set_expression(Expression* e) { expression_ = e; }
// Type feedback information.
void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
FeedbackVectorSlotCache* cache) override {
@ -2114,6 +2148,7 @@ class UnaryOperation final : public Expression {
Token::Value op() const { return op_; }
Expression* expression() const { return expression_; }
void set_expression(Expression* e) { expression_ = e; }
// For unary not (Token::NOT), the AST ids where true and false will
// actually be materialized, respectively.
@ -2144,7 +2179,9 @@ class BinaryOperation final : public Expression {
Token::Value op() const { return static_cast<Token::Value>(op_); }
Expression* left() const { return left_; }
void set_left(Expression* e) { left_ = e; }
Expression* right() const { return right_; }
void set_right(Expression* e) { right_ = e; }
Handle<AllocationSite> allocation_site() const { return allocation_site_; }
void set_allocation_site(Handle<AllocationSite> allocation_site) {
allocation_site_ = allocation_site;
@ -2219,6 +2256,7 @@ class CountOperation final : public Expression {
}
Expression* expression() const { return expression_; }
void set_expression(Expression* e) { expression_ = e; }
bool IsMonomorphic() override { return receiver_types_.length() == 1; }
SmallMapList* GetReceiverTypes() override { return &receiver_types_; }
@ -2288,6 +2326,9 @@ class CompareOperation final : public Expression {
Expression* left() const { return left_; }
Expression* right() const { return right_; }
void set_left(Expression* e) { left_ = e; }
void set_right(Expression* e) { right_ = e; }
// Type feedback information.
static int num_ids() { return parent_num_ids() + 1; }
TypeFeedbackId CompareOperationFeedbackId() const {
@ -2329,6 +2370,7 @@ class Spread final : public Expression {
DECLARE_NODE_TYPE(Spread)
Expression* expression() const { return expression_; }
void set_expression(Expression* e) { expression_ = e; }
static int num_ids() { return parent_num_ids(); }
@ -2352,6 +2394,10 @@ class Conditional final : public Expression {
Expression* then_expression() const { return then_expression_; }
Expression* else_expression() const { return else_expression_; }
void set_condition(Expression* e) { condition_ = e; }
void set_then_expression(Expression* e) { then_expression_ = e; }
void set_else_expression(Expression* e) { else_expression_ = e; }
void MarkTail() override {
then_expression_->MarkTail();
else_expression_->MarkTail();
@ -2391,6 +2437,9 @@ class Assignment final : public Expression {
Expression* target() const { return target_; }
Expression* value() const { return value_; }
void set_target(Expression* e) { target_ = e; }
void set_value(Expression* e) { value_ = e; }
BinaryOperation* binary_operation() const { return binary_operation_; }
// This check relies on the definition order of token in token.h.
@ -2463,6 +2512,8 @@ class RewritableAssignmentExpression : public Expression {
Expression* expression() { return expr_; }
bool is_rewritten() const { return is_rewritten_; }
void set_expression(Expression* e) { expr_ = e; }
void Rewrite(Expression* new_expression) {
DCHECK(!is_rewritten());
DCHECK_NOT_NULL(new_expression);
@ -2501,6 +2552,9 @@ class Yield final : public Expression {
Expression* expression() const { return expression_; }
Kind yield_kind() const { return yield_kind_; }
void set_generator_object(Expression* e) { generator_object_ = e; }
void set_expression(Expression* e) { expression_ = e; }
// Type feedback information.
bool HasFeedbackSlots() const { return yield_kind() == kDelegating; }
void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
@ -2544,6 +2598,7 @@ class Throw final : public Expression {
DECLARE_NODE_TYPE(Throw)
Expression* exception() const { return exception_; }
void set_exception(Expression* e) { exception_ = e; }
protected:
Throw(Zone* zone, Expression* exception, int pos)
@ -2751,7 +2806,9 @@ class ClassLiteral final : public Expression {
Scope* scope() const { return scope_; }
VariableProxy* class_variable_proxy() const { return class_variable_proxy_; }
Expression* extends() const { return extends_; }
void set_extends(Expression* e) { extends_ = e; }
FunctionLiteral* constructor() const { return constructor_; }
void set_constructor(FunctionLiteral* f) { constructor_ = f; }
ZoneList<Property*>* properties() const { return properties_; }
int start_position() const { return position(); }
int end_position() const { return end_position_; }
@ -2842,7 +2899,9 @@ class SuperPropertyReference final : public Expression {
DECLARE_NODE_TYPE(SuperPropertyReference)
VariableProxy* this_var() const { return this_var_; }
void set_this_var(VariableProxy* v) { this_var_ = v; }
Expression* home_object() const { return home_object_; }
void set_home_object(Expression* e) { home_object_ = e; }
protected:
SuperPropertyReference(Zone* zone, VariableProxy* this_var,
@ -2863,8 +2922,11 @@ class SuperCallReference final : public Expression {
DECLARE_NODE_TYPE(SuperCallReference)
VariableProxy* this_var() const { return this_var_; }
void set_this_var(VariableProxy* v) { this_var_ = v; }
VariableProxy* new_target_var() const { return new_target_var_; }
void set_new_target_var(VariableProxy* v) { new_target_var_ = v; }
VariableProxy* this_function_var() const { return this_function_var_; }
void set_this_function_var(VariableProxy* v) { this_function_var_ = v; }
protected:
SuperCallReference(Zone* zone, VariableProxy* this_var,
@ -2957,6 +3019,69 @@ class AstVisitor BASE_EMBEDDED {
uintptr_t stack_limit_; \
bool stack_overflow_
#define DEFINE_AST_REWRITER_SUBCLASS_MEMBERS() \
public: \
AstNode* Rewrite(AstNode* node) { \
DCHECK_NULL(replacement_); \
DCHECK_NOT_NULL(node); \
Visit(node); \
if (HasStackOverflow()) return node; \
if (replacement_ == nullptr) return node; \
AstNode* result = replacement_; \
replacement_ = nullptr; \
return result; \
} \
\
private: \
void InitializeAstRewriter(Isolate* isolate) { \
InitializeAstVisitor(isolate); \
replacement_ = nullptr; \
} \
\
void InitializeAstRewriter(uintptr_t stack_limit) { \
InitializeAstVisitor(stack_limit); \
replacement_ = nullptr; \
} \
\
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); \
\
protected: \
AstNode* replacement_
// Generic macro for rewriting things; `GET` is the expression to be
// rewritten; `SET` is a command that should do the rewriting, i.e.
// something sensible with the variable called `replacement`.
#define AST_REWRITE(Type, GET, SET) \
do { \
DCHECK(!HasStackOverflow()); \
DCHECK_NULL(replacement_); \
Visit(GET); \
if (HasStackOverflow()) return; \
if (replacement_ == nullptr) break; \
Type* replacement = reinterpret_cast<Type*>(replacement_); \
do { \
SET; \
} while (false); \
replacement_ = nullptr; \
} while (false)
// Macro for rewriting object properties; it assumes that `object` has
// `property` with a public getter and setter.
#define AST_REWRITE_PROPERTY(Type, object, property) \
do { \
auto _obj = (object); \
AST_REWRITE(Type, _obj->property(), _obj->set_##property(replacement)); \
} while (false)
// Macro for rewriting list elements; it assumes that `list` has methods
// `at` and `Set`.
#define AST_REWRITE_LIST_ELEMENT(Type, list, index) \
do { \
auto _list = (list); \
auto _index = (index); \
AST_REWRITE(Type, _list->at(_index), _list->Set(_index, replacement)); \
} while (false)
// ----------------------------------------------------------------------------
// AstNode factory

View File

@ -404,6 +404,8 @@
'../../src/assembler.h',
'../../src/assert-scope.h',
'../../src/assert-scope.cc',
'../../src/ast/ast-expression-rewriter.cc',
'../../src/ast/ast-expression-rewriter.h',
'../../src/ast/ast-expression-visitor.cc',
'../../src/ast/ast-expression-visitor.h',
'../../src/ast/ast-literal-reindexer.cc',