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

Side by Side Diff: src/data-flow.cc

Issue 1148007: Merge bleeding_edge from version 2.1.3 up to revision 4205... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: Created 10 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « src/data-flow.h ('k') | src/date.js » ('j') | src/heap.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 10 matching lines...) Expand all
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "data-flow.h" 30 #include "data-flow.h"
31 #include "scopes.h"
31 32
32 namespace v8 { 33 namespace v8 {
33 namespace internal { 34 namespace internal {
34 35
35 36
37 #ifdef DEBUG
38 void BitVector::Print() {
39 bool first = true;
40 PrintF("{");
41 for (int i = 0; i < length(); i++) {
42 if (Contains(i)) {
43 if (!first) PrintF(",");
44 first = false;
45 PrintF("%d");
46 }
47 }
48 PrintF("}");
49 }
50 #endif
51
52
36 void FlowGraph::AppendInstruction(AstNode* instruction) { 53 void FlowGraph::AppendInstruction(AstNode* instruction) {
54 // Add a (non-null) AstNode to the end of the graph fragment.
37 ASSERT(instruction != NULL); 55 ASSERT(instruction != NULL);
38 if (is_empty() || !exit()->IsBlockNode()) { 56 if (exit()->IsExitNode()) return;
39 AppendNode(new BlockNode()); 57 if (!exit()->IsBlockNode()) AppendNode(new BlockNode());
40 }
41 BlockNode::cast(exit())->AddInstruction(instruction); 58 BlockNode::cast(exit())->AddInstruction(instruction);
42 } 59 }
43 60
44 61
45 void FlowGraph::AppendNode(Node* node) { 62 void FlowGraph::AppendNode(Node* node) {
63 // Add a node to the end of the graph. An empty block is added to
64 // maintain edge-split form (that no join nodes or exit nodes as
65 // successors to branch nodes).
46 ASSERT(node != NULL); 66 ASSERT(node != NULL);
47 if (is_empty()) { 67 if (exit()->IsExitNode()) return;
48 entry_ = exit_ = node; 68 if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) {
49 } else { 69 AppendNode(new BlockNode());
50 exit()->AddSuccessor(node);
51 node->AddPredecessor(exit());
52 exit_ = node;
53 } 70 }
71 exit()->AddSuccessor(node);
72 node->AddPredecessor(exit());
73 exit_ = node;
54 } 74 }
55 75
56 76
57 void FlowGraph::AppendGraph(FlowGraph* graph) { 77 void FlowGraph::AppendGraph(FlowGraph* graph) {
58 ASSERT(!graph->is_empty()); 78 // Add a flow graph fragment to the end of this one. An empty block is
59 if (is_empty()) { 79 // added to maintain edge-split form (that no join nodes or exit nodes as
60 entry_ = graph->entry(); 80 // successors to branch nodes).
61 exit_ = graph->exit(); 81 ASSERT(graph != NULL);
62 } else { 82 if (exit()->IsExitNode()) return;
63 exit()->AddSuccessor(graph->entry()); 83 Node* node = graph->entry();
64 graph->entry()->AddPredecessor(exit()); 84 if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) {
65 exit_ = graph->exit(); 85 AppendNode(new BlockNode());
66 } 86 }
87 exit()->AddSuccessor(node);
88 node->AddPredecessor(exit());
89 exit_ = graph->exit();
67 } 90 }
68 91
69 92
70 void FlowGraph::Split(BranchNode* branch, 93 void FlowGraph::Split(BranchNode* branch,
71 FlowGraph* left, 94 FlowGraph* left,
72 FlowGraph* right, 95 FlowGraph* right,
73 JoinNode* merge) { 96 JoinNode* join) {
74 // Graphs are in edge split form. Add empty blocks if necessary. 97 // Add the branch node, left flowgraph, join node.
75 if (left->is_empty()) left->AppendNode(new BlockNode());
76 if (right->is_empty()) right->AppendNode(new BlockNode());
77
78 // Add the branch, left flowgraph and merge.
79 AppendNode(branch); 98 AppendNode(branch);
80 AppendGraph(left); 99 AppendGraph(left);
81 AppendNode(merge); 100 AppendNode(join);
82 101
83 // Splice in the right flowgraph. 102 // Splice in the right flowgraph.
84 right->AppendNode(merge); 103 right->AppendNode(join);
85 branch->AddSuccessor(right->entry()); 104 branch->AddSuccessor(right->entry());
86 right->entry()->AddPredecessor(branch); 105 right->entry()->AddPredecessor(branch);
87 } 106 }
88 107
89 108
90 void FlowGraph::Loop(JoinNode* merge, 109 void FlowGraph::Loop(JoinNode* join,
91 FlowGraph* condition, 110 FlowGraph* condition,
92 BranchNode* branch, 111 BranchNode* branch,
93 FlowGraph* body) { 112 FlowGraph* body) {
94 // Add the merge, condition and branch. Add merge's predecessors in 113 // Add the join, condition and branch. Add join's predecessors in
95 // left-to-right order. 114 // left-to-right order.
96 AppendNode(merge); 115 AppendNode(join);
97 body->AppendNode(merge); 116 body->AppendNode(join);
98 AppendGraph(condition); 117 AppendGraph(condition);
99 AppendNode(branch); 118 AppendNode(branch);
100 119
101 // Splice in the body flowgraph. 120 // Splice in the body flowgraph.
102 branch->AddSuccessor(body->entry()); 121 branch->AddSuccessor(body->entry());
103 body->entry()->AddPredecessor(branch); 122 body->entry()->AddPredecessor(branch);
104 } 123 }
105 124
106 125
107 void EntryNode::Traverse(bool mark,
108 ZoneList<Node*>* preorder,
109 ZoneList<Node*>* postorder) {
110 ASSERT(successor_ != NULL);
111 preorder->Add(this);
112 if (!successor_->IsMarkedWith(mark)) {
113 successor_->MarkWith(mark);
114 successor_->Traverse(mark, preorder, postorder);
115 }
116 postorder->Add(this);
117 }
118
119
120 void ExitNode::Traverse(bool mark, 126 void ExitNode::Traverse(bool mark,
121 ZoneList<Node*>* preorder, 127 ZoneList<Node*>* preorder,
122 ZoneList<Node*>* postorder) { 128 ZoneList<Node*>* postorder) {
123 preorder->Add(this); 129 preorder->Add(this);
124 postorder->Add(this); 130 postorder->Add(this);
125 } 131 }
126 132
127 133
128 void BlockNode::Traverse(bool mark, 134 void BlockNode::Traverse(bool mark,
129 ZoneList<Node*>* preorder, 135 ZoneList<Node*>* preorder,
130 ZoneList<Node*>* postorder) { 136 ZoneList<Node*>* postorder) {
131 ASSERT(successor_ != NULL); 137 ASSERT(successor_ != NULL);
132 preorder->Add(this); 138 preorder->Add(this);
133 if (!successor_->IsMarkedWith(mark)) { 139 if (!successor_->IsMarkedWith(mark)) {
134 successor_->MarkWith(mark); 140 successor_->MarkWith(mark);
135 successor_->Traverse(mark, preorder, postorder); 141 successor_->Traverse(mark, preorder, postorder);
136 } 142 }
137 postorder->Add(this); 143 postorder->Add(this);
138 } 144 }
139 145
140 146
141 void BranchNode::Traverse(bool mark, 147 void BranchNode::Traverse(bool mark,
142 ZoneList<Node*>* preorder, 148 ZoneList<Node*>* preorder,
143 ZoneList<Node*>* postorder) { 149 ZoneList<Node*>* postorder) {
144 ASSERT(successor0_ != NULL && successor1_ != NULL); 150 ASSERT(successor0_ != NULL && successor1_ != NULL);
145 preorder->Add(this); 151 preorder->Add(this);
152 if (!successor1_->IsMarkedWith(mark)) {
153 successor1_->MarkWith(mark);
154 successor1_->Traverse(mark, preorder, postorder);
155 }
146 if (!successor0_->IsMarkedWith(mark)) { 156 if (!successor0_->IsMarkedWith(mark)) {
147 successor0_->MarkWith(mark); 157 successor0_->MarkWith(mark);
148 successor0_->Traverse(mark, preorder, postorder); 158 successor0_->Traverse(mark, preorder, postorder);
149 } 159 }
150 if (!successor1_->IsMarkedWith(mark)) {
151 successor1_->MarkWith(mark);
152 successor1_->Traverse(mark, preorder, postorder);
153 }
154 postorder->Add(this); 160 postorder->Add(this);
155 } 161 }
156 162
157 163
158 void JoinNode::Traverse(bool mark, 164 void JoinNode::Traverse(bool mark,
159 ZoneList<Node*>* preorder, 165 ZoneList<Node*>* preorder,
160 ZoneList<Node*>* postorder) { 166 ZoneList<Node*>* postorder) {
161 ASSERT(successor_ != NULL); 167 ASSERT(successor_ != NULL);
162 preorder->Add(this); 168 preorder->Add(this);
163 if (!successor_->IsMarkedWith(mark)) { 169 if (!successor_->IsMarkedWith(mark)) {
164 successor_->MarkWith(mark); 170 successor_->MarkWith(mark);
165 successor_->Traverse(mark, preorder, postorder); 171 successor_->Traverse(mark, preorder, postorder);
166 } 172 }
167 postorder->Add(this); 173 postorder->Add(this);
168 } 174 }
169 175
170 176
171 void FlowGraphBuilder::Build(FunctionLiteral* lit) { 177 void FlowGraphBuilder::Build(FunctionLiteral* lit) {
172 graph_ = FlowGraph::Empty();
173 graph_.AppendNode(new EntryNode());
174 global_exit_ = new ExitNode(); 178 global_exit_ = new ExitNode();
175 VisitStatements(lit->body()); 179 VisitStatements(lit->body());
176 180
177 if (HasStackOverflow()) { 181 if (HasStackOverflow()) return;
178 graph_ = FlowGraph::Empty();
179 return;
180 }
181 182
183 // The graph can end with a branch node (if the function ended with a
184 // loop). Maintain edge-split form (no join nodes or exit nodes as
185 // successors to branch nodes).
186 if (graph_.exit()->IsBranchNode()) graph_.AppendNode(new BlockNode());
182 graph_.AppendNode(global_exit_); 187 graph_.AppendNode(global_exit_);
183 188
184 // Build preorder and postorder traversal orders. All the nodes in 189 // Build preorder and postorder traversal orders. All the nodes in
185 // the graph have the same mark flag. For the traversal, use that 190 // the graph have the same mark flag. For the traversal, use that
186 // flag's negation. Traversal will flip all the flags. 191 // flag's negation. Traversal will flip all the flags.
187 bool mark = graph_.entry()->IsMarkedWith(false); 192 bool mark = graph_.entry()->IsMarkedWith(false);
188 graph_.entry()->MarkWith(mark); 193 graph_.entry()->MarkWith(mark);
189 graph_.entry()->Traverse(mark, &preorder_, &postorder_); 194 graph_.entry()->Traverse(mark, &preorder_, &postorder_);
190 } 195 }
191 196
192 197
198 // This function peels off one iteration of a for-loop. The return value
199 // is either a block statement containing the peeled loop or NULL in case
200 // there is a stack overflow.
201 static Statement* PeelForLoop(ForStatement* stmt) {
202 // Mark this for-statement as processed.
203 stmt->set_peel_this_loop(false);
204
205 // Create new block containing the init statement of the for-loop and
206 // an if-statement containing the peeled iteration and the original
207 // loop without the init-statement.
208 Block* block = new Block(NULL, 2, false);
209 if (stmt->init() != NULL) {
210 Statement* init = stmt->init();
211 // The init statement gets the statement position of the for-loop
212 // to make debugging of peeled loops possible.
213 init->set_statement_pos(stmt->statement_pos());
214 block->AddStatement(init);
215 }
216
217 // Copy the condition.
218 CopyAstVisitor copy_visitor;
219 Expression* cond_copy = stmt->cond() != NULL
220 ? copy_visitor.DeepCopyExpr(stmt->cond())
221 : new Literal(Factory::true_value());
222 if (copy_visitor.HasStackOverflow()) return NULL;
223
224 // Construct a block with the peeled body and the rest of the for-loop.
225 Statement* body_copy = copy_visitor.DeepCopyStmt(stmt->body());
226 if (copy_visitor.HasStackOverflow()) return NULL;
227
228 Statement* next_copy = stmt->next() != NULL
229 ? copy_visitor.DeepCopyStmt(stmt->next())
230 : new EmptyStatement();
231 if (copy_visitor.HasStackOverflow()) return NULL;
232
233 Block* peeled_body = new Block(NULL, 3, false);
234 peeled_body->AddStatement(body_copy);
235 peeled_body->AddStatement(next_copy);
236 peeled_body->AddStatement(stmt);
237
238 // Remove the duplicated init statement from the for-statement.
239 stmt->set_init(NULL);
240
241 // Create new test at the top and add it to the newly created block.
242 IfStatement* test = new IfStatement(cond_copy,
243 peeled_body,
244 new EmptyStatement());
245 block->AddStatement(test);
246 return block;
247 }
248
249
250 void FlowGraphBuilder::VisitStatements(ZoneList<Statement*>* stmts) {
251 for (int i = 0, len = stmts->length(); i < len; i++) {
252 stmts->at(i) = ProcessStatement(stmts->at(i));
253 }
254 }
255
256
257 Statement* FlowGraphBuilder::ProcessStatement(Statement* stmt) {
258 if (FLAG_loop_peeling &&
259 stmt->AsForStatement() != NULL &&
260 stmt->AsForStatement()->peel_this_loop()) {
261 Statement* tmp_stmt = PeelForLoop(stmt->AsForStatement());
262 if (tmp_stmt == NULL) {
263 SetStackOverflow();
264 } else {
265 stmt = tmp_stmt;
266 }
267 }
268 Visit(stmt);
269 return stmt;
270 }
271
272
193 void FlowGraphBuilder::VisitDeclaration(Declaration* decl) { 273 void FlowGraphBuilder::VisitDeclaration(Declaration* decl) {
194 UNREACHABLE(); 274 UNREACHABLE();
195 } 275 }
196 276
197 277
198 void FlowGraphBuilder::VisitBlock(Block* stmt) { 278 void FlowGraphBuilder::VisitBlock(Block* stmt) {
199 VisitStatements(stmt->statements()); 279 VisitStatements(stmt->statements());
200 } 280 }
201 281
202 282
203 void FlowGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { 283 void FlowGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
204 Visit(stmt->expression()); 284 Visit(stmt->expression());
205 } 285 }
206 286
207 287
208 void FlowGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { 288 void FlowGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
209 // Nothing to do. 289 // Nothing to do.
210 } 290 }
211 291
212 292
213 void FlowGraphBuilder::VisitIfStatement(IfStatement* stmt) { 293 void FlowGraphBuilder::VisitIfStatement(IfStatement* stmt) {
214 Visit(stmt->condition()); 294 Visit(stmt->condition());
215 295
216 BranchNode* branch = new BranchNode(); 296 BranchNode* branch = new BranchNode();
217 FlowGraph original = graph_; 297 FlowGraph original = graph_;
218 graph_ = FlowGraph::Empty(); 298 graph_ = FlowGraph::Empty();
219 Visit(stmt->then_statement()); 299 stmt->set_then_statement(ProcessStatement(stmt->then_statement()));
220 300
221 FlowGraph left = graph_; 301 FlowGraph left = graph_;
222 graph_ = FlowGraph::Empty(); 302 graph_ = FlowGraph::Empty();
223 Visit(stmt->else_statement()); 303 stmt->set_else_statement(ProcessStatement(stmt->else_statement()));
224 304
305 if (HasStackOverflow()) return;
225 JoinNode* join = new JoinNode(); 306 JoinNode* join = new JoinNode();
226 original.Split(branch, &left, &graph_, join); 307 original.Split(branch, &left, &graph_, join);
227 graph_ = original; 308 graph_ = original;
228 } 309 }
229 310
230 311
231 void FlowGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { 312 void FlowGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
232 SetStackOverflow(); 313 SetStackOverflow();
233 } 314 }
234 315
235 316
236 void FlowGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { 317 void FlowGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
237 SetStackOverflow(); 318 SetStackOverflow();
238 } 319 }
239 320
240 321
241 void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { 322 void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
242 Visit(stmt->expression()); 323 SetStackOverflow();
243 graph_.AppendInstruction(stmt);
244 graph_.AppendNode(global_exit());
245 } 324 }
246 325
247 326
248 void FlowGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { 327 void FlowGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
249 Visit(stmt->expression()); 328 SetStackOverflow();
250 graph_.AppendInstruction(stmt);
251 } 329 }
252 330
253 331
254 void FlowGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { 332 void FlowGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
255 graph_.AppendInstruction(stmt); 333 SetStackOverflow();
256 } 334 }
257 335
258 336
259 void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 337 void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
260 SetStackOverflow(); 338 SetStackOverflow();
261 } 339 }
262 340
263 341
264 void FlowGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { 342 void FlowGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
265 JoinNode* join = new JoinNode(); 343 SetStackOverflow();
266 FlowGraph original = graph_;
267 graph_ = FlowGraph::Empty();
268 Visit(stmt->body());
269
270 FlowGraph body = graph_;
271 graph_ = FlowGraph::Empty();
272 Visit(stmt->cond());
273
274 BranchNode* branch = new BranchNode();
275
276 // Add body, condition and branch.
277 original.AppendNode(join);
278 original.AppendGraph(&body);
279 original.AppendGraph(&graph_); // The condition.
280 original.AppendNode(branch);
281
282 // Tie the knot.
283 branch->AddSuccessor(join);
284 join->AddPredecessor(branch);
285
286 graph_ = original;
287 } 344 }
288 345
289 346
290 void FlowGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { 347 void FlowGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
291 JoinNode* join = new JoinNode(); 348 SetStackOverflow();
292 FlowGraph original = graph_;
293 graph_ = FlowGraph::Empty();
294 Visit(stmt->cond());
295
296 BranchNode* branch = new BranchNode();
297 FlowGraph condition = graph_;
298 graph_ = FlowGraph::Empty();
299 Visit(stmt->body());
300
301 original.Loop(join, &condition, branch, &graph_);
302 graph_ = original;
303 } 349 }
304 350
305 351
306 void FlowGraphBuilder::VisitForStatement(ForStatement* stmt) { 352 void FlowGraphBuilder::VisitForStatement(ForStatement* stmt) {
307 if (stmt->init() != NULL) Visit(stmt->init()); 353 if (stmt->init() != NULL) stmt->set_init(ProcessStatement(stmt->init()));
308 354
309 JoinNode* join = new JoinNode(); 355 JoinNode* join = new JoinNode();
310 FlowGraph original = graph_; 356 FlowGraph original = graph_;
311 graph_ = FlowGraph::Empty(); 357 graph_ = FlowGraph::Empty();
312 if (stmt->cond() != NULL) Visit(stmt->cond()); 358 if (stmt->cond() != NULL) Visit(stmt->cond());
313 359
314 BranchNode* branch = new BranchNode(); 360 BranchNode* branch = new BranchNode();
315 FlowGraph condition = graph_; 361 FlowGraph condition = graph_;
316 graph_ = FlowGraph::Empty(); 362 graph_ = FlowGraph::Empty();
317 Visit(stmt->body()); 363 stmt->set_body(ProcessStatement(stmt->body()));
318 364
319 if (stmt->next() != NULL) Visit(stmt->next()); 365 if (stmt->next() != NULL) stmt->set_next(ProcessStatement(stmt->next()));
320 366
367 if (HasStackOverflow()) return;
321 original.Loop(join, &condition, branch, &graph_); 368 original.Loop(join, &condition, branch, &graph_);
322 graph_ = original; 369 graph_ = original;
323 } 370 }
324 371
325 372
326 void FlowGraphBuilder::VisitForInStatement(ForInStatement* stmt) { 373 void FlowGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
327 Visit(stmt->enumerable()); 374 SetStackOverflow();
328
329 JoinNode* join = new JoinNode();
330 FlowGraph empty;
331 BranchNode* branch = new BranchNode();
332 FlowGraph original = graph_;
333 graph_ = FlowGraph::Empty();
334 Visit(stmt->body());
335
336 original.Loop(join, &empty, branch, &graph_);
337 graph_ = original;
338 } 375 }
339 376
340 377
341 void FlowGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { 378 void FlowGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
342 SetStackOverflow(); 379 SetStackOverflow();
343 } 380 }
344 381
345 382
346 void FlowGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 383 void FlowGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
347 SetStackOverflow(); 384 SetStackOverflow();
348 } 385 }
349 386
350 387
351 void FlowGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 388 void FlowGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
352 graph_.AppendInstruction(stmt); 389 SetStackOverflow();
353 } 390 }
354 391
355 392
356 void FlowGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { 393 void FlowGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
357 graph_.AppendInstruction(expr); 394 SetStackOverflow();
358 } 395 }
359 396
360 397
361 void FlowGraphBuilder::VisitFunctionBoilerplateLiteral( 398 void FlowGraphBuilder::VisitFunctionBoilerplateLiteral(
362 FunctionBoilerplateLiteral* expr) { 399 FunctionBoilerplateLiteral* expr) {
363 graph_.AppendInstruction(expr); 400 SetStackOverflow();
364 } 401 }
365 402
366 403
367 void FlowGraphBuilder::VisitConditional(Conditional* expr) { 404 void FlowGraphBuilder::VisitConditional(Conditional* expr) {
368 Visit(expr->condition()); 405 SetStackOverflow();
369
370 BranchNode* branch = new BranchNode();
371 FlowGraph original = graph_;
372 graph_ = FlowGraph::Empty();
373 Visit(expr->then_expression());
374
375 FlowGraph left = graph_;
376 graph_ = FlowGraph::Empty();
377 Visit(expr->else_expression());
378
379 JoinNode* join = new JoinNode();
380 original.Split(branch, &left, &graph_, join);
381 graph_ = original;
382 } 406 }
383 407
384 408
385 void FlowGraphBuilder::VisitSlot(Slot* expr) { 409 void FlowGraphBuilder::VisitSlot(Slot* expr) {
386 UNREACHABLE(); 410 UNREACHABLE();
387 } 411 }
388 412
389 413
390 void FlowGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 414 void FlowGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
391 graph_.AppendInstruction(expr); 415 graph_.AppendInstruction(expr);
392 } 416 }
393 417
394 418
395 void FlowGraphBuilder::VisitLiteral(Literal* expr) { 419 void FlowGraphBuilder::VisitLiteral(Literal* expr) {
396 graph_.AppendInstruction(expr); 420 graph_.AppendInstruction(expr);
397 } 421 }
398 422
399 423
400 void FlowGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { 424 void FlowGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
401 graph_.AppendInstruction(expr); 425 SetStackOverflow();
402 } 426 }
403 427
404 428
405 void FlowGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 429 void FlowGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
406 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); 430 SetStackOverflow();
407 for (int i = 0, len = properties->length(); i < len; i++) {
408 Visit(properties->at(i)->value());
409 }
410 graph_.AppendInstruction(expr);
411 } 431 }
412 432
413 433
414 void FlowGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { 434 void FlowGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
415 ZoneList<Expression*>* values = expr->values(); 435 SetStackOverflow();
416 for (int i = 0, len = values->length(); i < len; i++) {
417 Visit(values->at(i));
418 }
419 graph_.AppendInstruction(expr);
420 } 436 }
421 437
422 438
423 void FlowGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { 439 void FlowGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
424 graph_.AppendInstruction(expr); 440 SetStackOverflow();
425 } 441 }
426 442
427 443
428 void FlowGraphBuilder::VisitAssignment(Assignment* expr) { 444 void FlowGraphBuilder::VisitAssignment(Assignment* expr) {
429 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); 445 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
430 Property* prop = expr->target()->AsProperty(); 446 Property* prop = expr->target()->AsProperty();
431 // Left-hand side can be a variable or property (or reference error) but 447 // Left-hand side can be a variable or property (or reference error) but
432 // not both. 448 // not both.
433 ASSERT(var == NULL || prop == NULL); 449 ASSERT(var == NULL || prop == NULL);
434 if (var != NULL) { 450 if (var != NULL) {
451 if (expr->is_compound()) Visit(expr->target());
435 Visit(expr->value()); 452 Visit(expr->value());
436 if (var->IsStackAllocated()) definitions_.Add(expr); 453 if (var->IsStackAllocated()) {
454 expr->set_num(definitions_.length());
455 definitions_.Add(expr);
456 }
437 457
438 } else if (prop != NULL) { 458 } else if (prop != NULL) {
439 Visit(prop->obj()); 459 Visit(prop->obj());
440 if (!prop->key()->IsPropertyName()) Visit(prop->key()); 460 if (!prop->key()->IsPropertyName()) Visit(prop->key());
441 Visit(expr->value()); 461 Visit(expr->value());
442 } 462 }
463
464 if (HasStackOverflow()) return;
443 graph_.AppendInstruction(expr); 465 graph_.AppendInstruction(expr);
444 } 466 }
445 467
446 468
447 void FlowGraphBuilder::VisitThrow(Throw* expr) { 469 void FlowGraphBuilder::VisitThrow(Throw* expr) {
448 Visit(expr->exception()); 470 SetStackOverflow();
449 graph_.AppendInstruction(expr);
450 } 471 }
451 472
452 473
453 void FlowGraphBuilder::VisitProperty(Property* expr) { 474 void FlowGraphBuilder::VisitProperty(Property* expr) {
454 Visit(expr->obj()); 475 Visit(expr->obj());
455 if (!expr->key()->IsPropertyName()) Visit(expr->key()); 476 if (!expr->key()->IsPropertyName()) Visit(expr->key());
477
478 if (HasStackOverflow()) return;
456 graph_.AppendInstruction(expr); 479 graph_.AppendInstruction(expr);
457 } 480 }
458 481
459 482
460 void FlowGraphBuilder::VisitCall(Call* expr) { 483 void FlowGraphBuilder::VisitCall(Call* expr) {
461 Visit(expr->expression()); 484 Visit(expr->expression());
462 ZoneList<Expression*>* arguments = expr->arguments(); 485 ZoneList<Expression*>* arguments = expr->arguments();
463 for (int i = 0, len = arguments->length(); i < len; i++) { 486 for (int i = 0, len = arguments->length(); i < len; i++) {
464 Visit(arguments->at(i)); 487 Visit(arguments->at(i));
465 } 488 }
489
490 if (HasStackOverflow()) return;
466 graph_.AppendInstruction(expr); 491 graph_.AppendInstruction(expr);
467 } 492 }
468 493
469 494
470 void FlowGraphBuilder::VisitCallNew(CallNew* expr) { 495 void FlowGraphBuilder::VisitCallNew(CallNew* expr) {
471 Visit(expr->expression()); 496 SetStackOverflow();
472 ZoneList<Expression*>* arguments = expr->arguments();
473 for (int i = 0, len = arguments->length(); i < len; i++) {
474 Visit(arguments->at(i));
475 }
476 graph_.AppendInstruction(expr);
477 } 497 }
478 498
479 499
480 void FlowGraphBuilder::VisitCallRuntime(CallRuntime* expr) { 500 void FlowGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
481 ZoneList<Expression*>* arguments = expr->arguments(); 501 SetStackOverflow();
482 for (int i = 0, len = arguments->length(); i < len; i++) {
483 Visit(arguments->at(i));
484 }
485 graph_.AppendInstruction(expr);
486 } 502 }
487 503
488 504
489 void FlowGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 505 void FlowGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
490 Visit(expr->expression()); 506 switch (expr->op()) {
491 graph_.AppendInstruction(expr); 507 case Token::NOT:
508 case Token::BIT_NOT:
509 case Token::DELETE:
510 case Token::TYPEOF:
511 case Token::VOID:
512 SetStackOverflow();
513 break;
514
515 case Token::ADD:
516 case Token::SUB:
517 Visit(expr->expression());
518 if (HasStackOverflow()) return;
519 graph_.AppendInstruction(expr);
520 break;
521
522 default:
523 UNREACHABLE();
524 }
492 } 525 }
493 526
494 527
495 void FlowGraphBuilder::VisitCountOperation(CountOperation* expr) { 528 void FlowGraphBuilder::VisitCountOperation(CountOperation* expr) {
496 Visit(expr->expression()); 529 Visit(expr->expression());
497 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 530 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
498 if (var != NULL && var->IsStackAllocated()) { 531 if (var != NULL && var->IsStackAllocated()) {
532 expr->set_num(definitions_.length());
499 definitions_.Add(expr); 533 definitions_.Add(expr);
500 } 534 }
535
536 if (HasStackOverflow()) return;
501 graph_.AppendInstruction(expr); 537 graph_.AppendInstruction(expr);
502 } 538 }
503 539
504 540
505 void FlowGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { 541 void FlowGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
506 Visit(expr->left());
507
508 switch (expr->op()) { 542 switch (expr->op()) {
509 case Token::COMMA: 543 case Token::COMMA:
510 Visit(expr->right()); 544 case Token::OR:
545 case Token::AND:
546 SetStackOverflow();
511 break; 547 break;
512 548
513 case Token::OR: {
514 BranchNode* branch = new BranchNode();
515 FlowGraph original = graph_;
516 graph_ = FlowGraph::Empty();
517 Visit(expr->right());
518 FlowGraph empty;
519 JoinNode* join = new JoinNode();
520 original.Split(branch, &empty, &graph_, join);
521 graph_ = original;
522 break;
523 }
524
525 case Token::AND: {
526 BranchNode* branch = new BranchNode();
527 FlowGraph original = graph_;
528 graph_ = FlowGraph::Empty();
529 Visit(expr->right());
530 FlowGraph empty;
531 JoinNode* join = new JoinNode();
532 original.Split(branch, &graph_, &empty, join);
533 graph_ = original;
534 break;
535 }
536
537 case Token::BIT_OR: 549 case Token::BIT_OR:
538 case Token::BIT_XOR: 550 case Token::BIT_XOR:
539 case Token::BIT_AND: 551 case Token::BIT_AND:
540 case Token::SHL: 552 case Token::SHL:
541 case Token::SAR:
542 case Token::SHR: 553 case Token::SHR:
543 case Token::ADD: 554 case Token::ADD:
544 case Token::SUB: 555 case Token::SUB:
545 case Token::MUL: 556 case Token::MUL:
546 case Token::DIV: 557 case Token::DIV:
547 case Token::MOD: 558 case Token::MOD:
559 case Token::SAR:
560 Visit(expr->left());
548 Visit(expr->right()); 561 Visit(expr->right());
562 if (HasStackOverflow()) return;
549 graph_.AppendInstruction(expr); 563 graph_.AppendInstruction(expr);
550 break; 564 break;
551 565
552 default: 566 default:
553 UNREACHABLE(); 567 UNREACHABLE();
554 } 568 }
555 } 569 }
556 570
557 571
558 void FlowGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 572 void FlowGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
559 Visit(expr->left()); 573 switch (expr->op()) {
560 Visit(expr->right()); 574 case Token::EQ:
561 graph_.AppendInstruction(expr); 575 case Token::NE:
576 case Token::EQ_STRICT:
577 case Token::NE_STRICT:
578 case Token::INSTANCEOF:
579 case Token::IN:
580 SetStackOverflow();
581 break;
582
583 case Token::LT:
584 case Token::GT:
585 case Token::LTE:
586 case Token::GTE:
587 Visit(expr->left());
588 Visit(expr->right());
589 if (HasStackOverflow()) return;
590 graph_.AppendInstruction(expr);
591 break;
592
593 default:
594 UNREACHABLE();
595 }
562 } 596 }
563 597
564 598
565 void FlowGraphBuilder::VisitThisFunction(ThisFunction* expr) { 599 void FlowGraphBuilder::VisitThisFunction(ThisFunction* expr) {
566 graph_.AppendInstruction(expr); 600 SetStackOverflow();
567 } 601 }
568 602
569 603
570 void AstLabeler::Label(CompilationInfo* info) { 604 void AstLabeler::Label(CompilationInfo* info) {
571 info_ = info; 605 info_ = info;
572 VisitStatements(info_->function()->body()); 606 VisitStatements(info_->function()->body());
573 } 607 }
574 608
575 609
576 void AstLabeler::VisitStatements(ZoneList<Statement*>* stmts) { 610 void AstLabeler::VisitStatements(ZoneList<Statement*>* stmts) {
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 void AstLabeler::VisitThisFunction(ThisFunction* expr) { 838 void AstLabeler::VisitThisFunction(ThisFunction* expr) {
805 UNREACHABLE(); 839 UNREACHABLE();
806 } 840 }
807 841
808 842
809 void AstLabeler::VisitDeclaration(Declaration* decl) { 843 void AstLabeler::VisitDeclaration(Declaration* decl) {
810 UNREACHABLE(); 844 UNREACHABLE();
811 } 845 }
812 846
813 847
814 ZoneList<Expression*>* VarUseMap::Lookup(Variable* var) { 848 AssignedVariablesAnalyzer::AssignedVariablesAnalyzer(FunctionLiteral* fun)
815 HashMap::Entry* entry = HashMap::Lookup(var, var->name()->Hash(), true); 849 : fun_(fun),
816 if (entry->value == NULL) { 850 av_(fun->scope()->num_parameters() + fun->scope()->num_stack_slots()) {}
817 entry->value = new ZoneList<Expression*>(1); 851
818 } 852
819 return reinterpret_cast<ZoneList<Expression*>*>(entry->value); 853 void AssignedVariablesAnalyzer::Analyze() {
820 } 854 ASSERT(av_.length() > 0);
821 855 VisitStatements(fun_->body());
822 856 }
823 void LivenessAnalyzer::Analyze(FunctionLiteral* fun) { 857
824 // Process the function body. 858
825 VisitStatements(fun->body()); 859 Variable* AssignedVariablesAnalyzer::FindSmiLoopVariable(ForStatement* stmt) {
826 860 // The loop must have all necessary parts.
827 // All variables are implicitly defined at the function start. 861 if (stmt->init() == NULL || stmt->cond() == NULL || stmt->next() == NULL) {
828 // Record a definition of all variables live at function entry. 862 return NULL;
829 for (HashMap::Entry* p = live_vars_.Start(); 863 }
830 p != NULL; 864 // The initialization statement has to be a simple assignment.
831 p = live_vars_.Next(p)) { 865 Assignment* init = stmt->init()->StatementAsSimpleAssignment();
832 Variable* var = reinterpret_cast<Variable*>(p->key); 866 if (init == NULL) return NULL;
833 RecordDef(var, fun); 867
834 } 868 // We only deal with local variables.
835 } 869 Variable* loop_var = init->target()->AsVariableProxy()->AsVariable();
836 870 if (loop_var == NULL || !loop_var->IsStackAllocated()) return NULL;
837 871
838 void LivenessAnalyzer::VisitStatements(ZoneList<Statement*>* stmts) { 872 // The initial value has to be a smi.
839 // Visit statements right-to-left. 873 Literal* init_lit = init->value()->AsLiteral();
840 for (int i = stmts->length() - 1; i >= 0; i--) { 874 if (init_lit == NULL || !init_lit->handle()->IsSmi()) return NULL;
841 Visit(stmts->at(i)); 875 int init_value = Smi::cast(*init_lit->handle())->value();
842 } 876
843 } 877 // The condition must be a compare of variable with <, <=, >, or >=.
844 878 CompareOperation* cond = stmt->cond()->AsCompareOperation();
845 879 if (cond == NULL) return NULL;
846 void LivenessAnalyzer::RecordUse(Variable* var, Expression* expr) { 880 if (cond->op() != Token::LT
847 ASSERT(var->is_global() || var->is_this()); 881 && cond->op() != Token::LTE
848 ZoneList<Expression*>* uses = live_vars_.Lookup(var); 882 && cond->op() != Token::GT
849 uses->Add(expr); 883 && cond->op() != Token::GTE) return NULL;
850 } 884
851 885 // The lhs must be the same variable as in the init expression.
852 886 if (cond->left()->AsVariableProxy()->AsVariable() != loop_var) return NULL;
853 void LivenessAnalyzer::RecordDef(Variable* var, Expression* expr) { 887
854 ASSERT(var->is_global() || var->is_this()); 888 // The rhs must be a smi.
855 889 Literal* term_lit = cond->right()->AsLiteral();
856 // We do not support other expressions that can define variables. 890 if (term_lit == NULL || !term_lit->handle()->IsSmi()) return NULL;
857 ASSERT(expr->AsFunctionLiteral() != NULL); 891 int term_value = Smi::cast(*term_lit->handle())->value();
858 892
859 // Add the variable to the list of defined variables. 893 // The count operation updates the same variable as in the init expression.
860 if (expr->defined_vars() == NULL) { 894 CountOperation* update = stmt->next()->StatementAsCountOperation();
861 expr->set_defined_vars(new ZoneList<DefinitionInfo*>(1)); 895 if (update == NULL) return NULL;
862 } 896 if (update->expression()->AsVariableProxy()->AsVariable() != loop_var) {
863 DefinitionInfo* def = new DefinitionInfo(); 897 return NULL;
864 expr->AsFunctionLiteral()->defined_vars()->Add(def); 898 }
865 899
866 // Compute the last use of the definition. The variable uses are 900 // The direction of the count operation must agree with the start and the end
867 // inserted in reversed evaluation order. The first element 901 // value. We currently do not allow the initial value to be the same as the
868 // in the list of live uses is the last use. 902 // terminal value. This _would_ be ok as long as the loop body never executes
869 ZoneList<Expression*>* uses = live_vars_.Lookup(var); 903 // or executes exactly one time.
870 while (uses->length() > 0) { 904 if (init_value == term_value) return NULL;
871 Expression* use_site = uses->RemoveLast(); 905 if (init_value < term_value && update->op() != Token::INC) return NULL;
872 use_site->set_var_def(def); 906 if (init_value > term_value && update->op() != Token::DEC) return NULL;
873 if (uses->length() == 0) { 907
874 def->set_last_use(use_site); 908 // Check that the update operation cannot overflow the smi range. This can
909 // occur in the two cases where the loop bound is equal to the largest or
910 // smallest smi.
911 if (update->op() == Token::INC && term_value == Smi::kMaxValue) return NULL;
912 if (update->op() == Token::DEC && term_value == Smi::kMinValue) return NULL;
913
914 // Found a smi loop variable.
915 return loop_var;
916 }
917
918 int AssignedVariablesAnalyzer::BitIndex(Variable* var) {
919 ASSERT(var != NULL);
920 ASSERT(var->IsStackAllocated());
921 Slot* slot = var->slot();
922 if (slot->type() == Slot::PARAMETER) {
923 return slot->index();
924 } else {
925 return fun_->scope()->num_parameters() + slot->index();
926 }
927 }
928
929
930 void AssignedVariablesAnalyzer::RecordAssignedVar(Variable* var) {
931 ASSERT(var != NULL);
932 if (var->IsStackAllocated()) {
933 av_.Add(BitIndex(var));
934 }
935 }
936
937
938 void AssignedVariablesAnalyzer::MarkIfTrivial(Expression* expr) {
939 Variable* var = expr->AsVariableProxy()->AsVariable();
940 if (var != NULL &&
941 var->IsStackAllocated() &&
942 !var->is_arguments() &&
943 var->mode() != Variable::CONST &&
944 (var->is_this() || !av_.Contains(BitIndex(var)))) {
945 expr->AsVariableProxy()->set_is_trivial(true);
946 }
947 }
948
949
950 void AssignedVariablesAnalyzer::ProcessExpression(Expression* expr) {
951 BitVector saved_av(av_);
952 av_.Clear();
953 Visit(expr);
954 av_.Union(saved_av);
955 }
956
957 void AssignedVariablesAnalyzer::VisitBlock(Block* stmt) {
958 VisitStatements(stmt->statements());
959 }
960
961
962 void AssignedVariablesAnalyzer::VisitExpressionStatement(
963 ExpressionStatement* stmt) {
964 ProcessExpression(stmt->expression());
965 }
966
967
968 void AssignedVariablesAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) {
969 // Do nothing.
970 }
971
972
973 void AssignedVariablesAnalyzer::VisitIfStatement(IfStatement* stmt) {
974 ProcessExpression(stmt->condition());
975 Visit(stmt->then_statement());
976 Visit(stmt->else_statement());
977 }
978
979
980 void AssignedVariablesAnalyzer::VisitContinueStatement(
981 ContinueStatement* stmt) {
982 // Nothing to do.
983 }
984
985
986 void AssignedVariablesAnalyzer::VisitBreakStatement(BreakStatement* stmt) {
987 // Nothing to do.
988 }
989
990
991 void AssignedVariablesAnalyzer::VisitReturnStatement(ReturnStatement* stmt) {
992 ProcessExpression(stmt->expression());
993 }
994
995
996 void AssignedVariablesAnalyzer::VisitWithEnterStatement(
997 WithEnterStatement* stmt) {
998 ProcessExpression(stmt->expression());
999 }
1000
1001
1002 void AssignedVariablesAnalyzer::VisitWithExitStatement(
1003 WithExitStatement* stmt) {
1004 // Nothing to do.
1005 }
1006
1007
1008 void AssignedVariablesAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) {
1009 BitVector result(av_);
1010 av_.Clear();
1011 Visit(stmt->tag());
1012 result.Union(av_);
1013 for (int i = 0; i < stmt->cases()->length(); i++) {
1014 CaseClause* clause = stmt->cases()->at(i);
1015 if (!clause->is_default()) {
1016 av_.Clear();
1017 Visit(clause->label());
1018 result.Union(av_);
875 } 1019 }
876 } 1020 VisitStatements(clause->statements());
877 } 1021 }
878 1022 av_.Union(result);
879 1023 }
880 // Visitor functions for live variable analysis. 1024
881 void LivenessAnalyzer::VisitDeclaration(Declaration* decl) { 1025
1026 void AssignedVariablesAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) {
1027 ProcessExpression(stmt->cond());
1028 Visit(stmt->body());
1029 }
1030
1031
1032 void AssignedVariablesAnalyzer::VisitWhileStatement(WhileStatement* stmt) {
1033 ProcessExpression(stmt->cond());
1034 Visit(stmt->body());
1035 }
1036
1037
1038 void AssignedVariablesAnalyzer::VisitForStatement(ForStatement* stmt) {
1039 if (stmt->init() != NULL) Visit(stmt->init());
1040
1041 if (stmt->cond() != NULL) ProcessExpression(stmt->cond());
1042
1043 if (stmt->next() != NULL) Visit(stmt->next());
1044
1045 // Process loop body. After visiting the loop body av_ contains
1046 // the assigned variables of the loop body.
1047 BitVector saved_av(av_);
1048 av_.Clear();
1049 Visit(stmt->body());
1050
1051 Variable* var = FindSmiLoopVariable(stmt);
1052 if (var != NULL && !av_.Contains(BitIndex(var))) {
1053 stmt->set_loop_variable(var);
1054 }
1055
1056 av_.Union(saved_av);
1057 }
1058
1059
1060 void AssignedVariablesAnalyzer::VisitForInStatement(ForInStatement* stmt) {
1061 ProcessExpression(stmt->each());
1062 ProcessExpression(stmt->enumerable());
1063 Visit(stmt->body());
1064 }
1065
1066
1067 void AssignedVariablesAnalyzer::VisitTryCatchStatement(
1068 TryCatchStatement* stmt) {
1069 Visit(stmt->try_block());
1070 Visit(stmt->catch_block());
1071 }
1072
1073
1074 void AssignedVariablesAnalyzer::VisitTryFinallyStatement(
1075 TryFinallyStatement* stmt) {
1076 Visit(stmt->try_block());
1077 Visit(stmt->finally_block());
1078 }
1079
1080
1081 void AssignedVariablesAnalyzer::VisitDebuggerStatement(
1082 DebuggerStatement* stmt) {
1083 // Nothing to do.
1084 }
1085
1086
1087 void AssignedVariablesAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) {
1088 // Nothing to do.
1089 ASSERT(av_.IsEmpty());
1090 }
1091
1092
1093 void AssignedVariablesAnalyzer::VisitFunctionBoilerplateLiteral(
1094 FunctionBoilerplateLiteral* expr) {
1095 // Nothing to do.
1096 ASSERT(av_.IsEmpty());
1097 }
1098
1099
1100 void AssignedVariablesAnalyzer::VisitConditional(Conditional* expr) {
1101 ASSERT(av_.IsEmpty());
1102
1103 Visit(expr->condition());
1104
1105 BitVector result(av_);
1106 av_.Clear();
1107 Visit(expr->then_expression());
1108 result.Union(av_);
1109
1110 av_.Clear();
1111 Visit(expr->else_expression());
1112 av_.Union(result);
1113 }
1114
1115
1116 void AssignedVariablesAnalyzer::VisitSlot(Slot* expr) {
882 UNREACHABLE(); 1117 UNREACHABLE();
883 } 1118 }
884 1119
885 1120
886 void LivenessAnalyzer::VisitBlock(Block* stmt) { 1121 void AssignedVariablesAnalyzer::VisitVariableProxy(VariableProxy* expr) {
887 VisitStatements(stmt->statements()); 1122 // Nothing to do.
888 } 1123 ASSERT(av_.IsEmpty());
889 1124 }
890 1125
891 void LivenessAnalyzer::VisitExpressionStatement( 1126
892 ExpressionStatement* stmt) { 1127 void AssignedVariablesAnalyzer::VisitLiteral(Literal* expr) {
893 Visit(stmt->expression()); 1128 // Nothing to do.
894 } 1129 ASSERT(av_.IsEmpty());
895 1130 }
896 1131
897 void LivenessAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) { 1132
898 // Do nothing. 1133 void AssignedVariablesAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) {
899 } 1134 // Nothing to do.
900 1135 ASSERT(av_.IsEmpty());
901 1136 }
902 void LivenessAnalyzer::VisitIfStatement(IfStatement* stmt) { 1137
1138
1139 void AssignedVariablesAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) {
1140 ASSERT(av_.IsEmpty());
1141 BitVector result(av_.length());
1142 for (int i = 0; i < expr->properties()->length(); i++) {
1143 Visit(expr->properties()->at(i)->value());
1144 result.Union(av_);
1145 av_.Clear();
1146 }
1147 av_ = result;
1148 }
1149
1150
1151 void AssignedVariablesAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) {
1152 ASSERT(av_.IsEmpty());
1153 BitVector result(av_.length());
1154 for (int i = 0; i < expr->values()->length(); i++) {
1155 Visit(expr->values()->at(i));
1156 result.Union(av_);
1157 av_.Clear();
1158 }
1159 av_ = result;
1160 }
1161
1162
1163 void AssignedVariablesAnalyzer::VisitCatchExtensionObject(
1164 CatchExtensionObject* expr) {
1165 ASSERT(av_.IsEmpty());
1166 Visit(expr->key());
1167 ProcessExpression(expr->value());
1168 }
1169
1170
1171 void AssignedVariablesAnalyzer::VisitAssignment(Assignment* expr) {
1172 ASSERT(av_.IsEmpty());
1173
1174 if (expr->target()->AsProperty() != NULL) {
1175 // Visit receiver and key of property store and rhs.
1176 Visit(expr->target()->AsProperty()->obj());
1177 ProcessExpression(expr->target()->AsProperty()->key());
1178 ProcessExpression(expr->value());
1179
1180 // If we have a variable as a receiver in a property store, check if
1181 // we can mark it as trivial.
1182 MarkIfTrivial(expr->target()->AsProperty()->obj());
1183 } else {
1184 Visit(expr->target());
1185 ProcessExpression(expr->value());
1186
1187 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
1188 if (var != NULL) RecordAssignedVar(var);
1189 }
1190 }
1191
1192
1193 void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) {
1194 ASSERT(av_.IsEmpty());
1195 Visit(expr->exception());
1196 }
1197
1198
1199 void AssignedVariablesAnalyzer::VisitProperty(Property* expr) {
1200 ASSERT(av_.IsEmpty());
1201 Visit(expr->obj());
1202 ProcessExpression(expr->key());
1203
1204 // In case we have a variable as a receiver, check if we can mark
1205 // it as trivial.
1206 MarkIfTrivial(expr->obj());
1207 }
1208
1209
1210 void AssignedVariablesAnalyzer::VisitCall(Call* expr) {
1211 ASSERT(av_.IsEmpty());
1212 Visit(expr->expression());
1213 BitVector result(av_);
1214 for (int i = 0; i < expr->arguments()->length(); i++) {
1215 av_.Clear();
1216 Visit(expr->arguments()->at(i));
1217 result.Union(av_);
1218 }
1219 av_ = result;
1220 }
1221
1222
1223 void AssignedVariablesAnalyzer::VisitCallNew(CallNew* expr) {
1224 ASSERT(av_.IsEmpty());
1225 Visit(expr->expression());
1226 BitVector result(av_);
1227 for (int i = 0; i < expr->arguments()->length(); i++) {
1228 av_.Clear();
1229 Visit(expr->arguments()->at(i));
1230 result.Union(av_);
1231 }
1232 av_ = result;
1233 }
1234
1235
1236 void AssignedVariablesAnalyzer::VisitCallRuntime(CallRuntime* expr) {
1237 ASSERT(av_.IsEmpty());
1238 BitVector result(av_);
1239 for (int i = 0; i < expr->arguments()->length(); i++) {
1240 av_.Clear();
1241 Visit(expr->arguments()->at(i));
1242 result.Union(av_);
1243 }
1244 av_ = result;
1245 }
1246
1247
1248 void AssignedVariablesAnalyzer::VisitUnaryOperation(UnaryOperation* expr) {
1249 ASSERT(av_.IsEmpty());
1250 Visit(expr->expression());
1251 }
1252
1253
1254 void AssignedVariablesAnalyzer::VisitCountOperation(CountOperation* expr) {
1255 ASSERT(av_.IsEmpty());
1256
1257 Visit(expr->expression());
1258
1259 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
1260 if (var != NULL) RecordAssignedVar(var);
1261 }
1262
1263
1264 void AssignedVariablesAnalyzer::VisitBinaryOperation(BinaryOperation* expr) {
1265 ASSERT(av_.IsEmpty());
1266 Visit(expr->left());
1267
1268 ProcessExpression(expr->right());
1269
1270 // In case we have a variable on the left side, check if we can mark
1271 // it as trivial.
1272 MarkIfTrivial(expr->left());
1273 }
1274
1275
1276 void AssignedVariablesAnalyzer::VisitCompareOperation(CompareOperation* expr) {
1277 ASSERT(av_.IsEmpty());
1278 Visit(expr->left());
1279
1280 ProcessExpression(expr->right());
1281
1282 // In case we have a variable on the left side, check if we can mark
1283 // it as trivial.
1284 MarkIfTrivial(expr->left());
1285 }
1286
1287
1288 void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) {
1289 // Nothing to do.
1290 ASSERT(av_.IsEmpty());
1291 }
1292
1293
1294 void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) {
903 UNREACHABLE(); 1295 UNREACHABLE();
904 } 1296 }
905 1297
906
907 void LivenessAnalyzer::VisitContinueStatement(ContinueStatement* stmt) {
908 UNREACHABLE();
909 }
910
911
912 void LivenessAnalyzer::VisitBreakStatement(BreakStatement* stmt) {
913 UNREACHABLE();
914 }
915
916
917 void LivenessAnalyzer::VisitReturnStatement(ReturnStatement* stmt) {
918 UNREACHABLE();
919 }
920
921
922 void LivenessAnalyzer::VisitWithEnterStatement(
923 WithEnterStatement* stmt) {
924 UNREACHABLE();
925 }
926
927
928 void LivenessAnalyzer::VisitWithExitStatement(WithExitStatement* stmt) {
929 UNREACHABLE();
930 }
931
932
933 void LivenessAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) {
934 UNREACHABLE();
935 }
936
937
938 void LivenessAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) {
939 UNREACHABLE();
940 }
941
942
943 void LivenessAnalyzer::VisitWhileStatement(WhileStatement* stmt) {
944 UNREACHABLE();
945 }
946
947
948 void LivenessAnalyzer::VisitForStatement(ForStatement* stmt) {
949 UNREACHABLE();
950 }
951
952
953 void LivenessAnalyzer::VisitForInStatement(ForInStatement* stmt) {
954 UNREACHABLE();
955 }
956
957
958 void LivenessAnalyzer::VisitTryCatchStatement(TryCatchStatement* stmt) {
959 UNREACHABLE();
960 }
961
962
963 void LivenessAnalyzer::VisitTryFinallyStatement(
964 TryFinallyStatement* stmt) {
965 UNREACHABLE();
966 }
967
968
969 void LivenessAnalyzer::VisitDebuggerStatement(
970 DebuggerStatement* stmt) {
971 UNREACHABLE();
972 }
973
974
975 void LivenessAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) {
976 UNREACHABLE();
977 }
978
979
980 void LivenessAnalyzer::VisitFunctionBoilerplateLiteral(
981 FunctionBoilerplateLiteral* expr) {
982 UNREACHABLE();
983 }
984
985
986 void LivenessAnalyzer::VisitConditional(Conditional* expr) {
987 UNREACHABLE();
988 }
989
990
991 void LivenessAnalyzer::VisitSlot(Slot* expr) {
992 UNREACHABLE();
993 }
994
995
996 void LivenessAnalyzer::VisitVariableProxy(VariableProxy* expr) {
997 Variable* var = expr->var();
998 ASSERT(var->is_global());
999 ASSERT(!var->is_this());
1000 RecordUse(var, expr);
1001 }
1002
1003
1004 void LivenessAnalyzer::VisitLiteral(Literal* expr) {
1005 UNREACHABLE();
1006 }
1007
1008
1009 void LivenessAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) {
1010 UNREACHABLE();
1011 }
1012
1013
1014 void LivenessAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) {
1015 UNREACHABLE();
1016 }
1017
1018
1019 void LivenessAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) {
1020 UNREACHABLE();
1021 }
1022
1023
1024 void LivenessAnalyzer::VisitCatchExtensionObject(
1025 CatchExtensionObject* expr) {
1026 UNREACHABLE();
1027 }
1028
1029
1030 void LivenessAnalyzer::VisitAssignment(Assignment* expr) {
1031 Property* prop = expr->target()->AsProperty();
1032 ASSERT(prop != NULL);
1033 ASSERT(prop->key()->IsPropertyName());
1034 VariableProxy* proxy = prop->obj()->AsVariableProxy();
1035 ASSERT(proxy != NULL && proxy->var()->is_this());
1036
1037 // Record use of this at the assignment node. Assignments to
1038 // this-properties are treated like unary operations.
1039 RecordUse(proxy->var(), expr);
1040
1041 // Visit right-hand side.
1042 Visit(expr->value());
1043 }
1044
1045
1046 void LivenessAnalyzer::VisitThrow(Throw* expr) {
1047 UNREACHABLE();
1048 }
1049
1050
1051 void LivenessAnalyzer::VisitProperty(Property* expr) {
1052 ASSERT(expr->key()->IsPropertyName());
1053 VariableProxy* proxy = expr->obj()->AsVariableProxy();
1054 ASSERT(proxy != NULL && proxy->var()->is_this());
1055 RecordUse(proxy->var(), expr);
1056 }
1057
1058
1059 void LivenessAnalyzer::VisitCall(Call* expr) {
1060 UNREACHABLE();
1061 }
1062
1063
1064 void LivenessAnalyzer::VisitCallNew(CallNew* expr) {
1065 UNREACHABLE();
1066 }
1067
1068
1069 void LivenessAnalyzer::VisitCallRuntime(CallRuntime* expr) {
1070 UNREACHABLE();
1071 }
1072
1073
1074 void LivenessAnalyzer::VisitUnaryOperation(UnaryOperation* expr) {
1075 UNREACHABLE();
1076 }
1077
1078
1079 void LivenessAnalyzer::VisitCountOperation(CountOperation* expr) {
1080 UNREACHABLE();
1081 }
1082
1083
1084 void LivenessAnalyzer::VisitBinaryOperation(BinaryOperation* expr) {
1085 // Visit child nodes in reverse evaluation order.
1086 Visit(expr->right());
1087 Visit(expr->left());
1088 }
1089
1090
1091 void LivenessAnalyzer::VisitCompareOperation(CompareOperation* expr) {
1092 UNREACHABLE();
1093 }
1094
1095
1096 void LivenessAnalyzer::VisitThisFunction(ThisFunction* expr) {
1097 UNREACHABLE();
1098 }
1099
1100 1298
1101 #ifdef DEBUG 1299 #ifdef DEBUG
1102 1300
1103 // Print a textual representation of an instruction in a flow graph. Using 1301 // Print a textual representation of an instruction in a flow graph. Using
1104 // the AstVisitor is overkill because there is no recursion here. It is 1302 // the AstVisitor is overkill because there is no recursion here. It is
1105 // only used for printing in debug mode. 1303 // only used for printing in debug mode.
1106 class TextInstructionPrinter: public AstVisitor { 1304 class TextInstructionPrinter: public AstVisitor {
1107 public: 1305 public:
1108 TextInstructionPrinter() {} 1306 TextInstructionPrinter() : number_(0) {}
1307
1308 int NextNumber() { return number_; }
1309 void AssignNumber(AstNode* node) { node->set_num(number_++); }
1109 1310
1110 private: 1311 private:
1111 // AST node visit functions. 1312 // AST node visit functions.
1112 #define DECLARE_VISIT(type) virtual void Visit##type(type* node); 1313 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
1113 AST_NODE_LIST(DECLARE_VISIT) 1314 AST_NODE_LIST(DECLARE_VISIT)
1114 #undef DECLARE_VISIT 1315 #undef DECLARE_VISIT
1115 1316
1317 int number_;
1318
1116 DISALLOW_COPY_AND_ASSIGN(TextInstructionPrinter); 1319 DISALLOW_COPY_AND_ASSIGN(TextInstructionPrinter);
1117 }; 1320 };
1118 1321
1119 1322
1120 void TextInstructionPrinter::VisitDeclaration(Declaration* decl) { 1323 void TextInstructionPrinter::VisitDeclaration(Declaration* decl) {
1121 UNREACHABLE(); 1324 UNREACHABLE();
1122 } 1325 }
1123 1326
1124 1327
1125 void TextInstructionPrinter::VisitBlock(Block* stmt) { 1328 void TextInstructionPrinter::VisitBlock(Block* stmt) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1226 1429
1227 1430
1228 void TextInstructionPrinter::VisitSlot(Slot* expr) { 1431 void TextInstructionPrinter::VisitSlot(Slot* expr) {
1229 UNREACHABLE(); 1432 UNREACHABLE();
1230 } 1433 }
1231 1434
1232 1435
1233 void TextInstructionPrinter::VisitVariableProxy(VariableProxy* expr) { 1436 void TextInstructionPrinter::VisitVariableProxy(VariableProxy* expr) {
1234 Variable* var = expr->AsVariable(); 1437 Variable* var = expr->AsVariable();
1235 if (var != NULL) { 1438 if (var != NULL) {
1236 SmartPointer<char> name = var->name()->ToCString(); 1439 PrintF("%s", *var->name()->ToCString());
1237 PrintF("%s", *name); 1440 if (var->IsStackAllocated() && expr->reaching_definitions() != NULL) {
1441 expr->reaching_definitions()->Print();
1442 }
1238 } else { 1443 } else {
1239 ASSERT(expr->AsProperty() != NULL); 1444 ASSERT(expr->AsProperty() != NULL);
1240 VisitProperty(expr->AsProperty()); 1445 VisitProperty(expr->AsProperty());
1241 } 1446 }
1242 } 1447 }
1243 1448
1244 1449
1245 void TextInstructionPrinter::VisitLiteral(Literal* expr) { 1450 void TextInstructionPrinter::VisitLiteral(Literal* expr) {
1246 expr->handle()->ShortPrint(); 1451 expr->handle()->ShortPrint();
1247 } 1452 }
(...skipping 17 matching lines...) Expand all
1265 void TextInstructionPrinter::VisitCatchExtensionObject( 1470 void TextInstructionPrinter::VisitCatchExtensionObject(
1266 CatchExtensionObject* expr) { 1471 CatchExtensionObject* expr) {
1267 PrintF("CatchExtensionObject"); 1472 PrintF("CatchExtensionObject");
1268 } 1473 }
1269 1474
1270 1475
1271 void TextInstructionPrinter::VisitAssignment(Assignment* expr) { 1476 void TextInstructionPrinter::VisitAssignment(Assignment* expr) {
1272 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); 1477 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
1273 Property* prop = expr->target()->AsProperty(); 1478 Property* prop = expr->target()->AsProperty();
1274 1479
1480 if (var == NULL && prop == NULL) {
1481 // Throw reference error.
1482 Visit(expr->target());
1483 return;
1484 }
1485
1486 // Print the left-hand side.
1275 if (var != NULL) { 1487 if (var != NULL) {
1276 SmartPointer<char> name = var->name()->ToCString(); 1488 PrintF("%s", *var->name()->ToCString());
1277 PrintF("%s %s @%d",
1278 *name,
1279 Token::String(expr->op()),
1280 expr->value()->num());
1281 } else if (prop != NULL) { 1489 } else if (prop != NULL) {
1490 PrintF("@%d", prop->obj()->num());
1282 if (prop->key()->IsPropertyName()) { 1491 if (prop->key()->IsPropertyName()) {
1283 PrintF("@%d.", prop->obj()->num()); 1492 PrintF(".");
1284 ASSERT(prop->key()->AsLiteral() != NULL); 1493 ASSERT(prop->key()->AsLiteral() != NULL);
1285 prop->key()->AsLiteral()->handle()->Print(); 1494 prop->key()->AsLiteral()->handle()->Print();
1286 PrintF(" %s @%d",
1287 Token::String(expr->op()),
1288 expr->value()->num());
1289 } else { 1495 } else {
1290 PrintF("@%d[@%d] %s @%d", 1496 PrintF("[@%d]", prop->key()->num());
1291 prop->obj()->num(),
1292 prop->key()->num(),
1293 Token::String(expr->op()),
1294 expr->value()->num());
1295 } 1497 }
1498 }
1499
1500 // Print the operation.
1501 if (expr->is_compound()) {
1502 PrintF(" = ");
1503 // Print the left-hand side again when compound.
1504 if (var != NULL) {
1505 PrintF("@%d", expr->target()->num());
1506 } else {
1507 PrintF("@%d", prop->obj()->num());
1508 if (prop->key()->IsPropertyName()) {
1509 PrintF(".");
1510 ASSERT(prop->key()->AsLiteral() != NULL);
1511 prop->key()->AsLiteral()->handle()->Print();
1512 } else {
1513 PrintF("[@%d]", prop->key()->num());
1514 }
1515 }
1516 // Print the corresponding binary operator.
1517 PrintF(" %s ", Token::String(expr->binary_op()));
1296 } else { 1518 } else {
1297 // Throw reference error. 1519 PrintF(" %s ", Token::String(expr->op()));
1298 Visit(expr->target()); 1520 }
1521
1522 // Print the right-hand side.
1523 PrintF("@%d", expr->value()->num());
1524
1525 if (expr->num() != AstNode::kNoNumber) {
1526 PrintF(" ;; D%d", expr->num());
1299 } 1527 }
1300 } 1528 }
1301 1529
1302 1530
1303 void TextInstructionPrinter::VisitThrow(Throw* expr) { 1531 void TextInstructionPrinter::VisitThrow(Throw* expr) {
1304 PrintF("throw @%d", expr->exception()->num()); 1532 PrintF("throw @%d", expr->exception()->num());
1305 } 1533 }
1306 1534
1307 1535
1308 void TextInstructionPrinter::VisitProperty(Property* expr) { 1536 void TextInstructionPrinter::VisitProperty(Property* expr) {
(...skipping 23 matching lines...) Expand all
1332 ZoneList<Expression*>* arguments = expr->arguments(); 1560 ZoneList<Expression*>* arguments = expr->arguments();
1333 for (int i = 0, len = arguments->length(); i < len; i++) { 1561 for (int i = 0, len = arguments->length(); i < len; i++) {
1334 if (i != 0) PrintF(", "); 1562 if (i != 0) PrintF(", ");
1335 PrintF("@%d", arguments->at(i)->num()); 1563 PrintF("@%d", arguments->at(i)->num());
1336 } 1564 }
1337 PrintF(")"); 1565 PrintF(")");
1338 } 1566 }
1339 1567
1340 1568
1341 void TextInstructionPrinter::VisitCallRuntime(CallRuntime* expr) { 1569 void TextInstructionPrinter::VisitCallRuntime(CallRuntime* expr) {
1342 SmartPointer<char> name = expr->name()->ToCString(); 1570 PrintF("%s(", *expr->name()->ToCString());
1343 PrintF("%s(", *name);
1344 ZoneList<Expression*>* arguments = expr->arguments(); 1571 ZoneList<Expression*>* arguments = expr->arguments();
1345 for (int i = 0, len = arguments->length(); i < len; i++) { 1572 for (int i = 0, len = arguments->length(); i < len; i++) {
1346 if (i != 0) PrintF(", "); 1573 if (i != 0) PrintF(", ");
1347 PrintF("@%d", arguments->at(i)->num()); 1574 PrintF("@%d", arguments->at(i)->num());
1348 } 1575 }
1349 PrintF(")"); 1576 PrintF(")");
1350 } 1577 }
1351 1578
1352 1579
1353 void TextInstructionPrinter::VisitUnaryOperation(UnaryOperation* expr) { 1580 void TextInstructionPrinter::VisitUnaryOperation(UnaryOperation* expr) {
1354 PrintF("%s(@%d)", Token::String(expr->op()), expr->expression()->num()); 1581 PrintF("%s(@%d)", Token::String(expr->op()), expr->expression()->num());
1355 } 1582 }
1356 1583
1357 1584
1358 void TextInstructionPrinter::VisitCountOperation(CountOperation* expr) { 1585 void TextInstructionPrinter::VisitCountOperation(CountOperation* expr) {
1359 if (expr->is_prefix()) { 1586 if (expr->is_prefix()) {
1360 PrintF("%s@%d", Token::String(expr->op()), expr->expression()->num()); 1587 PrintF("%s@%d", Token::String(expr->op()), expr->expression()->num());
1361 } else { 1588 } else {
1362 PrintF("@%d%s", expr->expression()->num(), Token::String(expr->op())); 1589 PrintF("@%d%s", expr->expression()->num(), Token::String(expr->op()));
1363 } 1590 }
1591
1592 if (expr->num() != AstNode::kNoNumber) {
1593 PrintF(" ;; D%d", expr->num());
1594 }
1364 } 1595 }
1365 1596
1366 1597
1367 void TextInstructionPrinter::VisitBinaryOperation(BinaryOperation* expr) { 1598 void TextInstructionPrinter::VisitBinaryOperation(BinaryOperation* expr) {
1368 ASSERT(expr->op() != Token::COMMA); 1599 ASSERT(expr->op() != Token::COMMA);
1369 ASSERT(expr->op() != Token::OR); 1600 ASSERT(expr->op() != Token::OR);
1370 ASSERT(expr->op() != Token::AND); 1601 ASSERT(expr->op() != Token::AND);
1371 PrintF("@%d %s @%d", 1602 PrintF("@%d %s @%d",
1372 expr->left()->num(), 1603 expr->left()->num(),
1373 Token::String(expr->op()), 1604 Token::String(expr->op()),
(...skipping 11 matching lines...) Expand all
1385 1616
1386 void TextInstructionPrinter::VisitThisFunction(ThisFunction* expr) { 1617 void TextInstructionPrinter::VisitThisFunction(ThisFunction* expr) {
1387 PrintF("ThisFunction"); 1618 PrintF("ThisFunction");
1388 } 1619 }
1389 1620
1390 1621
1391 static int node_count = 0; 1622 static int node_count = 0;
1392 static int instruction_count = 0; 1623 static int instruction_count = 0;
1393 1624
1394 1625
1395 void Node::AssignNumbers() { 1626 void Node::AssignNodeNumber() {
1396 set_number(node_count++); 1627 set_number(node_count++);
1397 } 1628 }
1398 1629
1399 1630
1400 void BlockNode::AssignNumbers() { 1631 void Node::PrintReachingDefinitions() {
1401 set_number(node_count++); 1632 if (rd_.rd_in() != NULL) {
1402 for (int i = 0, len = instructions_.length(); i < len; i++) { 1633 ASSERT(rd_.kill() != NULL && rd_.gen() != NULL);
1403 instructions_[i]->set_num(instruction_count++); 1634
1635 PrintF("RD_in = ");
1636 rd_.rd_in()->Print();
1637 PrintF("\n");
1638
1639 PrintF("RD_kill = ");
1640 rd_.kill()->Print();
1641 PrintF("\n");
1642
1643 PrintF("RD_gen = ");
1644 rd_.gen()->Print();
1645 PrintF("\n");
1404 } 1646 }
1405 } 1647 }
1406 1648
1407 1649
1408 void EntryNode::PrintText() {
1409 PrintF("L%d: Entry\n", number());
1410 PrintF("goto L%d\n\n", successor_->number());
1411 }
1412
1413 void ExitNode::PrintText() { 1650 void ExitNode::PrintText() {
1651 PrintReachingDefinitions();
1414 PrintF("L%d: Exit\n\n", number()); 1652 PrintF("L%d: Exit\n\n", number());
1415 } 1653 }
1416 1654
1417 1655
1418 void BlockNode::PrintText() { 1656 void BlockNode::PrintText() {
1657 PrintReachingDefinitions();
1419 // Print the instructions in the block. 1658 // Print the instructions in the block.
1420 PrintF("L%d: Block\n", number()); 1659 PrintF("L%d: Block\n", number());
1421 TextInstructionPrinter printer; 1660 TextInstructionPrinter printer;
1422 for (int i = 0, len = instructions_.length(); i < len; i++) { 1661 for (int i = 0, len = instructions_.length(); i < len; i++) {
1423 PrintF("%d ", instructions_[i]->num()); 1662 PrintF("%d ", printer.NextNumber());
1424 printer.Visit(instructions_[i]); 1663 printer.Visit(instructions_[i]);
1664 printer.AssignNumber(instructions_[i]);
1425 PrintF("\n"); 1665 PrintF("\n");
1426 } 1666 }
1427 PrintF("goto L%d\n\n", successor_->number()); 1667 PrintF("goto L%d\n\n", successor_->number());
1428 } 1668 }
1429 1669
1430 1670
1431 void BranchNode::PrintText() { 1671 void BranchNode::PrintText() {
1672 PrintReachingDefinitions();
1432 PrintF("L%d: Branch\n", number()); 1673 PrintF("L%d: Branch\n", number());
1433 PrintF("goto (L%d, L%d)\n\n", successor0_->number(), successor1_->number()); 1674 PrintF("goto (L%d, L%d)\n\n", successor0_->number(), successor1_->number());
1434 } 1675 }
1435 1676
1436 1677
1437 void JoinNode::PrintText() { 1678 void JoinNode::PrintText() {
1679 PrintReachingDefinitions();
1438 PrintF("L%d: Join(", number()); 1680 PrintF("L%d: Join(", number());
1439 for (int i = 0, len = predecessors_.length(); i < len; i++) { 1681 for (int i = 0, len = predecessors_.length(); i < len; i++) {
1440 if (i != 0) PrintF(", "); 1682 if (i != 0) PrintF(", ");
1441 PrintF("L%d", predecessors_[i]->number()); 1683 PrintF("L%d", predecessors_[i]->number());
1442 } 1684 }
1443 PrintF(")\ngoto L%d\n\n", successor_->number()); 1685 PrintF(")\ngoto L%d\n\n", successor_->number());
1444 } 1686 }
1445 1687
1446 1688
1447 void FlowGraph::PrintText(ZoneList<Node*>* postorder) { 1689 void FlowGraph::PrintText(FunctionLiteral* fun, ZoneList<Node*>* postorder) {
1448 PrintF("\n========\n"); 1690 PrintF("\n========\n");
1691 PrintF("name = %s\n", *fun->name()->ToCString());
1449 1692
1450 // Number nodes and instructions in reverse postorder. 1693 // Number nodes and instructions in reverse postorder.
1451 node_count = 0; 1694 node_count = 0;
1452 instruction_count = 0; 1695 instruction_count = 0;
1453 for (int i = postorder->length() - 1; i >= 0; i--) { 1696 for (int i = postorder->length() - 1; i >= 0; i--) {
1454 postorder->at(i)->AssignNumbers(); 1697 postorder->at(i)->AssignNodeNumber();
1455 } 1698 }
1456 1699
1457 // Print basic blocks in reverse postorder. 1700 // Print basic blocks in reverse postorder.
1458 for (int i = postorder->length() - 1; i >= 0; i--) { 1701 for (int i = postorder->length() - 1; i >= 0; i--) {
1459 postorder->at(i)->PrintText(); 1702 postorder->at(i)->PrintText();
1460 } 1703 }
1461 } 1704 }
1462 1705
1463 1706
1464 #endif // defined(DEBUG) 1707 #endif // defined(DEBUG)
1465 1708
1466 1709
1710 int ReachingDefinitions::IndexFor(Variable* var, int variable_count) {
1711 // Parameters are numbered left-to-right from the beginning of the bit
1712 // set. Stack-allocated locals are allocated right-to-left from the end.
1713 ASSERT(var != NULL && var->IsStackAllocated());
1714 Slot* slot = var->slot();
1715 if (slot->type() == Slot::PARAMETER) {
1716 return slot->index();
1717 } else {
1718 return (variable_count - 1) - slot->index();
1719 }
1720 }
1721
1722
1723 void Node::InitializeReachingDefinitions(int definition_count,
1724 List<BitVector*>* variables,
1725 WorkList<Node>* worklist,
1726 bool mark) {
1727 ASSERT(!IsMarkedWith(mark));
1728 rd_.Initialize(definition_count);
1729 MarkWith(mark);
1730 worklist->Insert(this);
1731 }
1732
1733
1734 void BlockNode::InitializeReachingDefinitions(int definition_count,
1735 List<BitVector*>* variables,
1736 WorkList<Node>* worklist,
1737 bool mark) {
1738 ASSERT(!IsMarkedWith(mark));
1739 int instruction_count = instructions_.length();
1740 int variable_count = variables->length();
1741
1742 rd_.Initialize(definition_count);
1743
1744 for (int i = 0; i < instruction_count; i++) {
1745 Expression* expr = instructions_[i]->AsExpression();
1746 if (expr == NULL) continue;
1747 Variable* var = expr->AssignedVar();
1748 if (var == NULL || !var->IsStackAllocated()) continue;
1749
1750 // All definitions of this variable are killed.
1751 BitVector* def_set =
1752 variables->at(ReachingDefinitions::IndexFor(var, variable_count));
1753 rd_.kill()->Union(*def_set);
1754
1755 // All previously generated definitions are not generated.
1756 rd_.gen()->Subtract(*def_set);
1757
1758 // This one is generated.
1759 rd_.gen()->Add(expr->num());
1760 }
1761
1762 // Add all blocks except the entry node to the worklist.
1763 if (predecessor_ != NULL) {
1764 MarkWith(mark);
1765 worklist->Insert(this);
1766 }
1767 }
1768
1769
1770 void ExitNode::ComputeRDOut(BitVector* result) {
1771 // Should not be the predecessor of any node.
1772 UNREACHABLE();
1773 }
1774
1775
1776 void BlockNode::ComputeRDOut(BitVector* result) {
1777 // All definitions reaching this block ...
1778 *result = *rd_.rd_in();
1779 // ... except those killed by the block ...
1780 result->Subtract(*rd_.kill());
1781 // ... but including those generated by the block.
1782 result->Union(*rd_.gen());
1783 }
1784
1785
1786 void BranchNode::ComputeRDOut(BitVector* result) {
1787 // Branch nodes don't kill or generate definitions.
1788 *result = *rd_.rd_in();
1789 }
1790
1791
1792 void JoinNode::ComputeRDOut(BitVector* result) {
1793 // Join nodes don't kill or generate definitions.
1794 *result = *rd_.rd_in();
1795 }
1796
1797
1798 void ExitNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
1799 // The exit node has no successors so we can just update in place. New
1800 // RD_in is the union over all predecessors.
1801 int definition_count = rd_.rd_in()->length();
1802 rd_.rd_in()->Clear();
1803
1804 BitVector temp(definition_count);
1805 for (int i = 0, len = predecessors_.length(); i < len; i++) {
1806 // Because ComputeRDOut always overwrites temp and its value is
1807 // always read out before calling ComputeRDOut again, we do not
1808 // have to clear it on each iteration of the loop.
1809 predecessors_[i]->ComputeRDOut(&temp);
1810 rd_.rd_in()->Union(temp);
1811 }
1812 }
1813
1814
1815 void BlockNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
1816 // The entry block has no predecessor. Its RD_in does not change.
1817 if (predecessor_ == NULL) return;
1818
1819 BitVector new_rd_in(rd_.rd_in()->length());
1820 predecessor_->ComputeRDOut(&new_rd_in);
1821
1822 if (rd_.rd_in()->Equals(new_rd_in)) return;
1823
1824 // Update RD_in.
1825 *rd_.rd_in() = new_rd_in;
1826 // Add the successor to the worklist if not already present.
1827 if (!successor_->IsMarkedWith(mark)) {
1828 successor_->MarkWith(mark);
1829 worklist->Insert(successor_);
1830 }
1831 }
1832
1833
1834 void BranchNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
1835 BitVector new_rd_in(rd_.rd_in()->length());
1836 predecessor_->ComputeRDOut(&new_rd_in);
1837
1838 if (rd_.rd_in()->Equals(new_rd_in)) return;
1839
1840 // Update RD_in.
1841 *rd_.rd_in() = new_rd_in;
1842 // Add the successors to the worklist if not already present.
1843 if (!successor0_->IsMarkedWith(mark)) {
1844 successor0_->MarkWith(mark);
1845 worklist->Insert(successor0_);
1846 }
1847 if (!successor1_->IsMarkedWith(mark)) {
1848 successor1_->MarkWith(mark);
1849 worklist->Insert(successor1_);
1850 }
1851 }
1852
1853
1854 void JoinNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
1855 int definition_count = rd_.rd_in()->length();
1856 BitVector new_rd_in(definition_count);
1857
1858 // New RD_in is the union over all predecessors.
1859 BitVector temp(definition_count);
1860 for (int i = 0, len = predecessors_.length(); i < len; i++) {
1861 predecessors_[i]->ComputeRDOut(&temp);
1862 new_rd_in.Union(temp);
1863 }
1864
1865 if (rd_.rd_in()->Equals(new_rd_in)) return;
1866
1867 // Update RD_in.
1868 *rd_.rd_in() = new_rd_in;
1869 // Add the successor to the worklist if not already present.
1870 if (!successor_->IsMarkedWith(mark)) {
1871 successor_->MarkWith(mark);
1872 worklist->Insert(successor_);
1873 }
1874 }
1875
1876
1877 void Node::PropagateReachingDefinitions(List<BitVector*>* variables) {
1878 // Nothing to do.
1879 }
1880
1881
1882 void BlockNode::PropagateReachingDefinitions(List<BitVector*>* variables) {
1883 // Propagate RD_in from the start of the block to all the variable
1884 // references.
1885 int variable_count = variables->length();
1886 BitVector rd = *rd_.rd_in();
1887 for (int i = 0, len = instructions_.length(); i < len; i++) {
1888 Expression* expr = instructions_[i]->AsExpression();
1889 if (expr == NULL) continue;
1890
1891 // Look for a variable reference to record its reaching definitions.
1892 VariableProxy* proxy = expr->AsVariableProxy();
1893 if (proxy == NULL) {
1894 // Not a VariableProxy? Maybe it's a count operation.
1895 CountOperation* count_operation = expr->AsCountOperation();
1896 if (count_operation != NULL) {
1897 proxy = count_operation->expression()->AsVariableProxy();
1898 }
1899 }
1900 if (proxy == NULL) {
1901 // OK, Maybe it's a compound assignment.
1902 Assignment* assignment = expr->AsAssignment();
1903 if (assignment != NULL && assignment->is_compound()) {
1904 proxy = assignment->target()->AsVariableProxy();
1905 }
1906 }
1907
1908 if (proxy != NULL &&
1909 proxy->var()->IsStackAllocated() &&
1910 !proxy->var()->is_this()) {
1911 // All definitions for this variable.
1912 BitVector* definitions =
1913 variables->at(ReachingDefinitions::IndexFor(proxy->var(),
1914 variable_count));
1915 BitVector* reaching_definitions = new BitVector(*definitions);
1916 // Intersected with all definitions (of any variable) reaching this
1917 // instruction.
1918 reaching_definitions->Intersect(rd);
1919 proxy->set_reaching_definitions(reaching_definitions);
1920 }
1921
1922 // It may instead (or also) be a definition. If so update the running
1923 // value of reaching definitions for the block.
1924 Variable* var = expr->AssignedVar();
1925 if (var == NULL || !var->IsStackAllocated()) continue;
1926
1927 // All definitions of this variable are killed.
1928 BitVector* def_set =
1929 variables->at(ReachingDefinitions::IndexFor(var, variable_count));
1930 rd.Subtract(*def_set);
1931 // This definition is generated.
1932 rd.Add(expr->num());
1933 }
1934 }
1935
1936
1937 void ReachingDefinitions::Compute() {
1938 ASSERT(!definitions_->is_empty());
1939
1940 int variable_count = variables_.length();
1941 int definition_count = definitions_->length();
1942 int node_count = postorder_->length();
1943
1944 // Step 1: For each variable, identify the set of all its definitions in
1945 // the body.
1946 for (int i = 0; i < definition_count; i++) {
1947 Variable* var = definitions_->at(i)->AssignedVar();
1948 variables_[IndexFor(var, variable_count)]->Add(i);
1949 }
1950
1951 if (FLAG_print_graph_text) {
1952 for (int i = 0; i < variable_count; i++) {
1953 BitVector* def_set = variables_[i];
1954 if (!def_set->IsEmpty()) {
1955 // At least one definition.
1956 bool first = true;
1957 for (int j = 0; j < definition_count; j++) {
1958 if (def_set->Contains(j)) {
1959 if (first) {
1960 Variable* var = definitions_->at(j)->AssignedVar();
1961 ASSERT(var != NULL);
1962 PrintF("Def[%s] = {%d", *var->name()->ToCString(), j);
1963 first = false;
1964 } else {
1965 PrintF(",%d", j);
1966 }
1967 }
1968 }
1969 PrintF("}\n");
1970 }
1971 }
1972 }
1973
1974 // Step 2: Compute KILL and GEN for each block node, initialize RD_in for
1975 // all nodes, and mark and add all nodes to the worklist in reverse
1976 // postorder. All nodes should currently have the same mark.
1977 bool mark = postorder_->at(0)->IsMarkedWith(false); // Negation of current.
1978 WorkList<Node> worklist(node_count);
1979 for (int i = node_count - 1; i >= 0; i--) {
1980 postorder_->at(i)->InitializeReachingDefinitions(definition_count,
1981 &variables_,
1982 &worklist,
1983 mark);
1984 }
1985
1986 // Step 3: Until the worklist is empty, remove an item compute and update
1987 // its rd_in based on its predecessor's rd_out. If rd_in has changed, add
1988 // all necessary successors to the worklist.
1989 while (!worklist.is_empty()) {
1990 Node* node = worklist.Remove();
1991 node->MarkWith(!mark);
1992 node->UpdateRDIn(&worklist, mark);
1993 }
1994
1995 // Step 4: Based on RD_in for block nodes, propagate reaching definitions
1996 // to all variable uses in the block.
1997 for (int i = 0; i < node_count; i++) {
1998 postorder_->at(i)->PropagateReachingDefinitions(&variables_);
1999 }
2000 }
2001
2002
1467 } } // namespace v8::internal 2003 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/data-flow.h ('k') | src/date.js » ('j') | src/heap.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698