Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Side by Side Diff: src/rewriter.cc

Issue 1362363002: Enable visitor in rewriter to replace statements. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ast.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/rewriter.h" 5 #include "src/rewriter.h"
6 6
7 #include "src/ast.h" 7 #include "src/ast.h"
8 #include "src/parser.h" 8 #include "src/parser.h"
9 #include "src/scopes.h" 9 #include "src/scopes.h"
10 10
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 13
14 class Processor: public AstVisitor { 14 class Processor: public AstVisitor {
15 public: 15 public:
16 Processor(Isolate* isolate, Variable* result, 16 Processor(Isolate* isolate, Variable* result,
17 AstValueFactory* ast_value_factory) 17 AstValueFactory* ast_value_factory)
18 : result_(result), 18 : result_(result),
19 result_assigned_(false), 19 result_assigned_(false),
20 replacement_(nullptr),
20 is_set_(false), 21 is_set_(false),
21 factory_(ast_value_factory) { 22 factory_(ast_value_factory) {
22 InitializeAstVisitor(isolate, ast_value_factory->zone()); 23 InitializeAstVisitor(isolate, ast_value_factory->zone());
23 } 24 }
24 25
25 virtual ~Processor() { } 26 virtual ~Processor() { }
26 27
27 void Process(ZoneList<Statement*>* statements); 28 void Process(ZoneList<Statement*>* statements);
28 bool result_assigned() const { return result_assigned_; } 29 bool result_assigned() const { return result_assigned_; }
29 30
30 AstNodeFactory* factory() { return &factory_; } 31 AstNodeFactory* factory() { return &factory_; }
31 32
32 private: 33 private:
33 Variable* result_; 34 Variable* result_;
34 35
35 // We are not tracking result usage via the result_'s use 36 // We are not tracking result usage via the result_'s use
36 // counts (we leave the accurate computation to the 37 // counts (we leave the accurate computation to the
37 // usage analyzer). Instead we simple remember if 38 // usage analyzer). Instead we simple remember if
38 // there was ever an assignment to result_. 39 // there was ever an assignment to result_.
39 bool result_assigned_; 40 bool result_assigned_;
40 41
42 // When visiting a node, we "return" a replacement for that node in
43 // [replacement_]. In many cases this will just be the original node.
44 Statement* replacement_;
45
41 // To avoid storing to .result all the time, we eliminate some of 46 // To avoid storing to .result all the time, we eliminate some of
42 // the stores by keeping track of whether or not we're sure .result 47 // the stores by keeping track of whether or not we're sure .result
43 // will be overwritten anyway. This is a bit more tricky than what I 48 // will be overwritten anyway. This is a bit more tricky than what I
44 // was hoping for. 49 // was hoping for.
45 bool is_set_; 50 bool is_set_;
46 51
47 AstNodeFactory factory_; 52 AstNodeFactory factory_;
48 53
49 Expression* SetResult(Expression* value) { 54 Expression* SetResult(Expression* value) {
50 result_assigned_ = true; 55 result_assigned_ = true;
51 VariableProxy* result_proxy = factory()->NewVariableProxy(result_); 56 VariableProxy* result_proxy = factory()->NewVariableProxy(result_);
52 return factory()->NewAssignment( 57 return factory()->NewAssignment(
53 Token::ASSIGN, result_proxy, value, RelocInfo::kNoPosition); 58 Token::ASSIGN, result_proxy, value, RelocInfo::kNoPosition);
54 } 59 }
55 60
56 // Node visitors. 61 // Node visitors.
57 #define DEF_VISIT(type) virtual void Visit##type(type* node) override; 62 #define DEF_VISIT(type) virtual void Visit##type(type* node) override;
58 AST_NODE_LIST(DEF_VISIT) 63 AST_NODE_LIST(DEF_VISIT)
59 #undef DEF_VISIT 64 #undef DEF_VISIT
60 65
61 void VisitIterationStatement(IterationStatement* stmt); 66 void VisitIterationStatement(IterationStatement* stmt);
62 67
63 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); 68 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
64 }; 69 };
65 70
66 71
67 void Processor::Process(ZoneList<Statement*>* statements) { 72 void Processor::Process(ZoneList<Statement*>* statements) {
68 for (int i = statements->length() - 1; i >= 0; --i) { 73 for (int i = statements->length() - 1; i >= 0; --i) {
69 Visit(statements->at(i)); 74 Visit(statements->at(i));
75 statements->Set(i, replacement_);
70 } 76 }
71 } 77 }
72 78
73 79
74 void Processor::VisitBlock(Block* node) { 80 void Processor::VisitBlock(Block* node) {
75 // An initializer block is the rewritten form of a variable declaration 81 // An initializer block is the rewritten form of a variable declaration
76 // with initialization expressions. The initializer block contains the 82 // with initialization expressions. The initializer block contains the
77 // list of assignments corresponding to the initialization expressions. 83 // list of assignments corresponding to the initialization expressions.
78 // While unclear from the spec (ECMA-262, 3rd., 12.2), the value of 84 // While unclear from the spec (ECMA-262, 3rd., 12.2), the value of
79 // a variable declaration with initialization expression is 'undefined' 85 // a variable declaration with initialization expression is 'undefined'
80 // with some JS VMs: For instance, using smjs, print(eval('var x = 7')) 86 // with some JS VMs: For instance, using smjs, print(eval('var x = 7'))
81 // returns 'undefined'. To obtain the same behavior with v8, we need 87 // returns 'undefined'. To obtain the same behavior with v8, we need
82 // to prevent rewriting in that case. 88 // to prevent rewriting in that case.
83 if (!node->ignore_completion_value()) Process(node->statements()); 89 if (!node->ignore_completion_value()) Process(node->statements());
90 replacement_ = node;
84 } 91 }
85 92
86 93
87 void Processor::VisitExpressionStatement(ExpressionStatement* node) { 94 void Processor::VisitExpressionStatement(ExpressionStatement* node) {
88 // Rewrite : <x>; -> .result = <x>; 95 // Rewrite : <x>; -> .result = <x>;
89 if (!is_set_) { 96 if (!is_set_) {
90 node->set_expression(SetResult(node->expression())); 97 node->set_expression(SetResult(node->expression()));
91 is_set_ = true; 98 is_set_ = true;
92 } 99 }
100 replacement_ = node;
93 } 101 }
94 102
95 103
96 void Processor::VisitIfStatement(IfStatement* node) { 104 void Processor::VisitIfStatement(IfStatement* node) {
97 // Rewrite both branches. 105 // Rewrite both branches.
98 bool set_after = is_set_; 106 bool set_after = is_set_;
99 Visit(node->then_statement()); 107 Visit(node->then_statement());
108 node->set_then_statement(replacement_);
100 bool set_in_then = is_set_; 109 bool set_in_then = is_set_;
101 is_set_ = set_after; 110 is_set_ = set_after;
102 Visit(node->else_statement()); 111 Visit(node->else_statement());
112 node->set_else_statement(replacement_);
103 is_set_ = is_set_ && set_in_then; 113 is_set_ = is_set_ && set_in_then;
114 replacement_ = node;
104 } 115 }
105 116
106 117
107 void Processor::VisitIterationStatement(IterationStatement* node) { 118 void Processor::VisitIterationStatement(IterationStatement* node) {
108 // Rewrite the body. 119 // Rewrite the body.
109 bool set_after = is_set_; 120 bool set_after = is_set_;
110 is_set_ = false; // We are in a loop, so we can't rely on [set_after]. 121 is_set_ = false; // We are in a loop, so we can't rely on [set_after].
111 Visit(node->body()); 122 Visit(node->body());
123 node->set_body(replacement_);
112 is_set_ = is_set_ && set_after; 124 is_set_ = is_set_ && set_after;
125 replacement_ = node;
113 } 126 }
114 127
115 128
116 void Processor::VisitDoWhileStatement(DoWhileStatement* node) { 129 void Processor::VisitDoWhileStatement(DoWhileStatement* node) {
117 VisitIterationStatement(node); 130 VisitIterationStatement(node);
118 } 131 }
119 132
120 133
121 void Processor::VisitWhileStatement(WhileStatement* node) { 134 void Processor::VisitWhileStatement(WhileStatement* node) {
122 VisitIterationStatement(node); 135 VisitIterationStatement(node);
(...skipping 12 matching lines...) Expand all
135 148
136 void Processor::VisitForOfStatement(ForOfStatement* node) { 149 void Processor::VisitForOfStatement(ForOfStatement* node) {
137 VisitIterationStatement(node); 150 VisitIterationStatement(node);
138 } 151 }
139 152
140 153
141 void Processor::VisitTryCatchStatement(TryCatchStatement* node) { 154 void Processor::VisitTryCatchStatement(TryCatchStatement* node) {
142 // Rewrite both try and catch block. 155 // Rewrite both try and catch block.
143 bool set_after = is_set_; 156 bool set_after = is_set_;
144 Visit(node->try_block()); 157 Visit(node->try_block());
158 node->set_try_block(static_cast<Block*>(replacement_));
145 bool set_in_try = is_set_; 159 bool set_in_try = is_set_;
146 is_set_ = set_after; 160 is_set_ = set_after;
147 Visit(node->catch_block()); 161 Visit(node->catch_block());
162 node->set_catch_block(static_cast<Block*>(replacement_));
148 is_set_ = is_set_ && set_in_try; 163 is_set_ = is_set_ && set_in_try;
164 replacement_ = node;
149 } 165 }
150 166
151 167
152 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) { 168 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
153 // Rewrite both try and finally block (in reverse order). 169 // Rewrite both try and finally block (in reverse order).
154 Visit(node->finally_block()); 170 Visit(node->finally_block());
155 Visit(node->try_block()); 171 node->set_finally_block(replacement_->AsBlock());
172 Visit(node->try_block()); // Exception will not be caught.
173 node->set_try_block(replacement_->AsBlock());
174 replacement_ = node;
156 } 175 }
157 176
158 177
159 void Processor::VisitSwitchStatement(SwitchStatement* node) { 178 void Processor::VisitSwitchStatement(SwitchStatement* node) {
160 // Rewrite statements in all case clauses (in reverse order). 179 // Rewrite statements in all case clauses (in reverse order).
161 ZoneList<CaseClause*>* clauses = node->cases(); 180 ZoneList<CaseClause*>* clauses = node->cases();
162 bool set_after = is_set_; 181 bool set_after = is_set_;
163 for (int i = clauses->length() - 1; i >= 0; --i) { 182 for (int i = clauses->length() - 1; i >= 0; --i) {
164 CaseClause* clause = clauses->at(i); 183 CaseClause* clause = clauses->at(i);
165 Process(clause->statements()); 184 Process(clause->statements());
166 } 185 }
167 is_set_ = is_set_ && set_after; 186 is_set_ = is_set_ && set_after;
187 replacement_ = node;
168 } 188 }
169 189
170 190
171 void Processor::VisitContinueStatement(ContinueStatement* node) { 191 void Processor::VisitContinueStatement(ContinueStatement* node) {
172 is_set_ = false; 192 is_set_ = false;
193 replacement_ = node;
173 } 194 }
174 195
175 196
176 void Processor::VisitBreakStatement(BreakStatement* node) { 197 void Processor::VisitBreakStatement(BreakStatement* node) {
177 is_set_ = false; 198 is_set_ = false;
199 replacement_ = node;
178 } 200 }
179 201
180 202
181 void Processor::VisitWithStatement(WithStatement* node) { 203 void Processor::VisitWithStatement(WithStatement* node) {
182 Visit(node->statement()); 204 Visit(node->statement());
205 node->set_statement(replacement_);
206 replacement_ = node;
183 } 207 }
184 208
185 209
186 void Processor::VisitSloppyBlockFunctionStatement( 210 void Processor::VisitSloppyBlockFunctionStatement(
187 SloppyBlockFunctionStatement* node) { 211 SloppyBlockFunctionStatement* node) {
188 Visit(node->statement()); 212 Visit(node->statement());
213 node->set_statement(replacement_);
214 replacement_ = node;
189 } 215 }
190 216
191 217
192 void Processor::VisitReturnStatement(ReturnStatement* node) { is_set_ = true; } 218 void Processor::VisitEmptyStatement(EmptyStatement* node) {
219 replacement_ = node;
220 }
193 221
194 222
195 // Do nothing: 223 void Processor::VisitReturnStatement(ReturnStatement* node) {
196 void Processor::VisitEmptyStatement(EmptyStatement* node) {} 224 is_set_ = true;
197 void Processor::VisitDebuggerStatement(DebuggerStatement* node) {} 225 replacement_ = node;
226 }
227
228
229 void Processor::VisitDebuggerStatement(DebuggerStatement* node) {
230 replacement_ = node;
231 }
198 232
199 233
200 // Expressions are never visited. 234 // Expressions are never visited.
201 #define DEF_VISIT(type) \ 235 #define DEF_VISIT(type) \
202 void Processor::Visit##type(type* expr) { UNREACHABLE(); } 236 void Processor::Visit##type(type* expr) { UNREACHABLE(); }
203 EXPRESSION_NODE_LIST(DEF_VISIT) 237 EXPRESSION_NODE_LIST(DEF_VISIT)
204 #undef DEF_VISIT 238 #undef DEF_VISIT
205 239
206 240
207 // Declarations are never visited. 241 // Declarations are never visited.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 body->Add(result_statement, info->zone()); 280 body->Add(result_statement, info->zone());
247 } 281 }
248 } 282 }
249 283
250 return true; 284 return true;
251 } 285 }
252 286
253 287
254 } // namespace internal 288 } // namespace internal
255 } // namespace v8 289 } // namespace v8
OLDNEW
« no previous file with comments | « src/ast.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698