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:
parent
0840e20764
commit
e54927244a
2
BUILD.gn
2
BUILD.gn
@ -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",
|
||||
|
409
src/ast/ast-expression-rewriter.cc
Normal file
409
src/ast/ast-expression-rewriter.cc
Normal 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
|
54
src/ast/ast-expression-rewriter.h
Normal file
54
src/ast/ast-expression-rewriter.h
Normal 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_
|
125
src/ast/ast.h
125
src/ast/ast.h
@ -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
|
||||
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user