[parser] Refactor AstTraversalVisitor

This patch parametrizes AstTraversalVisitor by the actual subclass,
in a similar way as AstVisitor is parametrized.  This allows a
subclass to, e.g., override the Visit method and still use the
traversal mechanism.  It also allows the subclass to override the
specific visiting methods, without them being virtual.

This patch also removes AstExpressionVisitor, subsuming its
functionality in AstTraversalVisitor.

R=adamk@chromium.org, verwaest@chromium.org
BUG=
LOG=N

Review-Url: https://codereview.chromium.org/2169833002
Cr-Commit-Position: refs/heads/master@{#37998}
This commit is contained in:
nikolaos 2016-07-25 01:25:49 -07:00 committed by Commit bot
parent a189839c53
commit ad6ea93227
12 changed files with 546 additions and 579 deletions

View File

@ -838,12 +838,11 @@ v8_source_set("v8_base") {
"src/assert-scope.h",
"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",
"src/ast/ast-literal-reindexer.h",
"src/ast/ast-numbering.cc",
"src/ast/ast-numbering.h",
"src/ast/ast-traversal-visitor.h",
"src/ast/ast-type-bounds.h",
"src/ast/ast-value-factory.cc",
"src/ast/ast-value-factory.h",

View File

@ -1,167 +0,0 @@
// 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/v8.h"
#include "src/ast/ast-expression-visitor.h"
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/codegen.h"
namespace v8 {
namespace internal {
AstExpressionVisitor::AstExpressionVisitor(Isolate* isolate, Expression* root)
: AstTraversalVisitor(isolate), root_(root) {}
AstExpressionVisitor::AstExpressionVisitor(uintptr_t stack_limit,
Expression* root)
: AstTraversalVisitor(stack_limit), root_(root) {}
void AstExpressionVisitor::Run() { Visit(root_); }
void AstExpressionVisitor::VisitFunctionLiteral(FunctionLiteral* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitFunctionLiteral(expr);
}
void AstExpressionVisitor::VisitNativeFunctionLiteral(
NativeFunctionLiteral* expr) {
AstTraversalVisitor::VisitNativeFunctionLiteral(expr);
}
void AstExpressionVisitor::VisitDoExpression(DoExpression* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitDoExpression(expr);
}
void AstExpressionVisitor::VisitConditional(Conditional* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitConditional(expr);
}
void AstExpressionVisitor::VisitVariableProxy(VariableProxy* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitVariableProxy(expr);
}
void AstExpressionVisitor::VisitLiteral(Literal* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitLiteral(expr);
}
void AstExpressionVisitor::VisitRegExpLiteral(RegExpLiteral* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitRegExpLiteral(expr);
}
void AstExpressionVisitor::VisitObjectLiteral(ObjectLiteral* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitObjectLiteral(expr);
}
void AstExpressionVisitor::VisitArrayLiteral(ArrayLiteral* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitArrayLiteral(expr);
}
void AstExpressionVisitor::VisitAssignment(Assignment* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitAssignment(expr);
}
void AstExpressionVisitor::VisitYield(Yield* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitYield(expr);
}
void AstExpressionVisitor::VisitThrow(Throw* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitThrow(expr);
}
void AstExpressionVisitor::VisitProperty(Property* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitProperty(expr);
}
void AstExpressionVisitor::VisitCall(Call* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitCall(expr);
}
void AstExpressionVisitor::VisitCallNew(CallNew* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitCallNew(expr);
}
void AstExpressionVisitor::VisitCallRuntime(CallRuntime* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitCallRuntime(expr);
}
void AstExpressionVisitor::VisitUnaryOperation(UnaryOperation* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitUnaryOperation(expr);
}
void AstExpressionVisitor::VisitCountOperation(CountOperation* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitCountOperation(expr);
}
void AstExpressionVisitor::VisitBinaryOperation(BinaryOperation* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitBinaryOperation(expr);
}
void AstExpressionVisitor::VisitCompareOperation(CompareOperation* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitCompareOperation(expr);
}
void AstExpressionVisitor::VisitThisFunction(ThisFunction* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitThisFunction(expr);
}
void AstExpressionVisitor::VisitClassLiteral(ClassLiteral* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitClassLiteral(expr);
}
void AstExpressionVisitor::VisitSpread(Spread* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitSpread(expr);
}
void AstExpressionVisitor::VisitSuperPropertyReference(
SuperPropertyReference* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitSuperPropertyReference(expr);
}
void AstExpressionVisitor::VisitSuperCallReference(SuperCallReference* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitSuperCallReference(expr);
}
void AstExpressionVisitor::VisitCaseClause(CaseClause* expr) {
AstTraversalVisitor::VisitCaseClause(expr);
}
void AstExpressionVisitor::VisitEmptyParentheses(EmptyParentheses* expr) {
AstTraversalVisitor::VisitEmptyParentheses(expr);
}
void AstExpressionVisitor::VisitRewritableExpression(
RewritableExpression* expr) {
VisitExpression(expr);
AstTraversalVisitor::VisitRewritableExpression(expr);
}
} // namespace internal
} // namespace v8

View File

@ -1,41 +0,0 @@
// 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_VISITOR_H_
#define V8_AST_AST_EXPRESSION_VISITOR_H_
#include "src/allocation.h"
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
#include "src/type-info.h"
#include "src/zone.h"
namespace v8 {
namespace internal {
// A Visitor over a CompilationInfo's AST that invokes
// VisitExpression on each expression node.
class AstExpressionVisitor : public AstTraversalVisitor {
public:
AstExpressionVisitor(Isolate* isolate, Expression* root);
AstExpressionVisitor(uintptr_t stack_limit, Expression* root);
void Run();
protected:
virtual void VisitExpression(Expression* expression) = 0;
private:
#define DECLARE_VISIT(type) void Visit##type(type* node) override;
EXPRESSION_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
Expression* root_;
DISALLOW_COPY_AND_ASSIGN(AstExpressionVisitor);
};
} // namespace internal
} // namespace v8
#endif // V8_AST_AST_EXPRESSION_VISITOR_H_

View File

@ -0,0 +1,504 @@
// Copyright 2016 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_TRAVERSAL_VISITOR_H_
#define V8_AST_AST_TRAVERSAL_VISITOR_H_
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
namespace v8 {
namespace internal {
// ----------------------------------------------------------------------------
// Traversal visitor
// - fully traverses the entire AST.
//
// Sub-class should parametrize AstTraversalVisitor with itself, e.g.:
// class SpecificVisitor : public AstTraversalVisitor<SpecificVisitor> { ... }
//
// It invokes VisitNode on each AST node, before proceeding with its subtrees.
// It invokes VisitExpression (after VisitNode) on each AST node that is an
// expression, before proceeding with its subtrees.
// It proceeds with the subtrees only if these two methods return true.
// Sub-classes may override VisitNode and VisitExpressions, whose implementation
// is dummy here. Or they may override the specific Visit* methods.
template <class Subclass>
class AstTraversalVisitor : public AstVisitor<Subclass> {
public:
explicit AstTraversalVisitor(Isolate* isolate, AstNode* root = nullptr);
explicit AstTraversalVisitor(uintptr_t stack_limit, AstNode* root = nullptr);
void Run() {
DCHECK_NOT_NULL(root_);
Visit(root_);
}
bool VisitNode(AstNode* node) { return true; }
bool VisitExpression(Expression* node) { return true; }
// Iteration left-to-right.
void VisitDeclarations(ZoneList<Declaration*>* declarations);
void VisitStatements(ZoneList<Statement*>* statements);
// Individual nodes
#define DECLARE_VISIT(type) void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
protected:
int depth() const { return depth_; }
private:
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
AstNode* root_;
int depth_;
DISALLOW_COPY_AND_ASSIGN(AstTraversalVisitor);
};
// ----------------------------------------------------------------------------
// Implementation of AstTraversalVisitor
#define PROCESS_NODE(node) do { \
if (!(this->impl()->VisitNode(node))) return; \
} while (false)
#define PROCESS_EXPRESSION(node) do { \
PROCESS_NODE(node); \
if (!(this->impl()->VisitExpression(node))) return; \
} while (false)
#define RECURSE(call) \
do { \
DCHECK(!HasStackOverflow()); \
this->impl()->call; \
if (HasStackOverflow()) return; \
} while (false)
#define RECURSE_EXPRESSION(call) \
do { \
DCHECK(!HasStackOverflow()); \
++depth_; \
this->impl()->call; \
--depth_; \
if (HasStackOverflow()) return; \
} while (false)
template <class Subclass>
AstTraversalVisitor<Subclass>::AstTraversalVisitor(Isolate* isolate,
AstNode* root)
: root_(root), depth_(0) {
InitializeAstVisitor(isolate);
}
template <class Subclass>
AstTraversalVisitor<Subclass>::AstTraversalVisitor(uintptr_t stack_limit,
AstNode* root)
: root_(root), depth_(0) {
InitializeAstVisitor(stack_limit);
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitDeclarations(
ZoneList<Declaration*>* decls) {
for (int i = 0; i < decls->length(); ++i) {
Declaration* decl = decls->at(i);
RECURSE(Visit(decl));
}
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitStatements(
ZoneList<Statement*>* stmts) {
for (int i = 0; i < stmts->length(); ++i) {
Statement* stmt = stmts->at(i);
RECURSE(Visit(stmt));
if (stmt->IsJump()) break;
}
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitVariableDeclaration(
VariableDeclaration* decl) {
PROCESS_NODE(decl);
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitFunctionDeclaration(
FunctionDeclaration* decl) {
PROCESS_NODE(decl);
RECURSE(Visit(decl->fun()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitBlock(Block* stmt) {
PROCESS_NODE(stmt);
RECURSE(VisitStatements(stmt->statements()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitExpressionStatement(
ExpressionStatement* stmt) {
PROCESS_NODE(stmt);
RECURSE(Visit(stmt->expression()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitEmptyStatement(EmptyStatement* stmt) {}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitSloppyBlockFunctionStatement(
SloppyBlockFunctionStatement* stmt) {
PROCESS_NODE(stmt);
RECURSE(Visit(stmt->statement()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitIfStatement(IfStatement* stmt) {
PROCESS_NODE(stmt);
RECURSE(Visit(stmt->condition()));
RECURSE(Visit(stmt->then_statement()));
RECURSE(Visit(stmt->else_statement()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitContinueStatement(
ContinueStatement* stmt) {
PROCESS_NODE(stmt);
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitBreakStatement(BreakStatement* stmt) {
PROCESS_NODE(stmt);
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitReturnStatement(
ReturnStatement* stmt) {
PROCESS_NODE(stmt);
RECURSE(Visit(stmt->expression()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitWithStatement(WithStatement* stmt) {
PROCESS_NODE(stmt);
RECURSE(Visit(stmt->expression()));
RECURSE(Visit(stmt->statement()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitSwitchStatement(
SwitchStatement* stmt) {
PROCESS_NODE(stmt);
RECURSE(Visit(stmt->tag()));
ZoneList<CaseClause*>* clauses = stmt->cases();
for (int i = 0; i < clauses->length(); ++i) {
CaseClause* clause = clauses->at(i);
if (!clause->is_default()) {
Expression* label = clause->label();
RECURSE(Visit(label));
}
ZoneList<Statement*>* stmts = clause->statements();
RECURSE(VisitStatements(stmts));
}
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitCaseClause(CaseClause* clause) {
UNREACHABLE();
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitDoWhileStatement(
DoWhileStatement* stmt) {
PROCESS_NODE(stmt);
RECURSE(Visit(stmt->body()));
RECURSE(Visit(stmt->cond()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitWhileStatement(WhileStatement* stmt) {
PROCESS_NODE(stmt);
RECURSE(Visit(stmt->cond()));
RECURSE(Visit(stmt->body()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitForStatement(ForStatement* stmt) {
PROCESS_NODE(stmt);
if (stmt->init() != NULL) {
RECURSE(Visit(stmt->init()));
}
if (stmt->cond() != NULL) {
RECURSE(Visit(stmt->cond()));
}
if (stmt->next() != NULL) {
RECURSE(Visit(stmt->next()));
}
RECURSE(Visit(stmt->body()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitForInStatement(ForInStatement* stmt) {
PROCESS_NODE(stmt);
RECURSE(Visit(stmt->enumerable()));
RECURSE(Visit(stmt->body()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitForOfStatement(ForOfStatement* stmt) {
PROCESS_NODE(stmt);
RECURSE(Visit(stmt->assign_iterator()));
RECURSE(Visit(stmt->next_result()));
RECURSE(Visit(stmt->result_done()));
RECURSE(Visit(stmt->assign_each()));
RECURSE(Visit(stmt->body()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitTryCatchStatement(
TryCatchStatement* stmt) {
PROCESS_NODE(stmt);
RECURSE(Visit(stmt->try_block()));
RECURSE(Visit(stmt->catch_block()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitTryFinallyStatement(
TryFinallyStatement* stmt) {
PROCESS_NODE(stmt);
RECURSE(Visit(stmt->try_block()));
RECURSE(Visit(stmt->finally_block()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitDebuggerStatement(
DebuggerStatement* stmt) {
PROCESS_NODE(stmt);
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitFunctionLiteral(
FunctionLiteral* expr) {
PROCESS_EXPRESSION(expr);
Scope* scope = expr->scope();
RECURSE_EXPRESSION(VisitDeclarations(scope->declarations()));
RECURSE_EXPRESSION(VisitStatements(expr->body()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitNativeFunctionLiteral(
NativeFunctionLiteral* expr) {
PROCESS_EXPRESSION(expr);
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitDoExpression(DoExpression* expr) {
PROCESS_EXPRESSION(expr);
RECURSE(VisitBlock(expr->block()));
RECURSE(VisitVariableProxy(expr->result()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitConditional(Conditional* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->condition()));
RECURSE_EXPRESSION(Visit(expr->then_expression()));
RECURSE_EXPRESSION(Visit(expr->else_expression()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitVariableProxy(VariableProxy* expr) {
PROCESS_EXPRESSION(expr);
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitLiteral(Literal* expr) {
PROCESS_EXPRESSION(expr);
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitRegExpLiteral(RegExpLiteral* expr) {
PROCESS_EXPRESSION(expr);
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitObjectLiteral(ObjectLiteral* expr) {
PROCESS_EXPRESSION(expr);
ZoneList<ObjectLiteralProperty*>* props = expr->properties();
for (int i = 0; i < props->length(); ++i) {
ObjectLiteralProperty* prop = props->at(i);
RECURSE_EXPRESSION(Visit(prop->key()));
RECURSE_EXPRESSION(Visit(prop->value()));
}
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitArrayLiteral(ArrayLiteral* expr) {
PROCESS_EXPRESSION(expr);
ZoneList<Expression*>* values = expr->values();
for (int i = 0; i < values->length(); ++i) {
Expression* value = values->at(i);
RECURSE_EXPRESSION(Visit(value));
}
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitAssignment(Assignment* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->target()));
RECURSE_EXPRESSION(Visit(expr->value()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitYield(Yield* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->generator_object()));
RECURSE_EXPRESSION(Visit(expr->expression()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitThrow(Throw* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->exception()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitProperty(Property* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->obj()));
RECURSE_EXPRESSION(Visit(expr->key()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitCall(Call* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->expression()));
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
RECURSE_EXPRESSION(Visit(arg));
}
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitCallNew(CallNew* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->expression()));
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
RECURSE_EXPRESSION(Visit(arg));
}
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitCallRuntime(CallRuntime* expr) {
PROCESS_EXPRESSION(expr);
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
RECURSE_EXPRESSION(Visit(arg));
}
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitUnaryOperation(UnaryOperation* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->expression()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitCountOperation(CountOperation* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->expression()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitBinaryOperation(
BinaryOperation* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->left()));
RECURSE_EXPRESSION(Visit(expr->right()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitCompareOperation(
CompareOperation* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->left()));
RECURSE_EXPRESSION(Visit(expr->right()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitThisFunction(ThisFunction* expr) {
PROCESS_EXPRESSION(expr);
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitClassLiteral(ClassLiteral* expr) {
PROCESS_EXPRESSION(expr);
if (expr->extends() != nullptr) {
RECURSE_EXPRESSION(Visit(expr->extends()));
}
RECURSE_EXPRESSION(Visit(expr->constructor()));
ZoneList<ObjectLiteralProperty*>* props = expr->properties();
for (int i = 0; i < props->length(); ++i) {
ObjectLiteralProperty* prop = props->at(i);
if (!prop->key()->IsLiteral()) {
RECURSE_EXPRESSION(Visit(prop->key()));
}
RECURSE_EXPRESSION(Visit(prop->value()));
}
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitSpread(Spread* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(Visit(expr->expression()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitEmptyParentheses(
EmptyParentheses* expr) {
PROCESS_EXPRESSION(expr);
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitSuperPropertyReference(
SuperPropertyReference* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
RECURSE_EXPRESSION(Visit(expr->home_object()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitSuperCallReference(
SuperCallReference* expr) {
PROCESS_EXPRESSION(expr);
RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
RECURSE_EXPRESSION(VisitVariableProxy(expr->new_target_var()));
RECURSE_EXPRESSION(VisitVariableProxy(expr->this_function_var()));
}
template <class Subclass>
void AstTraversalVisitor<Subclass>::VisitRewritableExpression(
RewritableExpression* expr) {
PROCESS_EXPRESSION(expr);
RECURSE(Visit(expr->expression()));
}
#undef PROCESS_NODE
#undef PROCESS_EXPRESSION
#undef RECURSE_EXPRESSION
#undef RECURSE
} // namespace internal
} // namespace v8
#endif // V8_AST_AST_TRAVERSAL_VISITOR_H_

View File

@ -923,305 +923,6 @@ Call::CallType Call::GetCallType(Isolate* isolate) const {
}
// ----------------------------------------------------------------------------
// Implementation of AstTraversalVisitor
#define RECURSE(call) \
do { \
DCHECK(!HasStackOverflow()); \
call; \
if (HasStackOverflow()) return; \
} while (false)
#define RECURSE_EXPRESSION(call) \
do { \
DCHECK(!HasStackOverflow()); \
++depth_; \
call; \
--depth_; \
if (HasStackOverflow()) return; \
} while (false)
AstTraversalVisitor::AstTraversalVisitor(Isolate* isolate) : depth_(0) {
InitializeAstVisitor(isolate);
}
AstTraversalVisitor::AstTraversalVisitor(uintptr_t stack_limit) : depth_(0) {
InitializeAstVisitor(stack_limit);
}
void AstTraversalVisitor::VisitDeclarations(ZoneList<Declaration*>* decls) {
for (int i = 0; i < decls->length(); ++i) {
Declaration* decl = decls->at(i);
RECURSE(Visit(decl));
}
}
void AstTraversalVisitor::VisitStatements(ZoneList<Statement*>* stmts) {
for (int i = 0; i < stmts->length(); ++i) {
Statement* stmt = stmts->at(i);
RECURSE(Visit(stmt));
if (stmt->IsJump()) break;
}
}
void AstTraversalVisitor::VisitVariableDeclaration(VariableDeclaration* decl) {}
void AstTraversalVisitor::VisitFunctionDeclaration(FunctionDeclaration* decl) {
RECURSE(Visit(decl->fun()));
}
void AstTraversalVisitor::VisitBlock(Block* stmt) {
RECURSE(VisitStatements(stmt->statements()));
}
void AstTraversalVisitor::VisitExpressionStatement(ExpressionStatement* stmt) {
RECURSE(Visit(stmt->expression()));
}
void AstTraversalVisitor::VisitEmptyStatement(EmptyStatement* stmt) {}
void AstTraversalVisitor::VisitSloppyBlockFunctionStatement(
SloppyBlockFunctionStatement* stmt) {
RECURSE(Visit(stmt->statement()));
}
void AstTraversalVisitor::VisitIfStatement(IfStatement* stmt) {
RECURSE(Visit(stmt->condition()));
RECURSE(Visit(stmt->then_statement()));
RECURSE(Visit(stmt->else_statement()));
}
void AstTraversalVisitor::VisitContinueStatement(ContinueStatement* stmt) {}
void AstTraversalVisitor::VisitBreakStatement(BreakStatement* stmt) {}
void AstTraversalVisitor::VisitReturnStatement(ReturnStatement* stmt) {
RECURSE(Visit(stmt->expression()));
}
void AstTraversalVisitor::VisitWithStatement(WithStatement* stmt) {
RECURSE(stmt->expression());
RECURSE(stmt->statement());
}
void AstTraversalVisitor::VisitSwitchStatement(SwitchStatement* stmt) {
RECURSE(Visit(stmt->tag()));
ZoneList<CaseClause*>* clauses = stmt->cases();
for (int i = 0; i < clauses->length(); ++i) {
CaseClause* clause = clauses->at(i);
if (!clause->is_default()) {
Expression* label = clause->label();
RECURSE(Visit(label));
}
ZoneList<Statement*>* stmts = clause->statements();
RECURSE(VisitStatements(stmts));
}
}
void AstTraversalVisitor::VisitCaseClause(CaseClause* clause) { UNREACHABLE(); }
void AstTraversalVisitor::VisitDoWhileStatement(DoWhileStatement* stmt) {
RECURSE(Visit(stmt->body()));
RECURSE(Visit(stmt->cond()));
}
void AstTraversalVisitor::VisitWhileStatement(WhileStatement* stmt) {
RECURSE(Visit(stmt->cond()));
RECURSE(Visit(stmt->body()));
}
void AstTraversalVisitor::VisitForStatement(ForStatement* stmt) {
if (stmt->init() != NULL) {
RECURSE(Visit(stmt->init()));
}
if (stmt->cond() != NULL) {
RECURSE(Visit(stmt->cond()));
}
if (stmt->next() != NULL) {
RECURSE(Visit(stmt->next()));
}
RECURSE(Visit(stmt->body()));
}
void AstTraversalVisitor::VisitForInStatement(ForInStatement* stmt) {
RECURSE(Visit(stmt->enumerable()));
RECURSE(Visit(stmt->body()));
}
void AstTraversalVisitor::VisitForOfStatement(ForOfStatement* stmt) {
RECURSE(Visit(stmt->assign_iterator()));
RECURSE(Visit(stmt->next_result()));
RECURSE(Visit(stmt->result_done()));
RECURSE(Visit(stmt->assign_each()));
RECURSE(Visit(stmt->body()));
}
void AstTraversalVisitor::VisitTryCatchStatement(TryCatchStatement* stmt) {
RECURSE(Visit(stmt->try_block()));
RECURSE(Visit(stmt->catch_block()));
}
void AstTraversalVisitor::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
RECURSE(Visit(stmt->try_block()));
RECURSE(Visit(stmt->finally_block()));
}
void AstTraversalVisitor::VisitDebuggerStatement(DebuggerStatement* stmt) {}
void AstTraversalVisitor::VisitFunctionLiteral(FunctionLiteral* expr) {
Scope* scope = expr->scope();
RECURSE_EXPRESSION(VisitDeclarations(scope->declarations()));
RECURSE_EXPRESSION(VisitStatements(expr->body()));
}
void AstTraversalVisitor::VisitNativeFunctionLiteral(
NativeFunctionLiteral* expr) {}
void AstTraversalVisitor::VisitDoExpression(DoExpression* expr) {
RECURSE(VisitBlock(expr->block()));
RECURSE(VisitVariableProxy(expr->result()));
}
void AstTraversalVisitor::VisitConditional(Conditional* expr) {
RECURSE_EXPRESSION(Visit(expr->condition()));
RECURSE_EXPRESSION(Visit(expr->then_expression()));
RECURSE_EXPRESSION(Visit(expr->else_expression()));
}
void AstTraversalVisitor::VisitVariableProxy(VariableProxy* expr) {}
void AstTraversalVisitor::VisitLiteral(Literal* expr) {}
void AstTraversalVisitor::VisitRegExpLiteral(RegExpLiteral* expr) {}
void AstTraversalVisitor::VisitObjectLiteral(ObjectLiteral* expr) {
ZoneList<ObjectLiteralProperty*>* props = expr->properties();
for (int i = 0; i < props->length(); ++i) {
ObjectLiteralProperty* prop = props->at(i);
if (!prop->key()->IsLiteral()) {
RECURSE_EXPRESSION(Visit(prop->key()));
}
RECURSE_EXPRESSION(Visit(prop->value()));
}
}
void AstTraversalVisitor::VisitArrayLiteral(ArrayLiteral* expr) {
ZoneList<Expression*>* values = expr->values();
for (int i = 0; i < values->length(); ++i) {
Expression* value = values->at(i);
RECURSE_EXPRESSION(Visit(value));
}
}
void AstTraversalVisitor::VisitAssignment(Assignment* expr) {
RECURSE_EXPRESSION(Visit(expr->target()));
RECURSE_EXPRESSION(Visit(expr->value()));
}
void AstTraversalVisitor::VisitYield(Yield* expr) {
RECURSE_EXPRESSION(Visit(expr->generator_object()));
RECURSE_EXPRESSION(Visit(expr->expression()));
}
void AstTraversalVisitor::VisitThrow(Throw* expr) {
RECURSE_EXPRESSION(Visit(expr->exception()));
}
void AstTraversalVisitor::VisitProperty(Property* expr) {
RECURSE_EXPRESSION(Visit(expr->obj()));
RECURSE_EXPRESSION(Visit(expr->key()));
}
void AstTraversalVisitor::VisitCall(Call* expr) {
RECURSE_EXPRESSION(Visit(expr->expression()));
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
RECURSE_EXPRESSION(Visit(arg));
}
}
void AstTraversalVisitor::VisitCallNew(CallNew* expr) {
RECURSE_EXPRESSION(Visit(expr->expression()));
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
RECURSE_EXPRESSION(Visit(arg));
}
}
void AstTraversalVisitor::VisitCallRuntime(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
RECURSE_EXPRESSION(Visit(arg));
}
}
void AstTraversalVisitor::VisitUnaryOperation(UnaryOperation* expr) {
RECURSE_EXPRESSION(Visit(expr->expression()));
}
void AstTraversalVisitor::VisitCountOperation(CountOperation* expr) {
RECURSE_EXPRESSION(Visit(expr->expression()));
}
void AstTraversalVisitor::VisitBinaryOperation(BinaryOperation* expr) {
RECURSE_EXPRESSION(Visit(expr->left()));
RECURSE_EXPRESSION(Visit(expr->right()));
}
void AstTraversalVisitor::VisitCompareOperation(CompareOperation* expr) {
RECURSE_EXPRESSION(Visit(expr->left()));
RECURSE_EXPRESSION(Visit(expr->right()));
}
void AstTraversalVisitor::VisitThisFunction(ThisFunction* expr) {}
void AstTraversalVisitor::VisitClassLiteral(ClassLiteral* expr) {
if (expr->extends() != nullptr) {
RECURSE_EXPRESSION(Visit(expr->extends()));
}
RECURSE_EXPRESSION(Visit(expr->constructor()));
ZoneList<ObjectLiteralProperty*>* props = expr->properties();
for (int i = 0; i < props->length(); ++i) {
ObjectLiteralProperty* prop = props->at(i);
if (!prop->key()->IsLiteral()) {
RECURSE_EXPRESSION(Visit(prop->key()));
}
RECURSE_EXPRESSION(Visit(prop->value()));
}
}
void AstTraversalVisitor::VisitSpread(Spread* expr) {
RECURSE_EXPRESSION(Visit(expr->expression()));
}
void AstTraversalVisitor::VisitEmptyParentheses(EmptyParentheses* expr) {}
void AstTraversalVisitor::VisitSuperPropertyReference(
SuperPropertyReference* expr) {
RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
RECURSE_EXPRESSION(Visit(expr->home_object()));
}
void AstTraversalVisitor::VisitSuperCallReference(SuperCallReference* expr) {
RECURSE_EXPRESSION(VisitVariableProxy(expr->this_var()));
RECURSE_EXPRESSION(VisitVariableProxy(expr->new_target_var()));
RECURSE_EXPRESSION(VisitVariableProxy(expr->this_function_var()));
}
void AstTraversalVisitor::VisitRewritableExpression(
RewritableExpression* expr) {
RECURSE(Visit(expr->expression()));
}
#undef RECURSE_EXPRESSION
#undef RECURSE
CaseClause::CaseClause(Zone* zone, Expression* label,
ZoneList<Statement*>* statements, int pos)
: Expression(zone, pos, kCaseClause),

View File

@ -2893,7 +2893,7 @@ class EmptyParentheses final : public Expression {
template <class Subclass>
class AstVisitor BASE_EMBEDDED {
public:
void Visit(AstNode* node) { This()->Visit(node); }
void Visit(AstNode* node) { impl()->Visit(node); }
void VisitDeclarations(ZoneList<Declaration*>* declarations) {
for (int i = 0; i < declarations->length(); i++) {
@ -2920,13 +2920,13 @@ class AstVisitor BASE_EMBEDDED {
}
}
private:
Subclass* This() { return static_cast<Subclass*>(this); }
protected:
Subclass* impl() { return static_cast<Subclass*>(this); }
};
#define GENERATE_VISIT_CASE(NodeType) \
case AstNode::k##NodeType: \
return Visit##NodeType(static_cast<NodeType*>(node));
#define GENERATE_VISIT_CASE(NodeType) \
case AstNode::k##NodeType: \
return this->impl()->Visit##NodeType(static_cast<NodeType*>(node));
#define GENERATE_AST_VISITOR_SWITCH() \
switch (node->node_type()) { \
@ -3038,38 +3038,6 @@ class AstVisitor BASE_EMBEDDED {
} while (false)
// ----------------------------------------------------------------------------
// Traversing visitor
// - fully traverses the entire AST.
// This AstVistor is not final, and provides the AstVisitor methods as virtual
// methods so they can be specialized by subclasses.
class AstTraversalVisitor : public AstVisitor<AstTraversalVisitor> {
public:
explicit AstTraversalVisitor(Isolate* isolate);
explicit AstTraversalVisitor(uintptr_t stack_limit);
virtual ~AstTraversalVisitor() {}
// Iteration left-to-right.
void VisitDeclarations(ZoneList<Declaration*>* declarations);
void VisitStatements(ZoneList<Statement*>* statements);
// Individual nodes
#define DECLARE_VISIT(type) virtual void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
protected:
int depth() { return depth_; }
private:
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
int depth_;
DISALLOW_COPY_AND_ASSIGN(AstTraversalVisitor);
};
// ----------------------------------------------------------------------------
// AstNode factory

View File

@ -1857,7 +1857,7 @@ Handle<JSArray> LiveEditFunctionTracker::Collect(FunctionLiteral* node,
LiveEditFunctionTracker::LiveEditFunctionTracker(Handle<Script> script,
Zone* zone, Isolate* isolate)
: AstTraversalVisitor(isolate) {
: AstTraversalVisitor<LiveEditFunctionTracker>(isolate) {
current_parent_index_ = -1;
isolate_ = isolate;
len_ = 0;
@ -1867,20 +1867,16 @@ LiveEditFunctionTracker::LiveEditFunctionTracker(Handle<Script> script,
}
void LiveEditFunctionTracker::VisitFunctionLiteral(FunctionLiteral* node) {
Scope* scope = node->scope();
// FunctionStarted is called in pre-order.
FunctionStarted(node);
VisitDeclarations(scope->declarations());
VisitStatements(node->body());
// Recurse using the regular traversal.
AstTraversalVisitor::VisitFunctionLiteral(node);
// FunctionDone are called in post-order.
// TODO(jgruber): If required, replace the (linear cost)
// FindSharedFunctionInfo call with a more efficient implementation.
Handle<SharedFunctionInfo> info =
script_->FindSharedFunctionInfo(node).ToHandleChecked();
FunctionDone(info, scope);
FunctionDone(info, node->scope());
}
void LiveEditFunctionTracker::FunctionStarted(FunctionLiteral* fun) {

View File

@ -26,6 +26,7 @@
#include "src/allocation.h"
#include "src/ast/ast-traversal-visitor.h"
#include "src/compiler.h"
namespace v8 {
@ -38,7 +39,8 @@ namespace internal {
// in order to analyze whether function code may be safely patched (with new
// code successfully reading existing data from function scopes). The Tracker
// also collects compiled function codes.
class LiveEditFunctionTracker : public AstTraversalVisitor {
class LiveEditFunctionTracker
: public AstTraversalVisitor<LiveEditFunctionTracker> {
public:
// Traverses the entire AST, and records information about all
// FunctionLiterals for further use by LiveEdit code patching. The collected
@ -46,8 +48,9 @@ class LiveEditFunctionTracker : public AstTraversalVisitor {
static Handle<JSArray> Collect(FunctionLiteral* node, Handle<Script> script,
Zone* zone, Isolate* isolate);
virtual ~LiveEditFunctionTracker() {}
void VisitFunctionLiteral(FunctionLiteral* node) override;
protected:
friend AstTraversalVisitor<LiveEditFunctionTracker>;
void VisitFunctionLiteral(FunctionLiteral* node);
private:
LiveEditFunctionTracker(Handle<Script> script, Zone* zone, Isolate* isolate);

View File

@ -5,7 +5,7 @@
#include "src/parsing/parameter-initializer-rewriter.h"
#include "src/ast/ast.h"
#include "src/ast/ast-expression-visitor.h"
#include "src/ast/ast-traversal-visitor.h"
#include "src/ast/scopes.h"
namespace v8 {
@ -14,22 +14,24 @@ namespace internal {
namespace {
class Rewriter final : public AstExpressionVisitor {
class Rewriter final : public AstTraversalVisitor<Rewriter> {
public:
Rewriter(uintptr_t stack_limit, Expression* initializer, Scope* param_scope)
: AstExpressionVisitor(stack_limit, initializer),
: AstTraversalVisitor(stack_limit, initializer),
param_scope_(param_scope) {}
private:
void VisitExpression(Expression* expr) override {}
// This is required so that the overriden Visit* methods can be
// called by the base class (template).
friend class AstTraversalVisitor<Rewriter>;
void VisitFunctionLiteral(FunctionLiteral* expr) override;
void VisitClassLiteral(ClassLiteral* expr) override;
void VisitVariableProxy(VariableProxy* expr) override;
void VisitFunctionLiteral(FunctionLiteral* expr);
void VisitClassLiteral(ClassLiteral* expr);
void VisitVariableProxy(VariableProxy* expr);
void VisitBlock(Block* stmt) override;
void VisitTryCatchStatement(TryCatchStatement* stmt) override;
void VisitWithStatement(WithStatement* stmt) override;
void VisitBlock(Block* stmt);
void VisitTryCatchStatement(TryCatchStatement* stmt);
void VisitWithStatement(WithStatement* stmt);
Scope* param_scope_;
};

View File

@ -7,8 +7,8 @@
#include "src/api.h"
#include "src/ast/ast.h"
#include "src/ast/ast-expression-rewriter.h"
#include "src/ast/ast-expression-visitor.h"
#include "src/ast/ast-literal-reindexer.h"
#include "src/ast/ast-traversal-visitor.h"
#include "src/ast/scopeinfo.h"
#include "src/bailout-reason.h"
#include "src/base/platform/platform.h"
@ -4631,28 +4631,31 @@ Statement* Parser::BuildAssertIsCoercible(Variable* var) {
}
class InitializerRewriter : public AstExpressionVisitor {
class InitializerRewriter final
: public AstTraversalVisitor<InitializerRewriter> {
public:
InitializerRewriter(uintptr_t stack_limit, Expression* root, Parser* parser,
Scope* scope)
: AstExpressionVisitor(stack_limit, root),
: AstTraversalVisitor(stack_limit, root),
parser_(parser),
scope_(scope) {}
private:
void VisitExpression(Expression* expr) override {
RewritableExpression* to_rewrite = expr->AsRewritableExpression();
if (to_rewrite == nullptr || to_rewrite->is_rewritten()) return;
// This is required so that the overriden Visit* methods can be
// called by the base class (template).
friend class AstTraversalVisitor<InitializerRewriter>;
// Just rewrite destructuring assignments wrapped in RewritableExpressions.
void VisitRewritableExpression(RewritableExpression* to_rewrite) {
if (to_rewrite->is_rewritten()) return;
Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, to_rewrite,
scope_);
}
// Code in function literals does not need to be eagerly rewritten, it will be
// rewritten when scheduled.
void VisitFunctionLiteral(FunctionLiteral* expr) override {}
void VisitFunctionLiteral(FunctionLiteral* expr) {}
private:
Parser* parser_;
Scope* scope_;
};

View File

@ -853,7 +853,7 @@ class Parser : public ParserBase<ParserTraits> {
Scanner::Location bindings_loc;
};
class PatternRewriter final : private AstVisitor<PatternRewriter> {
class PatternRewriter final : public AstVisitor<PatternRewriter> {
public:
static void DeclareAndInitializeVariables(
Block* block, const DeclarationDescriptor* declaration_descriptor,

View File

@ -451,12 +451,11 @@
'assert-scope.cc',
'ast/ast-expression-rewriter.cc',
'ast/ast-expression-rewriter.h',
'ast/ast-expression-visitor.cc',
'ast/ast-expression-visitor.h',
'ast/ast-literal-reindexer.cc',
'ast/ast-literal-reindexer.h',
'ast/ast-numbering.cc',
'ast/ast-numbering.h',
'ast/ast-traversal-visitor.h',
'ast/ast-type-bounds.h',
'ast/ast-value-factory.cc',
'ast/ast-value-factory.h',