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

Side by Side Diff: src/cfg.cc

Issue 160584: Add support to the CFG builder for non-short-circuited binary... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 4 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/cfg.h ('k') | src/ia32/cfg-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 24 matching lines...) Expand all
35 namespace v8 { 35 namespace v8 {
36 namespace internal { 36 namespace internal {
37 37
38 38
39 CfgGlobals* CfgGlobals::top_ = NULL; 39 CfgGlobals* CfgGlobals::top_ = NULL;
40 40
41 41
42 CfgGlobals::CfgGlobals(FunctionLiteral* fun) 42 CfgGlobals::CfgGlobals(FunctionLiteral* fun)
43 : global_fun_(fun), 43 : global_fun_(fun),
44 global_exit_(new ExitNode()), 44 global_exit_(new ExitNode()),
45 effect_(new Effect()),
45 #ifdef DEBUG 46 #ifdef DEBUG
46 node_counter_(0), 47 node_counter_(0),
48 temp_counter_(0),
47 #endif 49 #endif
48 previous_(top_) { 50 previous_(top_) {
49 top_ = this; 51 top_ = this;
50 } 52 }
51 53
52 54
53 #define BAILOUT(reason) \ 55 #define BAILOUT(reason) \
54 do { return NULL; } while (false) 56 do { return NULL; } while (false)
55 57
56 Cfg* Cfg::Build() { 58 Cfg* Cfg::Build() {
57 FunctionLiteral* fun = CfgGlobals::current()->fun(); 59 FunctionLiteral* fun = CfgGlobals::current()->fun();
58 if (fun->scope()->num_heap_slots() > 0) { 60 if (fun->scope()->num_heap_slots() > 0) {
59 BAILOUT("function has context slots"); 61 BAILOUT("function has context slots");
60 } 62 }
61 if (fun->scope()->arguments() != NULL) { 63 if (fun->scope()->arguments() != NULL) {
62 BAILOUT("function uses .arguments"); 64 BAILOUT("function uses .arguments");
63 } 65 }
64 66
65 ZoneList<Statement*>* body = fun->body(); 67 ZoneList<Statement*>* body = fun->body();
66 if (body->is_empty()) { 68 if (body->is_empty()) {
67 BAILOUT("empty function body"); 69 BAILOUT("empty function body");
68 } 70 }
69 71
70 StatementBuilder builder; 72 StatementBuilder builder;
71 builder.VisitStatements(body); 73 builder.VisitStatements(body);
72 Cfg* cfg = builder.cfg(); 74 Cfg* cfg = builder.cfg();
73 if (cfg == NULL) { 75 if (cfg == NULL) {
74 BAILOUT("unsupported statement type"); 76 BAILOUT("unsupported statement type");
75 } 77 }
78 if (cfg->is_empty()) {
79 BAILOUT("function body produces empty cfg");
80 }
76 if (cfg->has_exit()) { 81 if (cfg->has_exit()) {
77 BAILOUT("control path without explicit return"); 82 BAILOUT("control path without explicit return");
78 } 83 }
79 cfg->PrependEntryNode(); 84 cfg->PrependEntryNode();
80 return cfg; 85 return cfg;
81 } 86 }
82 87
83 #undef BAILOUT 88 #undef BAILOUT
84 89
85 90
86 void Cfg::PrependEntryNode() { 91 void Cfg::PrependEntryNode() {
87 ASSERT(!is_empty()); 92 ASSERT(!is_empty());
88 entry_ = new EntryNode(InstructionBlock::cast(entry())); 93 entry_ = new EntryNode(InstructionBlock::cast(entry()));
89 } 94 }
90 95
91 96
92 void Cfg::Append(Instruction* instr) { 97 void Cfg::Append(Instruction* instr) {
93 ASSERT(has_exit()); 98 ASSERT(is_empty() || has_exit());
94 ASSERT(!is_empty()); 99 if (is_empty()) {
100 entry_ = exit_ = new InstructionBlock();
101 }
95 InstructionBlock::cast(exit_)->Append(instr); 102 InstructionBlock::cast(exit_)->Append(instr);
96 } 103 }
97 104
98 105
99 void Cfg::AppendReturnInstruction(Value* value) { 106 void Cfg::AppendReturnInstruction(Value* value) {
100 Append(new ReturnInstr(value)); 107 Append(new ReturnInstr(value));
101 ExitNode* global_exit = CfgGlobals::current()->exit(); 108 ExitNode* global_exit = CfgGlobals::current()->exit();
102 InstructionBlock::cast(exit_)->set_successor(global_exit); 109 InstructionBlock::cast(exit_)->set_successor(global_exit);
103 exit_ = NULL; 110 exit_ = NULL;
104 } 111 }
105 112
106 113
114 void Cfg::Concatenate(Cfg* other) {
115 ASSERT(is_empty() || has_exit());
116 if (other->is_empty()) return;
117
118 if (is_empty()) {
119 entry_ = other->entry();
120 exit_ = other->exit();
121 } else {
122 // We have a pair of nonempty fragments and this has an available exit.
123 // Destructively glue the fragments together.
124 InstructionBlock* first = InstructionBlock::cast(exit_);
125 InstructionBlock* second = InstructionBlock::cast(other->entry());
126 first->instructions()->AddAll(*second->instructions());
127 if (second->successor() != NULL) {
128 first->set_successor(second->successor());
129 exit_ = other->exit();
130 }
131 }
132 }
133
134
107 void InstructionBlock::Unmark() { 135 void InstructionBlock::Unmark() {
108 if (is_marked_) { 136 if (is_marked_) {
109 is_marked_ = false; 137 is_marked_ = false;
110 successor_->Unmark(); 138 successor_->Unmark();
111 } 139 }
112 } 140 }
113 141
114 142
115 void EntryNode::Unmark() { 143 void EntryNode::Unmark() {
116 if (is_marked_) { 144 if (is_marked_) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 } 187 }
160 PrintF("--- Code ---\n"); 188 PrintF("--- Code ---\n");
161 code->Disassemble(*fun->name()->ToCString()); 189 code->Disassemble(*fun->name()->ToCString());
162 } 190 }
163 #endif 191 #endif
164 192
165 return code; 193 return code;
166 } 194 }
167 195
168 196
197 void BinaryOpInstr::FastAllocate(TempLocation* temp) {
198 ASSERT(temp->where() == TempLocation::NOWHERE);
199 if (temp == val0_ || temp == val1_) {
200 temp->set_where(TempLocation::ACCUMULATOR);
201 } else {
202 temp->set_where(TempLocation::STACK);
203 }
204 }
205
206
207 void ReturnInstr::FastAllocate(TempLocation* temp) {
208 ASSERT(temp->where() == TempLocation::NOWHERE);
209 if (temp == value_) {
210 temp->set_where(TempLocation::ACCUMULATOR);
211 } else {
212 temp->set_where(TempLocation::STACK);
213 }
214 }
215
216
169 // The expression builder should not be used for declarations or statements. 217 // The expression builder should not be used for declarations or statements.
170 void ExpressionBuilder::VisitDeclaration(Declaration* decl) { UNREACHABLE(); } 218 void ExpressionBuilder::VisitDeclaration(Declaration* decl) { UNREACHABLE(); }
171 219
172 #define DEFINE_VISIT(type) \ 220 #define DEFINE_VISIT(type) \
173 void ExpressionBuilder::Visit##type(type* stmt) { UNREACHABLE(); } 221 void ExpressionBuilder::Visit##type(type* stmt) { UNREACHABLE(); }
174 STATEMENT_NODE_LIST(DEFINE_VISIT) 222 STATEMENT_NODE_LIST(DEFINE_VISIT)
175 #undef DEFINE_VISIT 223 #undef DEFINE_VISIT
176 224
177 225
178 // Macros (temporarily) handling unsupported expression types. 226 // Macros (temporarily) handling unsupported expression types.
179 #define BAILOUT(reason) \ 227 #define BAILOUT(reason) \
180 do { \ 228 do { \
181 value_ = NULL; \ 229 cfg_ = NULL; \
182 return; \ 230 return; \
183 } while (false) 231 } while (false)
184 232
185 #define CHECK_BAILOUT() \
186 if (value_ == NULL) { return; } else {}
187
188 void ExpressionBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { 233 void ExpressionBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
189 BAILOUT("FunctionLiteral"); 234 BAILOUT("FunctionLiteral");
190 } 235 }
191 236
192 237
193 void ExpressionBuilder::VisitFunctionBoilerplateLiteral( 238 void ExpressionBuilder::VisitFunctionBoilerplateLiteral(
194 FunctionBoilerplateLiteral* expr) { 239 FunctionBoilerplateLiteral* expr) {
195 BAILOUT("FunctionBoilerplateLiteral"); 240 BAILOUT("FunctionBoilerplateLiteral");
196 } 241 }
197 242
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 BAILOUT("UnaryOperation"); 328 BAILOUT("UnaryOperation");
284 } 329 }
285 330
286 331
287 void ExpressionBuilder::VisitCountOperation(CountOperation* expr) { 332 void ExpressionBuilder::VisitCountOperation(CountOperation* expr) {
288 BAILOUT("CountOperation"); 333 BAILOUT("CountOperation");
289 } 334 }
290 335
291 336
292 void ExpressionBuilder::VisitBinaryOperation(BinaryOperation* expr) { 337 void ExpressionBuilder::VisitBinaryOperation(BinaryOperation* expr) {
293 BAILOUT("BinaryOperation"); 338 Token::Value op = expr->op();
339 switch (op) {
340 case Token::COMMA:
341 case Token::OR:
342 case Token::AND:
343 BAILOUT("unsupported binary operation");
344
345 case Token::BIT_OR:
346 case Token::BIT_XOR:
347 case Token::BIT_AND:
348 case Token::SHL:
349 case Token::SAR:
350 case Token::SHR:
351 case Token::ADD:
352 case Token::SUB:
353 case Token::MUL:
354 case Token::DIV:
355 case Token::MOD: {
356 ExpressionBuilder left, right;
357 left.Build(expr->left());
358 if (left.cfg() == NULL) {
359 BAILOUT("unsupported left subexpression in binop");
360 }
361 right.Build(expr->right());
362 if (right.cfg() == NULL) {
363 BAILOUT("unsupported right subexpression in binop");
364 }
365
366 Location* temp = new TempLocation();
367 cfg_ = left.cfg();
368 cfg_->Concatenate(right.cfg());
369 cfg_->Append(new BinaryOpInstr(temp, op, left.value(), right.value()));
370
371 value_ = temp;
372 return;
373 }
374
375 default:
376 UNREACHABLE();
377 }
294 } 378 }
295 379
296 380
297 void ExpressionBuilder::VisitCompareOperation(CompareOperation* expr) { 381 void ExpressionBuilder::VisitCompareOperation(CompareOperation* expr) {
298 BAILOUT("CompareOperation"); 382 BAILOUT("CompareOperation");
299 } 383 }
300 384
301 385
302 void ExpressionBuilder::VisitThisFunction(ThisFunction* expr) { 386 void ExpressionBuilder::VisitThisFunction(ThisFunction* expr) {
303 BAILOUT("ThisFunction"); 387 BAILOUT("ThisFunction");
304 } 388 }
305 389
306 #undef BAILOUT 390 #undef BAILOUT
307 #undef CHECK_BAILOUT
308 391
309 392
310 // Macros (temporarily) handling unsupported statement types. 393 // Macros (temporarily) handling unsupported statement types.
311 #define BAILOUT(reason) \ 394 #define BAILOUT(reason) \
312 do { \ 395 do { \
313 cfg_ = NULL; \ 396 cfg_ = NULL; \
314 return; \ 397 return; \
315 } while (false) 398 } while (false)
316 399
317 #define CHECK_BAILOUT() \ 400 #define CHECK_BAILOUT() \
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 } 443 }
361 444
362 445
363 void StatementBuilder::VisitBreakStatement(BreakStatement* stmt) { 446 void StatementBuilder::VisitBreakStatement(BreakStatement* stmt) {
364 BAILOUT("BreakStatement"); 447 BAILOUT("BreakStatement");
365 } 448 }
366 449
367 450
368 void StatementBuilder::VisitReturnStatement(ReturnStatement* stmt) { 451 void StatementBuilder::VisitReturnStatement(ReturnStatement* stmt) {
369 ExpressionBuilder builder; 452 ExpressionBuilder builder;
370 builder.Visit(stmt->expression()); 453 builder.Build(stmt->expression());
371 Value* value = builder.value(); 454 if (builder.cfg() == NULL) {
372 if (value == NULL) BAILOUT("unsupported expression type"); 455 BAILOUT("unsupported expression in return statement");
373 cfg_->AppendReturnInstruction(value); 456 }
457
458 cfg_->Concatenate(builder.cfg());
459 cfg_->AppendReturnInstruction(builder.value());
374 } 460 }
375 461
376 462
377 void StatementBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { 463 void StatementBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
378 BAILOUT("WithEnterStatement"); 464 BAILOUT("WithEnterStatement");
379 } 465 }
380 466
381 467
382 void StatementBuilder::VisitWithExitStatement(WithExitStatement* stmt) { 468 void StatementBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
383 BAILOUT("WithExitStatement"); 469 BAILOUT("WithExitStatement");
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 } 509 }
424 510
425 511
426 void Constant::Print() { 512 void Constant::Print() {
427 PrintF("Constant("); 513 PrintF("Constant(");
428 handle_->Print(); 514 handle_->Print();
429 PrintF(")"); 515 PrintF(")");
430 } 516 }
431 517
432 518
519 void Effect::Print() {
520 PrintF("Effect");
521 }
522
523
433 void SlotLocation::Print() { 524 void SlotLocation::Print() {
434 PrintF("Slot("); 525 PrintF("Slot(");
435 switch (type_) { 526 switch (type_) {
436 case Slot::PARAMETER: 527 case Slot::PARAMETER:
437 PrintF("PARAMETER, %d)", index_); 528 PrintF("PARAMETER, %d)", index_);
438 break; 529 break;
439 case Slot::LOCAL: 530 case Slot::LOCAL:
440 PrintF("LOCAL, %d)", index_); 531 PrintF("LOCAL, %d)", index_);
441 break; 532 break;
442 default: 533 default:
443 UNREACHABLE(); 534 UNREACHABLE();
444 } 535 }
445 } 536 }
446 537
447 538
539 void TempLocation::Print() {
540 PrintF("Temp(%d)", number());
541 }
542
543
544 void BinaryOpInstr::Print() {
545 PrintF("BinaryOp(");
546 loc_->Print();
547 PrintF(", %s, ", Token::Name(op_));
548 val0_->Print();
549 PrintF(", ");
550 val1_->Print();
551 PrintF(")\n");
552 }
553
554
448 void ReturnInstr::Print() { 555 void ReturnInstr::Print() {
449 PrintF("Return "); 556 PrintF("Return(");
450 value_->Print(); 557 value_->Print();
451 PrintF("\n"); 558 PrintF(")\n");
452 } 559 }
453 560
454 561
455 void InstructionBlock::Print() { 562 void InstructionBlock::Print() {
456 if (!is_marked_) { 563 if (!is_marked_) {
457 is_marked_ = true; 564 is_marked_ = true;
458 PrintF("L%d:\n", number()); 565 PrintF("L%d:\n", number());
459 for (int i = 0, len = instructions_.length(); i < len; i++) { 566 for (int i = 0, len = instructions_.length(); i < len; i++) {
460 instructions_[i]->Print(); 567 instructions_[i]->Print();
461 } 568 }
(...skipping 14 matching lines...) Expand all
476 void ExitNode::Print() { 583 void ExitNode::Print() {
477 if (!is_marked_) { 584 if (!is_marked_) {
478 is_marked_ = true; 585 is_marked_ = true;
479 PrintF("L%d:\nExit\n\n", number()); 586 PrintF("L%d:\nExit\n\n", number());
480 } 587 }
481 } 588 }
482 589
483 #endif // DEBUG 590 #endif // DEBUG
484 591
485 } } // namespace v8::internal 592 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/cfg.h ('k') | src/ia32/cfg-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698