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

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

Issue 804003: Add defensive checks to the flow graph builder. (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
« src/compiler.cc ('K') | « src/data-flow.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
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
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
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
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
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
OLDNEW
« src/compiler.cc ('K') | « src/data-flow.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698