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

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

Issue 1253009: Move flow graph and helper classes to their own file. (Closed)
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
« no previous file with comments | « src/flow-graph.h ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
27
28 #include "flow-graph.h"
29
30 namespace v8 {
31 namespace internal {
32
33 void FlowGraph::AppendInstruction(AstNode* instruction) {
34 // Add a (non-null) AstNode to the end of the graph fragment.
35 ASSERT(instruction != NULL);
36 if (exit()->IsExitNode()) return;
37 if (!exit()->IsBlockNode()) AppendNode(new BlockNode());
38 BlockNode::cast(exit())->AddInstruction(instruction);
39 }
40
41
42 void FlowGraph::AppendNode(Node* node) {
43 // Add a node to the end of the graph. An empty block is added to
44 // maintain edge-split form (that no join nodes or exit nodes as
45 // successors to branch nodes).
46 ASSERT(node != NULL);
47 if (exit()->IsExitNode()) return;
48 if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) {
49 AppendNode(new BlockNode());
50 }
51 exit()->AddSuccessor(node);
52 node->AddPredecessor(exit());
53 exit_ = node;
54 }
55
56
57 void FlowGraph::AppendGraph(FlowGraph* graph) {
58 // Add a flow graph fragment to the end of this one. An empty block is
59 // added to maintain edge-split form (that no join nodes or exit nodes as
60 // successors to branch nodes).
61 ASSERT(graph != NULL);
62 if (exit()->IsExitNode()) return;
63 Node* node = graph->entry();
64 if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) {
65 AppendNode(new BlockNode());
66 }
67 exit()->AddSuccessor(node);
68 node->AddPredecessor(exit());
69 exit_ = graph->exit();
70 }
71
72
73 void FlowGraph::Split(BranchNode* branch,
74 FlowGraph* left,
75 FlowGraph* right,
76 JoinNode* join) {
77 // Add the branch node, left flowgraph, join node.
78 AppendNode(branch);
79 AppendGraph(left);
80 AppendNode(join);
81
82 // Splice in the right flowgraph.
83 right->AppendNode(join);
84 branch->AddSuccessor(right->entry());
85 right->entry()->AddPredecessor(branch);
86 }
87
88
89 void FlowGraph::Loop(JoinNode* join,
90 FlowGraph* condition,
91 BranchNode* branch,
92 FlowGraph* body) {
93 // Add the join, condition and branch. Add join's predecessors in
94 // left-to-right order.
95 AppendNode(join);
96 body->AppendNode(join);
97 AppendGraph(condition);
98 AppendNode(branch);
99
100 // Splice in the body flowgraph.
101 branch->AddSuccessor(body->entry());
102 body->entry()->AddPredecessor(branch);
103 }
104
105
106 void ExitNode::Traverse(bool mark,
107 ZoneList<Node*>* preorder,
108 ZoneList<Node*>* postorder) {
109 preorder->Add(this);
110 postorder->Add(this);
111 }
112
113
114 void BlockNode::Traverse(bool mark,
115 ZoneList<Node*>* preorder,
116 ZoneList<Node*>* postorder) {
117 ASSERT(successor_ != NULL);
118 preorder->Add(this);
119 if (!successor_->IsMarkedWith(mark)) {
120 successor_->MarkWith(mark);
121 successor_->Traverse(mark, preorder, postorder);
122 }
123 postorder->Add(this);
124 }
125
126
127 void BranchNode::Traverse(bool mark,
128 ZoneList<Node*>* preorder,
129 ZoneList<Node*>* postorder) {
130 ASSERT(successor0_ != NULL && successor1_ != NULL);
131 preorder->Add(this);
132 if (!successor1_->IsMarkedWith(mark)) {
133 successor1_->MarkWith(mark);
134 successor1_->Traverse(mark, preorder, postorder);
135 }
136 if (!successor0_->IsMarkedWith(mark)) {
137 successor0_->MarkWith(mark);
138 successor0_->Traverse(mark, preorder, postorder);
139 }
140 postorder->Add(this);
141 }
142
143
144 void JoinNode::Traverse(bool mark,
145 ZoneList<Node*>* preorder,
146 ZoneList<Node*>* postorder) {
147 ASSERT(successor_ != NULL);
148 preorder->Add(this);
149 if (!successor_->IsMarkedWith(mark)) {
150 successor_->MarkWith(mark);
151 successor_->Traverse(mark, preorder, postorder);
152 }
153 postorder->Add(this);
154 }
155
156
157 void FlowGraphBuilder::Build(FunctionLiteral* lit) {
158 global_exit_ = new ExitNode();
159 VisitStatements(lit->body());
160
161 if (HasStackOverflow()) return;
162
163 // The graph can end with a branch node (if the function ended with a
164 // loop). Maintain edge-split form (no join nodes or exit nodes as
165 // successors to branch nodes).
166 if (graph_.exit()->IsBranchNode()) graph_.AppendNode(new BlockNode());
167 graph_.AppendNode(global_exit_);
168
169 // Build preorder and postorder traversal orders. All the nodes in
170 // the graph have the same mark flag. For the traversal, use that
171 // flag's negation. Traversal will flip all the flags.
172 bool mark = graph_.entry()->IsMarkedWith(false);
173 graph_.entry()->MarkWith(mark);
174 graph_.entry()->Traverse(mark, &preorder_, &postorder_);
175 }
176
177
178 // This function peels off one iteration of a for-loop. The return value
179 // is either a block statement containing the peeled loop or NULL in case
180 // there is a stack overflow.
181 static Statement* PeelForLoop(ForStatement* stmt) {
182 // Mark this for-statement as processed.
183 stmt->set_peel_this_loop(false);
184
185 // Create new block containing the init statement of the for-loop and
186 // an if-statement containing the peeled iteration and the original
187 // loop without the init-statement.
188 Block* block = new Block(NULL, 2, false);
189 if (stmt->init() != NULL) {
190 Statement* init = stmt->init();
191 // The init statement gets the statement position of the for-loop
192 // to make debugging of peeled loops possible.
193 init->set_statement_pos(stmt->statement_pos());
194 block->AddStatement(init);
195 }
196
197 // Copy the condition.
198 CopyAstVisitor copy_visitor;
199 Expression* cond_copy = stmt->cond() != NULL
200 ? copy_visitor.DeepCopyExpr(stmt->cond())
201 : new Literal(Factory::true_value());
202 if (copy_visitor.HasStackOverflow()) return NULL;
203
204 // Construct a block with the peeled body and the rest of the for-loop.
205 Statement* body_copy = copy_visitor.DeepCopyStmt(stmt->body());
206 if (copy_visitor.HasStackOverflow()) return NULL;
207
208 Statement* next_copy = stmt->next() != NULL
209 ? copy_visitor.DeepCopyStmt(stmt->next())
210 : new EmptyStatement();
211 if (copy_visitor.HasStackOverflow()) return NULL;
212
213 Block* peeled_body = new Block(NULL, 3, false);
214 peeled_body->AddStatement(body_copy);
215 peeled_body->AddStatement(next_copy);
216 peeled_body->AddStatement(stmt);
217
218 // Remove the duplicated init statement from the for-statement.
219 stmt->set_init(NULL);
220
221 // Create new test at the top and add it to the newly created block.
222 IfStatement* test = new IfStatement(cond_copy,
223 peeled_body,
224 new EmptyStatement());
225 block->AddStatement(test);
226 return block;
227 }
228
229
230 void FlowGraphBuilder::VisitStatements(ZoneList<Statement*>* stmts) {
231 for (int i = 0, len = stmts->length(); i < len; i++) {
232 stmts->at(i) = ProcessStatement(stmts->at(i));
233 }
234 }
235
236
237 Statement* FlowGraphBuilder::ProcessStatement(Statement* stmt) {
238 if (FLAG_loop_peeling &&
239 stmt->AsForStatement() != NULL &&
240 stmt->AsForStatement()->peel_this_loop()) {
241 Statement* tmp_stmt = PeelForLoop(stmt->AsForStatement());
242 if (tmp_stmt == NULL) {
243 SetStackOverflow();
244 } else {
245 stmt = tmp_stmt;
246 }
247 }
248 Visit(stmt);
249 return stmt;
250 }
251
252
253 void FlowGraphBuilder::VisitDeclaration(Declaration* decl) {
254 UNREACHABLE();
255 }
256
257
258 void FlowGraphBuilder::VisitBlock(Block* stmt) {
259 VisitStatements(stmt->statements());
260 }
261
262
263 void FlowGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
264 Visit(stmt->expression());
265 }
266
267
268 void FlowGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
269 // Nothing to do.
270 }
271
272
273 void FlowGraphBuilder::VisitIfStatement(IfStatement* stmt) {
274 Visit(stmt->condition());
275
276 BranchNode* branch = new BranchNode();
277 FlowGraph original = graph_;
278 graph_ = FlowGraph::Empty();
279 stmt->set_then_statement(ProcessStatement(stmt->then_statement()));
280
281 FlowGraph left = graph_;
282 graph_ = FlowGraph::Empty();
283 stmt->set_else_statement(ProcessStatement(stmt->else_statement()));
284
285 if (HasStackOverflow()) return;
286 JoinNode* join = new JoinNode();
287 original.Split(branch, &left, &graph_, join);
288 graph_ = original;
289 }
290
291
292 void FlowGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
293 SetStackOverflow();
294 }
295
296
297 void FlowGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
298 SetStackOverflow();
299 }
300
301
302 void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
303 SetStackOverflow();
304 }
305
306
307 void FlowGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
308 SetStackOverflow();
309 }
310
311
312 void FlowGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
313 SetStackOverflow();
314 }
315
316
317 void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
318 SetStackOverflow();
319 }
320
321
322 void FlowGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
323 SetStackOverflow();
324 }
325
326
327 void FlowGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
328 SetStackOverflow();
329 }
330
331
332 void FlowGraphBuilder::VisitForStatement(ForStatement* stmt) {
333 if (stmt->init() != NULL) stmt->set_init(ProcessStatement(stmt->init()));
334
335 JoinNode* join = new JoinNode();
336 FlowGraph original = graph_;
337 graph_ = FlowGraph::Empty();
338 if (stmt->cond() != NULL) Visit(stmt->cond());
339
340 BranchNode* branch = new BranchNode();
341 FlowGraph condition = graph_;
342 graph_ = FlowGraph::Empty();
343 stmt->set_body(ProcessStatement(stmt->body()));
344
345 if (stmt->next() != NULL) stmt->set_next(ProcessStatement(stmt->next()));
346
347 if (HasStackOverflow()) return;
348 original.Loop(join, &condition, branch, &graph_);
349 graph_ = original;
350 }
351
352
353 void FlowGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
354 SetStackOverflow();
355 }
356
357
358 void FlowGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
359 SetStackOverflow();
360 }
361
362
363 void FlowGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
364 SetStackOverflow();
365 }
366
367
368 void FlowGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
369 SetStackOverflow();
370 }
371
372
373 void FlowGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
374 SetStackOverflow();
375 }
376
377
378 void FlowGraphBuilder::VisitSharedFunctionInfoLiteral(
379 SharedFunctionInfoLiteral* expr) {
380 SetStackOverflow();
381 }
382
383
384 void FlowGraphBuilder::VisitConditional(Conditional* expr) {
385 SetStackOverflow();
386 }
387
388
389 void FlowGraphBuilder::VisitSlot(Slot* expr) {
390 UNREACHABLE();
391 }
392
393
394 void FlowGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
395 graph_.AppendInstruction(expr);
396 }
397
398
399 void FlowGraphBuilder::VisitLiteral(Literal* expr) {
400 graph_.AppendInstruction(expr);
401 }
402
403
404 void FlowGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
405 SetStackOverflow();
406 }
407
408
409 void FlowGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
410 SetStackOverflow();
411 }
412
413
414 void FlowGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
415 SetStackOverflow();
416 }
417
418
419 void FlowGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
420 SetStackOverflow();
421 }
422
423
424 void FlowGraphBuilder::VisitAssignment(Assignment* expr) {
425 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
426 Property* prop = expr->target()->AsProperty();
427 // Left-hand side can be a variable or property (or reference error) but
428 // not both.
429 ASSERT(var == NULL || prop == NULL);
430 if (var != NULL) {
431 if (expr->is_compound()) Visit(expr->target());
432 Visit(expr->value());
433 if (var->IsStackAllocated()) {
434 // The first definition in the body is numbered n, where n is the
435 // number of parameters and stack-allocated locals.
436 expr->set_num(body_definitions_.length() + variable_count_);
437 body_definitions_.Add(expr);
438 }
439
440 } else if (prop != NULL) {
441 Visit(prop->obj());
442 if (!prop->key()->IsPropertyName()) Visit(prop->key());
443 Visit(expr->value());
444 }
445
446 if (HasStackOverflow()) return;
447 graph_.AppendInstruction(expr);
448 }
449
450
451 void FlowGraphBuilder::VisitThrow(Throw* expr) {
452 SetStackOverflow();
453 }
454
455
456 void FlowGraphBuilder::VisitProperty(Property* expr) {
457 Visit(expr->obj());
458 if (!expr->key()->IsPropertyName()) Visit(expr->key());
459
460 if (HasStackOverflow()) return;
461 graph_.AppendInstruction(expr);
462 }
463
464
465 void FlowGraphBuilder::VisitCall(Call* expr) {
466 Visit(expr->expression());
467 ZoneList<Expression*>* arguments = expr->arguments();
468 for (int i = 0, len = arguments->length(); i < len; i++) {
469 Visit(arguments->at(i));
470 }
471
472 if (HasStackOverflow()) return;
473 graph_.AppendInstruction(expr);
474 }
475
476
477 void FlowGraphBuilder::VisitCallNew(CallNew* expr) {
478 SetStackOverflow();
479 }
480
481
482 void FlowGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
483 SetStackOverflow();
484 }
485
486
487 void FlowGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
488 switch (expr->op()) {
489 case Token::NOT:
490 case Token::BIT_NOT:
491 case Token::DELETE:
492 case Token::TYPEOF:
493 case Token::VOID:
494 SetStackOverflow();
495 break;
496
497 case Token::ADD:
498 case Token::SUB:
499 Visit(expr->expression());
500 if (HasStackOverflow()) return;
501 graph_.AppendInstruction(expr);
502 break;
503
504 default:
505 UNREACHABLE();
506 }
507 }
508
509
510 void FlowGraphBuilder::VisitCountOperation(CountOperation* expr) {
511 Visit(expr->expression());
512 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
513 if (var != NULL && var->IsStackAllocated()) {
514 // The first definition in the body is numbered n, where n is the number
515 // of parameters and stack-allocated locals.
516 expr->set_num(body_definitions_.length() + variable_count_);
517 body_definitions_.Add(expr);
518 }
519
520 if (HasStackOverflow()) return;
521 graph_.AppendInstruction(expr);
522 }
523
524
525 void FlowGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
526 switch (expr->op()) {
527 case Token::COMMA:
528 case Token::OR:
529 case Token::AND:
530 SetStackOverflow();
531 break;
532
533 case Token::BIT_OR:
534 case Token::BIT_XOR:
535 case Token::BIT_AND:
536 case Token::SHL:
537 case Token::SHR:
538 case Token::ADD:
539 case Token::SUB:
540 case Token::MUL:
541 case Token::DIV:
542 case Token::MOD:
543 case Token::SAR:
544 Visit(expr->left());
545 Visit(expr->right());
546 if (HasStackOverflow()) return;
547 graph_.AppendInstruction(expr);
548 break;
549
550 default:
551 UNREACHABLE();
552 }
553 }
554
555
556 void FlowGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
557 switch (expr->op()) {
558 case Token::EQ:
559 case Token::NE:
560 case Token::EQ_STRICT:
561 case Token::NE_STRICT:
562 case Token::INSTANCEOF:
563 case Token::IN:
564 SetStackOverflow();
565 break;
566
567 case Token::LT:
568 case Token::GT:
569 case Token::LTE:
570 case Token::GTE:
571 Visit(expr->left());
572 Visit(expr->right());
573 if (HasStackOverflow()) return;
574 graph_.AppendInstruction(expr);
575 break;
576
577 default:
578 UNREACHABLE();
579 }
580 }
581
582
583 void FlowGraphBuilder::VisitThisFunction(ThisFunction* expr) {
584 SetStackOverflow();
585 }
586
587
588 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/flow-graph.h ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698