 Chromium Code Reviews
 Chromium Code Reviews Issue 1565153002:
  Add a generic mechanism for expression rewriting  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 1565153002:
  Add a generic mechanism for expression rewriting  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| Index: src/ast/ast.h | 
| diff --git a/src/ast/ast.h b/src/ast/ast.h | 
| index 8c9ef323ad29b422fb735a92c0ba154e905cac9e..73d52a6a1cca9ae9b0a6b853ac9764985e7ad83f 100644 | 
| --- a/src/ast/ast.h | 
| +++ b/src/ast/ast.h | 
| @@ -505,7 +505,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(); } | 
| @@ -583,6 +585,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; | 
| } | 
| @@ -706,6 +709,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)); } | 
| @@ -734,6 +738,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(); } | 
| @@ -770,6 +775,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(); } | 
| @@ -808,6 +817,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_; } | 
| @@ -912,6 +924,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; } | 
| 
nickie
2016/01/11 10:24:18
Small fix #1: these four lines had inadvertently b
 | 
| + | 
| BailoutId ContinueId() const override { return EntryId(); } | 
| BailoutId StackCheckId() const override { return BackEdgeId(); } | 
| @@ -1000,6 +1017,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) { } | 
| @@ -1015,6 +1034,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; } | 
| @@ -1059,6 +1079,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_; } | 
| @@ -1100,6 +1121,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(); | 
| } | 
| @@ -1132,6 +1155,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; } | 
| @@ -1426,6 +1450,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_; } | 
| @@ -1799,6 +1826,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)); } | 
| @@ -1890,6 +1920,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; | 
| @@ -2009,6 +2041,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 { | 
| @@ -2118,6 +2152,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. | 
| @@ -2148,7 +2183,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; | 
| @@ -2223,6 +2260,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_; } | 
| @@ -2292,6 +2330,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 { | 
| @@ -2333,6 +2374,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(); } | 
| @@ -2356,6 +2398,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(); | 
| @@ -2395,6 +2441,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. | 
| @@ -2467,6 +2516,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); | 
| @@ -2505,6 +2556,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, | 
| @@ -2548,6 +2602,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) | 
| @@ -2767,7 +2822,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_; } | 
| @@ -2858,7 +2915,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, | 
| @@ -2879,8 +2938,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, | 
| @@ -3324,6 +3386,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; \ | 
| 
nickie
2016/01/11 10:24:18
Small fix #2: in case of failure, a non-null 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 |