OLD | NEW |
---|---|
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 16 matching lines...) Expand all Loading... | |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "data-flow.h" | 30 #include "data-flow.h" |
31 | 31 |
32 namespace v8 { | 32 namespace v8 { |
33 namespace internal { | 33 namespace internal { |
34 | 34 |
35 | 35 |
36 void FlowGraph::AppendInstruction(AstNode* instruction) { | 36 void FlowGraph::AppendInstruction(AstNode* instruction) { |
37 // Add a (non-null) AstNode to the end of the graph fragment. | |
37 ASSERT(instruction != NULL); | 38 ASSERT(instruction != NULL); |
38 if (is_empty() || !exit()->IsBlockNode()) { | 39 if (exit()->IsExitNode()) return; |
39 AppendNode(new BlockNode()); | 40 if (!exit()->IsBlockNode()) AppendNode(new BlockNode()); |
40 } | |
41 BlockNode::cast(exit())->AddInstruction(instruction); | 41 BlockNode::cast(exit())->AddInstruction(instruction); |
42 } | 42 } |
43 | 43 |
44 | 44 |
45 void FlowGraph::AppendNode(Node* node) { | 45 void FlowGraph::AppendNode(Node* node) { |
46 // Add a node to the end of the graph. An empty block is added to | |
47 // maintain edge-split form (that no join nodes or exit nodes as | |
48 // successors to branch nodes). | |
46 ASSERT(node != NULL); | 49 ASSERT(node != NULL); |
47 if (is_empty()) { | 50 if (exit()->IsExitNode()) return; |
48 entry_ = exit_ = node; | 51 if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) { |
49 } else { | 52 AppendNode(new BlockNode()); |
50 exit()->AddSuccessor(node); | |
51 node->AddPredecessor(exit()); | |
52 exit_ = node; | |
53 } | 53 } |
54 exit()->AddSuccessor(node); | |
55 node->AddPredecessor(exit()); | |
56 exit_ = node; | |
54 } | 57 } |
55 | 58 |
56 | 59 |
57 void FlowGraph::AppendGraph(FlowGraph* graph) { | 60 void FlowGraph::AppendGraph(FlowGraph* graph) { |
58 ASSERT(!graph->is_empty()); | 61 // Add a flow graph fragment to the end of this one. An empty block is |
59 if (is_empty()) { | 62 // added to maintain edge-split form (that no join nodes or exit nodes as |
60 entry_ = graph->entry(); | 63 // successors to branch nodes). |
fschneider
2010/03/10 16:51:09
Maybe ASSERT(graph != NULL) for consistency with t
| |
61 exit_ = graph->exit(); | 64 if (exit()->IsExitNode()) return; |
62 } else { | 65 Node* node = graph->entry(); |
63 exit()->AddSuccessor(graph->entry()); | 66 if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) { |
64 graph->entry()->AddPredecessor(exit()); | 67 AppendNode(new BlockNode()); |
65 exit_ = graph->exit(); | |
66 } | 68 } |
69 exit()->AddSuccessor(node); | |
70 node->AddPredecessor(exit()); | |
71 exit_ = graph->exit(); | |
67 } | 72 } |
68 | 73 |
69 | 74 |
70 void FlowGraph::Split(BranchNode* branch, | 75 void FlowGraph::Split(BranchNode* branch, |
71 FlowGraph* left, | 76 FlowGraph* left, |
72 FlowGraph* right, | 77 FlowGraph* right, |
73 JoinNode* merge) { | 78 JoinNode* join) { |
74 // Graphs are in edge split form. Add empty blocks if necessary. | 79 // 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); | 80 AppendNode(branch); |
80 AppendGraph(left); | 81 AppendGraph(left); |
81 AppendNode(merge); | 82 AppendNode(join); |
82 | 83 |
83 // Splice in the right flowgraph. | 84 // Splice in the right flowgraph. |
84 right->AppendNode(merge); | 85 right->AppendNode(join); |
85 branch->AddSuccessor(right->entry()); | 86 branch->AddSuccessor(right->entry()); |
86 right->entry()->AddPredecessor(branch); | 87 right->entry()->AddPredecessor(branch); |
87 } | 88 } |
88 | 89 |
89 | 90 |
90 void FlowGraph::Loop(JoinNode* merge, | 91 void FlowGraph::Loop(JoinNode* join, |
91 FlowGraph* condition, | 92 FlowGraph* condition, |
92 BranchNode* branch, | 93 BranchNode* branch, |
93 FlowGraph* body) { | 94 FlowGraph* body) { |
94 // Add the merge, condition and branch. Add merge's predecessors in | 95 // Add the join, condition and branch. Add join's predecessors in |
95 // left-to-right order. | 96 // left-to-right order. |
96 AppendNode(merge); | 97 AppendNode(join); |
97 body->AppendNode(merge); | 98 body->AppendNode(join); |
98 AppendGraph(condition); | 99 AppendGraph(condition); |
99 AppendNode(branch); | 100 AppendNode(branch); |
100 | 101 |
101 // Splice in the body flowgraph. | 102 // Splice in the body flowgraph. |
102 branch->AddSuccessor(body->entry()); | 103 branch->AddSuccessor(body->entry()); |
103 body->entry()->AddPredecessor(branch); | 104 body->entry()->AddPredecessor(branch); |
104 } | 105 } |
105 | 106 |
106 | 107 |
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, | 108 void ExitNode::Traverse(bool mark, |
121 ZoneList<Node*>* preorder, | 109 ZoneList<Node*>* preorder, |
122 ZoneList<Node*>* postorder) { | 110 ZoneList<Node*>* postorder) { |
123 preorder->Add(this); | 111 preorder->Add(this); |
124 postorder->Add(this); | 112 postorder->Add(this); |
125 } | 113 } |
126 | 114 |
127 | 115 |
128 void BlockNode::Traverse(bool mark, | 116 void BlockNode::Traverse(bool mark, |
129 ZoneList<Node*>* preorder, | 117 ZoneList<Node*>* preorder, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
162 preorder->Add(this); | 150 preorder->Add(this); |
163 if (!successor_->IsMarkedWith(mark)) { | 151 if (!successor_->IsMarkedWith(mark)) { |
164 successor_->MarkWith(mark); | 152 successor_->MarkWith(mark); |
165 successor_->Traverse(mark, preorder, postorder); | 153 successor_->Traverse(mark, preorder, postorder); |
166 } | 154 } |
167 postorder->Add(this); | 155 postorder->Add(this); |
168 } | 156 } |
169 | 157 |
170 | 158 |
171 void FlowGraphBuilder::Build(FunctionLiteral* lit) { | 159 void FlowGraphBuilder::Build(FunctionLiteral* lit) { |
172 graph_ = FlowGraph::Empty(); | |
173 graph_.AppendNode(new EntryNode()); | |
174 global_exit_ = new ExitNode(); | 160 global_exit_ = new ExitNode(); |
175 VisitStatements(lit->body()); | 161 VisitStatements(lit->body()); |
176 | 162 |
177 if (HasStackOverflow()) { | 163 if (HasStackOverflow()) return; |
178 graph_ = FlowGraph::Empty(); | |
179 return; | |
180 } | |
181 | 164 |
165 // The graph can end with a branch node (if the function ended with a | |
166 // loop). Maintain edge-split form (no join nodes or exit nodes as | |
167 // successors to branch nodes). | |
168 if (graph_.exit()->IsBranchNode()) graph_.AppendNode(new BlockNode()); | |
182 graph_.AppendNode(global_exit_); | 169 graph_.AppendNode(global_exit_); |
183 | 170 |
184 // Build preorder and postorder traversal orders. All the nodes in | 171 // Build preorder and postorder traversal orders. All the nodes in |
185 // the graph have the same mark flag. For the traversal, use that | 172 // the graph have the same mark flag. For the traversal, use that |
186 // flag's negation. Traversal will flip all the flags. | 173 // flag's negation. Traversal will flip all the flags. |
187 bool mark = graph_.entry()->IsMarkedWith(false); | 174 bool mark = graph_.entry()->IsMarkedWith(false); |
188 graph_.entry()->MarkWith(mark); | 175 graph_.entry()->MarkWith(mark); |
189 graph_.entry()->Traverse(mark, &preorder_, &postorder_); | 176 graph_.entry()->Traverse(mark, &preorder_, &postorder_); |
190 } | 177 } |
191 | 178 |
(...skipping 23 matching lines...) Expand all Loading... | |
215 | 202 |
216 BranchNode* branch = new BranchNode(); | 203 BranchNode* branch = new BranchNode(); |
217 FlowGraph original = graph_; | 204 FlowGraph original = graph_; |
218 graph_ = FlowGraph::Empty(); | 205 graph_ = FlowGraph::Empty(); |
219 Visit(stmt->then_statement()); | 206 Visit(stmt->then_statement()); |
220 | 207 |
221 FlowGraph left = graph_; | 208 FlowGraph left = graph_; |
222 graph_ = FlowGraph::Empty(); | 209 graph_ = FlowGraph::Empty(); |
223 Visit(stmt->else_statement()); | 210 Visit(stmt->else_statement()); |
224 | 211 |
212 if (HasStackOverflow()) return; | |
225 JoinNode* join = new JoinNode(); | 213 JoinNode* join = new JoinNode(); |
226 original.Split(branch, &left, &graph_, join); | 214 original.Split(branch, &left, &graph_, join); |
227 graph_ = original; | 215 graph_ = original; |
228 } | 216 } |
229 | 217 |
230 | 218 |
231 void FlowGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { | 219 void FlowGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { |
232 SetStackOverflow(); | 220 SetStackOverflow(); |
233 } | 221 } |
234 | 222 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
276 graph_ = FlowGraph::Empty(); | 264 graph_ = FlowGraph::Empty(); |
277 if (stmt->cond() != NULL) Visit(stmt->cond()); | 265 if (stmt->cond() != NULL) Visit(stmt->cond()); |
278 | 266 |
279 BranchNode* branch = new BranchNode(); | 267 BranchNode* branch = new BranchNode(); |
280 FlowGraph condition = graph_; | 268 FlowGraph condition = graph_; |
281 graph_ = FlowGraph::Empty(); | 269 graph_ = FlowGraph::Empty(); |
282 Visit(stmt->body()); | 270 Visit(stmt->body()); |
283 | 271 |
284 if (stmt->next() != NULL) Visit(stmt->next()); | 272 if (stmt->next() != NULL) Visit(stmt->next()); |
285 | 273 |
274 if (HasStackOverflow()) return; | |
286 original.Loop(join, &condition, branch, &graph_); | 275 original.Loop(join, &condition, branch, &graph_); |
287 graph_ = original; | 276 graph_ = original; |
288 } | 277 } |
289 | 278 |
290 | 279 |
291 void FlowGraphBuilder::VisitForInStatement(ForInStatement* stmt) { | 280 void FlowGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
292 SetStackOverflow(); | 281 SetStackOverflow(); |
293 } | 282 } |
294 | 283 |
295 | 284 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 ASSERT(var == NULL || prop == NULL); | 356 ASSERT(var == NULL || prop == NULL); |
368 if (var != NULL) { | 357 if (var != NULL) { |
369 Visit(expr->value()); | 358 Visit(expr->value()); |
370 if (var->IsStackAllocated()) definitions_.Add(expr); | 359 if (var->IsStackAllocated()) definitions_.Add(expr); |
371 | 360 |
372 } else if (prop != NULL) { | 361 } else if (prop != NULL) { |
373 Visit(prop->obj()); | 362 Visit(prop->obj()); |
374 if (!prop->key()->IsPropertyName()) Visit(prop->key()); | 363 if (!prop->key()->IsPropertyName()) Visit(prop->key()); |
375 Visit(expr->value()); | 364 Visit(expr->value()); |
376 } | 365 } |
366 | |
367 if (HasStackOverflow()) return; | |
377 graph_.AppendInstruction(expr); | 368 graph_.AppendInstruction(expr); |
378 } | 369 } |
379 | 370 |
380 | 371 |
381 void FlowGraphBuilder::VisitThrow(Throw* expr) { | 372 void FlowGraphBuilder::VisitThrow(Throw* expr) { |
382 SetStackOverflow(); | 373 SetStackOverflow(); |
383 } | 374 } |
384 | 375 |
385 | 376 |
386 void FlowGraphBuilder::VisitProperty(Property* expr) { | 377 void FlowGraphBuilder::VisitProperty(Property* expr) { |
387 Visit(expr->obj()); | 378 Visit(expr->obj()); |
388 if (!expr->key()->IsPropertyName()) Visit(expr->key()); | 379 if (!expr->key()->IsPropertyName()) Visit(expr->key()); |
380 | |
381 if (HasStackOverflow()) return; | |
389 graph_.AppendInstruction(expr); | 382 graph_.AppendInstruction(expr); |
390 } | 383 } |
391 | 384 |
392 | 385 |
393 void FlowGraphBuilder::VisitCall(Call* expr) { | 386 void FlowGraphBuilder::VisitCall(Call* expr) { |
394 Visit(expr->expression()); | 387 Visit(expr->expression()); |
395 ZoneList<Expression*>* arguments = expr->arguments(); | 388 ZoneList<Expression*>* arguments = expr->arguments(); |
396 for (int i = 0, len = arguments->length(); i < len; i++) { | 389 for (int i = 0, len = arguments->length(); i < len; i++) { |
397 Visit(arguments->at(i)); | 390 Visit(arguments->at(i)); |
398 } | 391 } |
392 | |
393 if (HasStackOverflow()) return; | |
399 graph_.AppendInstruction(expr); | 394 graph_.AppendInstruction(expr); |
400 } | 395 } |
401 | 396 |
402 | 397 |
403 void FlowGraphBuilder::VisitCallNew(CallNew* expr) { | 398 void FlowGraphBuilder::VisitCallNew(CallNew* expr) { |
404 SetStackOverflow(); | 399 SetStackOverflow(); |
405 } | 400 } |
406 | 401 |
407 | 402 |
408 void FlowGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 403 void FlowGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
409 SetStackOverflow(); | 404 SetStackOverflow(); |
410 } | 405 } |
411 | 406 |
412 | 407 |
413 void FlowGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 408 void FlowGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
414 switch (expr->op()) { | 409 switch (expr->op()) { |
415 case Token::NOT: | 410 case Token::NOT: |
416 case Token::BIT_NOT: | 411 case Token::BIT_NOT: |
417 case Token::DELETE: | 412 case Token::DELETE: |
418 case Token::TYPEOF: | 413 case Token::TYPEOF: |
419 case Token::VOID: | 414 case Token::VOID: |
420 SetStackOverflow(); | 415 SetStackOverflow(); |
421 break; | 416 break; |
422 | 417 |
423 case Token::ADD: | 418 case Token::ADD: |
424 case Token::SUB: | 419 case Token::SUB: |
425 Visit(expr->expression()); | 420 Visit(expr->expression()); |
421 if (HasStackOverflow()) return; | |
426 graph_.AppendInstruction(expr); | 422 graph_.AppendInstruction(expr); |
427 break; | 423 break; |
428 | 424 |
429 default: | 425 default: |
430 UNREACHABLE(); | 426 UNREACHABLE(); |
431 } | 427 } |
432 } | 428 } |
433 | 429 |
434 | 430 |
435 void FlowGraphBuilder::VisitCountOperation(CountOperation* expr) { | 431 void FlowGraphBuilder::VisitCountOperation(CountOperation* expr) { |
436 Visit(expr->expression()); | 432 Visit(expr->expression()); |
437 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 433 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
438 if (var != NULL && var->IsStackAllocated()) { | 434 if (var != NULL && var->IsStackAllocated()) { |
439 definitions_.Add(expr); | 435 definitions_.Add(expr); |
440 } | 436 } |
437 | |
438 if (HasStackOverflow()) return; | |
441 graph_.AppendInstruction(expr); | 439 graph_.AppendInstruction(expr); |
442 } | 440 } |
443 | 441 |
444 | 442 |
445 void FlowGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 443 void FlowGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
446 switch (expr->op()) { | 444 switch (expr->op()) { |
447 case Token::COMMA: | 445 case Token::COMMA: |
448 case Token::OR: | 446 case Token::OR: |
449 case Token::AND: | 447 case Token::AND: |
450 SetStackOverflow(); | 448 SetStackOverflow(); |
451 break; | 449 break; |
452 | 450 |
453 case Token::BIT_OR: | 451 case Token::BIT_OR: |
454 case Token::BIT_XOR: | 452 case Token::BIT_XOR: |
455 case Token::BIT_AND: | 453 case Token::BIT_AND: |
456 case Token::SHL: | 454 case Token::SHL: |
457 case Token::SHR: | 455 case Token::SHR: |
458 case Token::ADD: | 456 case Token::ADD: |
459 case Token::SUB: | 457 case Token::SUB: |
460 case Token::MUL: | 458 case Token::MUL: |
461 case Token::DIV: | 459 case Token::DIV: |
462 case Token::MOD: | 460 case Token::MOD: |
463 case Token::SAR: | 461 case Token::SAR: |
464 Visit(expr->left()); | 462 Visit(expr->left()); |
465 Visit(expr->right()); | 463 Visit(expr->right()); |
464 if (HasStackOverflow()) return; | |
466 graph_.AppendInstruction(expr); | 465 graph_.AppendInstruction(expr); |
467 break; | 466 break; |
468 | 467 |
469 default: | 468 default: |
470 UNREACHABLE(); | 469 UNREACHABLE(); |
471 } | 470 } |
472 } | 471 } |
473 | 472 |
474 | 473 |
475 void FlowGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 474 void FlowGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
476 switch (expr->op()) { | 475 switch (expr->op()) { |
477 case Token::EQ: | 476 case Token::EQ: |
478 case Token::NE: | 477 case Token::NE: |
479 case Token::EQ_STRICT: | 478 case Token::EQ_STRICT: |
480 case Token::NE_STRICT: | 479 case Token::NE_STRICT: |
481 case Token::INSTANCEOF: | 480 case Token::INSTANCEOF: |
482 case Token::IN: | 481 case Token::IN: |
483 SetStackOverflow(); | 482 SetStackOverflow(); |
484 break; | 483 break; |
485 | 484 |
486 case Token::LT: | 485 case Token::LT: |
487 case Token::GT: | 486 case Token::GT: |
488 case Token::LTE: | 487 case Token::LTE: |
489 case Token::GTE: | 488 case Token::GTE: |
490 Visit(expr->left()); | 489 Visit(expr->left()); |
491 Visit(expr->right()); | 490 Visit(expr->right()); |
491 if (HasStackOverflow()) return; | |
492 graph_.AppendInstruction(expr); | 492 graph_.AppendInstruction(expr); |
493 break; | 493 break; |
494 | 494 |
495 default: | 495 default: |
496 UNREACHABLE(); | 496 UNREACHABLE(); |
497 } | 497 } |
498 } | 498 } |
499 | 499 |
500 | 500 |
501 void FlowGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 501 void FlowGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1334 | 1334 |
1335 | 1335 |
1336 void BlockNode::AssignNumbers() { | 1336 void BlockNode::AssignNumbers() { |
1337 set_number(node_count++); | 1337 set_number(node_count++); |
1338 for (int i = 0, len = instructions_.length(); i < len; i++) { | 1338 for (int i = 0, len = instructions_.length(); i < len; i++) { |
1339 instructions_[i]->set_num(instruction_count++); | 1339 instructions_[i]->set_num(instruction_count++); |
1340 } | 1340 } |
1341 } | 1341 } |
1342 | 1342 |
1343 | 1343 |
1344 void EntryNode::PrintText() { | |
1345 PrintF("L%d: Entry\n", number()); | |
1346 PrintF("goto L%d\n\n", successor_->number()); | |
1347 } | |
1348 | |
1349 void ExitNode::PrintText() { | 1344 void ExitNode::PrintText() { |
1350 PrintF("L%d: Exit\n\n", number()); | 1345 PrintF("L%d: Exit\n\n", number()); |
1351 } | 1346 } |
1352 | 1347 |
1353 | 1348 |
1354 void BlockNode::PrintText() { | 1349 void BlockNode::PrintText() { |
1355 // Print the instructions in the block. | 1350 // Print the instructions in the block. |
1356 PrintF("L%d: Block\n", number()); | 1351 PrintF("L%d: Block\n", number()); |
1357 TextInstructionPrinter printer; | 1352 TextInstructionPrinter printer; |
1358 for (int i = 0, len = instructions_.length(); i < len; i++) { | 1353 for (int i = 0, len = instructions_.length(); i < len; i++) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1394 for (int i = postorder->length() - 1; i >= 0; i--) { | 1389 for (int i = postorder->length() - 1; i >= 0; i--) { |
1395 postorder->at(i)->PrintText(); | 1390 postorder->at(i)->PrintText(); |
1396 } | 1391 } |
1397 } | 1392 } |
1398 | 1393 |
1399 | 1394 |
1400 #endif // defined(DEBUG) | 1395 #endif // defined(DEBUG) |
1401 | 1396 |
1402 | 1397 |
1403 } } // namespace v8::internal | 1398 } } // namespace v8::internal |
OLD | NEW |