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

Side by Side Diff: src/cfg.cc

Issue 255022: Remove obsolete support for an experimental multipass compiler. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 11 years, 2 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/compiler.cc » ('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 2009 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 "v8.h"
29
30 #include "bootstrapper.h"
31 #include "cfg.h"
32 #include "scopeinfo.h"
33 #include "scopes.h"
34
35 namespace v8 {
36 namespace internal {
37
38
39 CfgGlobals* CfgGlobals::top_ = NULL;
40
41
42 CfgGlobals::CfgGlobals(FunctionLiteral* fun)
43 : global_fun_(fun),
44 global_exit_(new ExitNode()),
45 nowhere_(new Nowhere()),
46 #ifdef DEBUG
47 node_counter_(0),
48 temp_counter_(0),
49 #endif
50 previous_(top_) {
51 top_ = this;
52 }
53
54
55 #define BAILOUT(reason) \
56 do { return NULL; } while (false)
57
58 Cfg* Cfg::Build() {
59 FunctionLiteral* fun = CfgGlobals::current()->fun();
60 if (fun->scope()->num_heap_slots() > 0) {
61 BAILOUT("function has context slots");
62 }
63 if (fun->scope()->num_stack_slots() > kBitsPerPointer) {
64 BAILOUT("function has too many locals");
65 }
66 if (fun->scope()->num_parameters() > kBitsPerPointer - 1) {
67 BAILOUT("function has too many parameters");
68 }
69 if (fun->scope()->arguments() != NULL) {
70 BAILOUT("function uses .arguments");
71 }
72
73 ZoneList<Statement*>* body = fun->body();
74 if (body->is_empty()) {
75 BAILOUT("empty function body");
76 }
77
78 StatementCfgBuilder builder;
79 builder.VisitStatements(body);
80 Cfg* graph = builder.graph();
81 if (graph == NULL) {
82 BAILOUT("unsupported statement type");
83 }
84 if (graph->is_empty()) {
85 BAILOUT("function body produces empty cfg");
86 }
87 if (graph->has_exit()) {
88 BAILOUT("control path without explicit return");
89 }
90 graph->PrependEntryNode();
91 return graph;
92 }
93
94 #undef BAILOUT
95
96
97 void Cfg::PrependEntryNode() {
98 ASSERT(!is_empty());
99 entry_ = new EntryNode(InstructionBlock::cast(entry()));
100 }
101
102
103 void Cfg::Append(Instruction* instr) {
104 ASSERT(is_empty() || has_exit());
105 if (is_empty()) {
106 entry_ = exit_ = new InstructionBlock();
107 }
108 InstructionBlock::cast(exit_)->Append(instr);
109 }
110
111
112 void Cfg::AppendReturnInstruction(Value* value) {
113 Append(new ReturnInstr(value));
114 ExitNode* global_exit = CfgGlobals::current()->exit();
115 InstructionBlock::cast(exit_)->set_successor(global_exit);
116 exit_ = NULL;
117 }
118
119
120 void Cfg::Concatenate(Cfg* other) {
121 ASSERT(is_empty() || has_exit());
122 if (other->is_empty()) return;
123
124 if (is_empty()) {
125 entry_ = other->entry();
126 exit_ = other->exit();
127 } else {
128 // We have a pair of nonempty fragments and this has an available exit.
129 // Destructively glue the fragments together.
130 InstructionBlock* first = InstructionBlock::cast(exit_);
131 InstructionBlock* second = InstructionBlock::cast(other->entry());
132 first->instructions()->AddAll(*second->instructions());
133 if (second->successor() != NULL) {
134 first->set_successor(second->successor());
135 exit_ = other->exit();
136 }
137 }
138 }
139
140
141 void InstructionBlock::Unmark() {
142 if (is_marked_) {
143 is_marked_ = false;
144 successor_->Unmark();
145 }
146 }
147
148
149 void EntryNode::Unmark() {
150 if (is_marked_) {
151 is_marked_ = false;
152 successor_->Unmark();
153 }
154 }
155
156
157 void ExitNode::Unmark() {
158 is_marked_ = false;
159 }
160
161
162 Handle<Code> Cfg::Compile(Handle<Script> script) {
163 const int kInitialBufferSize = 4 * KB;
164 MacroAssembler* masm = new MacroAssembler(NULL, kInitialBufferSize);
165 entry()->Compile(masm);
166 entry()->Unmark();
167 CodeDesc desc;
168 masm->GetCode(&desc);
169 FunctionLiteral* fun = CfgGlobals::current()->fun();
170 ZoneScopeInfo info(fun->scope());
171 InLoopFlag in_loop = fun->loop_nesting() ? IN_LOOP : NOT_IN_LOOP;
172 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
173 Handle<Code> code = Factory::NewCode(desc, &info, flags, masm->CodeObject());
174
175 // Add unresolved entries in the code to the fixup list.
176 Bootstrapper::AddFixup(*code, masm);
177
178 #ifdef ENABLE_DISASSEMBLER
179 if (FLAG_print_code) {
180 // Print the source code if available.
181 if (!script->IsUndefined() && !script->source()->IsUndefined()) {
182 PrintF("--- Raw source ---\n");
183 StringInputBuffer stream(String::cast(script->source()));
184 stream.Seek(fun->start_position());
185 // fun->end_position() points to the last character in the
186 // stream. We need to compensate by adding one to calculate the
187 // length.
188 int source_len = fun->end_position() - fun->start_position() + 1;
189 for (int i = 0; i < source_len; i++) {
190 if (stream.has_more()) PrintF("%c", stream.GetNext());
191 }
192 PrintF("\n\n");
193 }
194 PrintF("--- Code ---\n");
195 code->Disassemble(*fun->name()->ToCString());
196 }
197 #endif
198
199 return code;
200 }
201
202
203 void ZeroOperandInstruction::FastAllocate(TempLocation* temp) {
204 temp->set_where(TempLocation::STACK);
205 }
206
207
208 void OneOperandInstruction::FastAllocate(TempLocation* temp) {
209 temp->set_where((temp == value_)
210 ? TempLocation::ACCUMULATOR
211 : TempLocation::STACK);
212 }
213
214
215 void TwoOperandInstruction::FastAllocate(TempLocation* temp) {
216 temp->set_where((temp == value0_ || temp == value1_)
217 ? TempLocation::ACCUMULATOR
218 : TempLocation::STACK);
219 }
220
221
222 void PositionInstr::Compile(MacroAssembler* masm) {
223 if (FLAG_debug_info && pos_ != RelocInfo::kNoPosition) {
224 masm->RecordStatementPosition(pos_);
225 masm->RecordPosition(pos_);
226 }
227 }
228
229
230 void MoveInstr::Compile(MacroAssembler* masm) {
231 location()->Move(masm, value());
232 }
233
234
235 // The expression builder should not be used for declarations or statements.
236 void ExpressionCfgBuilder::VisitDeclaration(Declaration* decl) {
237 UNREACHABLE();
238 }
239
240 #define DEFINE_VISIT(type) \
241 void ExpressionCfgBuilder::Visit##type(type* stmt) { UNREACHABLE(); }
242 STATEMENT_NODE_LIST(DEFINE_VISIT)
243 #undef DEFINE_VISIT
244
245
246 // Macros (temporarily) handling unsupported expression types.
247 #define BAILOUT(reason) \
248 do { \
249 graph_ = NULL; \
250 return; \
251 } while (false)
252
253 void ExpressionCfgBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
254 BAILOUT("FunctionLiteral");
255 }
256
257
258 void ExpressionCfgBuilder::VisitFunctionBoilerplateLiteral(
259 FunctionBoilerplateLiteral* expr) {
260 BAILOUT("FunctionBoilerplateLiteral");
261 }
262
263
264 void ExpressionCfgBuilder::VisitConditional(Conditional* expr) {
265 BAILOUT("Conditional");
266 }
267
268
269 void ExpressionCfgBuilder::VisitSlot(Slot* expr) {
270 BAILOUT("Slot");
271 }
272
273
274 void ExpressionCfgBuilder::VisitVariableProxy(VariableProxy* expr) {
275 Expression* rewrite = expr->var()->rewrite();
276 if (rewrite == NULL || rewrite->AsSlot() == NULL) {
277 BAILOUT("unsupported variable (not a slot)");
278 }
279 Slot* slot = rewrite->AsSlot();
280 if (slot->type() != Slot::PARAMETER && slot->type() != Slot::LOCAL) {
281 BAILOUT("unsupported slot type (not a parameter or local)");
282 }
283 // Ignore the passed destination.
284 value_ = new SlotLocation(slot->type(), slot->index());
285 }
286
287
288 void ExpressionCfgBuilder::VisitLiteral(Literal* expr) {
289 // Ignore the passed destination.
290 value_ = new Constant(expr->handle());
291 }
292
293
294 void ExpressionCfgBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
295 BAILOUT("RegExpLiteral");
296 }
297
298
299 void ExpressionCfgBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
300 BAILOUT("ObjectLiteral");
301 }
302
303
304 void ExpressionCfgBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
305 BAILOUT("ArrayLiteral");
306 }
307
308
309 void ExpressionCfgBuilder::VisitCatchExtensionObject(
310 CatchExtensionObject* expr) {
311 BAILOUT("CatchExtensionObject");
312 }
313
314
315 void ExpressionCfgBuilder::VisitAssignment(Assignment* expr) {
316 if (expr->op() != Token::ASSIGN && expr->op() != Token::INIT_VAR) {
317 BAILOUT("unsupported compound assignment");
318 }
319 Expression* lhs = expr->target();
320 if (lhs->AsProperty() != NULL) {
321 BAILOUT("unsupported property assignment");
322 }
323
324 Variable* var = lhs->AsVariableProxy()->AsVariable();
325 if (var == NULL) {
326 BAILOUT("unsupported invalid left-hand side");
327 }
328 if (var->is_global()) {
329 BAILOUT("unsupported global variable");
330 }
331 Slot* slot = var->slot();
332 ASSERT(slot != NULL);
333 if (slot->type() != Slot::PARAMETER && slot->type() != Slot::LOCAL) {
334 BAILOUT("unsupported slot lhs (not a parameter or local)");
335 }
336
337 // Parameter and local slot assignments.
338 ExpressionCfgBuilder builder;
339 SlotLocation* loc = new SlotLocation(slot->type(), slot->index());
340 builder.Build(expr->value(), loc);
341 if (builder.graph() == NULL) {
342 BAILOUT("unsupported expression in assignment");
343 }
344 // If the expression did not come back in the slot location, append
345 // a move to the CFG.
346 graph_ = builder.graph();
347 if (builder.value() != loc) {
348 graph()->Append(new MoveInstr(loc, builder.value()));
349 }
350 // Record the assignment.
351 assigned_vars_.AddElement(loc);
352 // Ignore the destination passed to us.
353 value_ = loc;
354 }
355
356
357 void ExpressionCfgBuilder::VisitThrow(Throw* expr) {
358 BAILOUT("Throw");
359 }
360
361
362 void ExpressionCfgBuilder::VisitProperty(Property* expr) {
363 ExpressionCfgBuilder object, key;
364 object.Build(expr->obj(), NULL);
365 if (object.graph() == NULL) {
366 BAILOUT("unsupported object subexpression in propload");
367 }
368 key.Build(expr->key(), NULL);
369 if (key.graph() == NULL) {
370 BAILOUT("unsupported key subexpression in propload");
371 }
372
373 if (destination_ == NULL) destination_ = new TempLocation();
374
375 graph_ = object.graph();
376 // Insert a move to a fresh temporary if the object value is in a slot
377 // that's assigned in the key.
378 Location* temp = NULL;
379 if (object.value()->is_slot() &&
380 key.assigned_vars()->Contains(SlotLocation::cast(object.value()))) {
381 temp = new TempLocation();
382 graph()->Append(new MoveInstr(temp, object.value()));
383 }
384 graph()->Concatenate(key.graph());
385 graph()->Append(new PropLoadInstr(destination_,
386 temp == NULL ? object.value() : temp,
387 key.value()));
388
389 assigned_vars_ = *object.assigned_vars();
390 assigned_vars()->Union(key.assigned_vars());
391
392 value_ = destination_;
393 }
394
395
396 void ExpressionCfgBuilder::VisitCall(Call* expr) {
397 BAILOUT("Call");
398 }
399
400
401 void ExpressionCfgBuilder::VisitCallNew(CallNew* expr) {
402 BAILOUT("CallNew");
403 }
404
405
406 void ExpressionCfgBuilder::VisitCallRuntime(CallRuntime* expr) {
407 BAILOUT("CallRuntime");
408 }
409
410
411 void ExpressionCfgBuilder::VisitUnaryOperation(UnaryOperation* expr) {
412 BAILOUT("UnaryOperation");
413 }
414
415
416 void ExpressionCfgBuilder::VisitCountOperation(CountOperation* expr) {
417 BAILOUT("CountOperation");
418 }
419
420
421 void ExpressionCfgBuilder::VisitBinaryOperation(BinaryOperation* expr) {
422 Token::Value op = expr->op();
423 switch (op) {
424 case Token::COMMA:
425 case Token::OR:
426 case Token::AND:
427 BAILOUT("unsupported binary operation");
428
429 case Token::BIT_OR:
430 case Token::BIT_XOR:
431 case Token::BIT_AND:
432 case Token::SHL:
433 case Token::SAR:
434 case Token::SHR:
435 case Token::ADD:
436 case Token::SUB:
437 case Token::MUL:
438 case Token::DIV:
439 case Token::MOD: {
440 ExpressionCfgBuilder left, right;
441 left.Build(expr->left(), NULL);
442 if (left.graph() == NULL) {
443 BAILOUT("unsupported left subexpression in binop");
444 }
445 right.Build(expr->right(), NULL);
446 if (right.graph() == NULL) {
447 BAILOUT("unsupported right subexpression in binop");
448 }
449
450 if (destination_ == NULL) destination_ = new TempLocation();
451
452 graph_ = left.graph();
453 // Insert a move to a fresh temporary if the left value is in a
454 // slot that's assigned on the right.
455 Location* temp = NULL;
456 if (left.value()->is_slot() &&
457 right.assigned_vars()->Contains(SlotLocation::cast(left.value()))) {
458 temp = new TempLocation();
459 graph()->Append(new MoveInstr(temp, left.value()));
460 }
461 graph()->Concatenate(right.graph());
462 graph()->Append(new BinaryOpInstr(destination_, op,
463 temp == NULL ? left.value() : temp,
464 right.value()));
465
466 assigned_vars_ = *left.assigned_vars();
467 assigned_vars()->Union(right.assigned_vars());
468
469 value_ = destination_;
470 return;
471 }
472
473 default:
474 UNREACHABLE();
475 }
476 }
477
478
479 void ExpressionCfgBuilder::VisitCompareOperation(CompareOperation* expr) {
480 BAILOUT("CompareOperation");
481 }
482
483
484 void ExpressionCfgBuilder::VisitThisFunction(ThisFunction* expr) {
485 BAILOUT("ThisFunction");
486 }
487
488 #undef BAILOUT
489
490
491 // Macros (temporarily) handling unsupported statement types.
492 #define BAILOUT(reason) \
493 do { \
494 graph_ = NULL; \
495 return; \
496 } while (false)
497
498 #define CHECK_BAILOUT() \
499 if (graph() == NULL) { return; } else {}
500
501 void StatementCfgBuilder::VisitStatements(ZoneList<Statement*>* stmts) {
502 for (int i = 0, len = stmts->length(); i < len; i++) {
503 Visit(stmts->at(i));
504 CHECK_BAILOUT();
505 if (!graph()->has_exit()) return;
506 }
507 }
508
509
510 // The statement builder should not be used for declarations or expressions.
511 void StatementCfgBuilder::VisitDeclaration(Declaration* decl) { UNREACHABLE(); }
512
513 #define DEFINE_VISIT(type) \
514 void StatementCfgBuilder::Visit##type(type* expr) { UNREACHABLE(); }
515 EXPRESSION_NODE_LIST(DEFINE_VISIT)
516 #undef DEFINE_VISIT
517
518
519 void StatementCfgBuilder::VisitBlock(Block* stmt) {
520 VisitStatements(stmt->statements());
521 }
522
523
524 void StatementCfgBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
525 ExpressionCfgBuilder builder;
526 builder.Build(stmt->expression(), CfgGlobals::current()->nowhere());
527 if (builder.graph() == NULL) {
528 BAILOUT("unsupported expression in expression statement");
529 }
530 graph()->Append(new PositionInstr(stmt->statement_pos()));
531 graph()->Concatenate(builder.graph());
532 }
533
534
535 void StatementCfgBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
536 // Nothing to do.
537 }
538
539
540 void StatementCfgBuilder::VisitIfStatement(IfStatement* stmt) {
541 BAILOUT("IfStatement");
542 }
543
544
545 void StatementCfgBuilder::VisitContinueStatement(ContinueStatement* stmt) {
546 BAILOUT("ContinueStatement");
547 }
548
549
550 void StatementCfgBuilder::VisitBreakStatement(BreakStatement* stmt) {
551 BAILOUT("BreakStatement");
552 }
553
554
555 void StatementCfgBuilder::VisitReturnStatement(ReturnStatement* stmt) {
556 ExpressionCfgBuilder builder;
557 builder.Build(stmt->expression(), NULL);
558 if (builder.graph() == NULL) {
559 BAILOUT("unsupported expression in return statement");
560 }
561
562 graph()->Append(new PositionInstr(stmt->statement_pos()));
563 graph()->Concatenate(builder.graph());
564 graph()->AppendReturnInstruction(builder.value());
565 }
566
567
568 void StatementCfgBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
569 BAILOUT("WithEnterStatement");
570 }
571
572
573 void StatementCfgBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
574 BAILOUT("WithExitStatement");
575 }
576
577
578 void StatementCfgBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
579 BAILOUT("SwitchStatement");
580 }
581
582
583 void StatementCfgBuilder::VisitLoopStatement(LoopStatement* stmt) {
584 BAILOUT("LoopStatement");
585 }
586
587
588 void StatementCfgBuilder::VisitForInStatement(ForInStatement* stmt) {
589 BAILOUT("ForInStatement");
590 }
591
592
593 void StatementCfgBuilder::VisitTryCatch(TryCatch* stmt) {
594 BAILOUT("TryCatch");
595 }
596
597
598 void StatementCfgBuilder::VisitTryFinally(TryFinally* stmt) {
599 BAILOUT("TryFinally");
600 }
601
602
603 void StatementCfgBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
604 BAILOUT("DebuggerStatement");
605 }
606
607
608 #ifdef DEBUG
609 // CFG printing support (via depth-first, preorder block traversal).
610
611 void Cfg::Print() {
612 entry_->Print();
613 entry_->Unmark();
614 }
615
616
617 void Constant::Print() {
618 PrintF("Constant ");
619 handle_->Print();
620 }
621
622
623 void Nowhere::Print() {
624 PrintF("Nowhere");
625 }
626
627
628 void SlotLocation::Print() {
629 PrintF("Slot ");
630 switch (type_) {
631 case Slot::PARAMETER:
632 PrintF("(PARAMETER, %d)", index_);
633 break;
634 case Slot::LOCAL:
635 PrintF("(LOCAL, %d)", index_);
636 break;
637 default:
638 UNREACHABLE();
639 }
640 }
641
642
643 void TempLocation::Print() {
644 PrintF("Temp %d", number());
645 }
646
647
648 void OneOperandInstruction::Print() {
649 PrintF("(");
650 location()->Print();
651 PrintF(", ");
652 value_->Print();
653 PrintF(")");
654 }
655
656
657 void TwoOperandInstruction::Print() {
658 PrintF("(");
659 location()->Print();
660 PrintF(", ");
661 value0_->Print();
662 PrintF(", ");
663 value1_->Print();
664 PrintF(")");
665 }
666
667
668 void MoveInstr::Print() {
669 PrintF("Move ");
670 OneOperandInstruction::Print();
671 PrintF("\n");
672 }
673
674
675 void PropLoadInstr::Print() {
676 PrintF("PropLoad ");
677 TwoOperandInstruction::Print();
678 PrintF("\n");
679 }
680
681
682 void BinaryOpInstr::Print() {
683 switch (op()) {
684 case Token::OR:
685 // Two character operand.
686 PrintF("BinaryOp[OR] ");
687 break;
688 case Token::AND:
689 case Token::SHL:
690 case Token::SAR:
691 case Token::SHR:
692 case Token::ADD:
693 case Token::SUB:
694 case Token::MUL:
695 case Token::DIV:
696 case Token::MOD:
697 // Three character operands.
698 PrintF("BinaryOp[%s] ", Token::Name(op()));
699 break;
700 case Token::COMMA:
701 // Five character operand.
702 PrintF("BinaryOp[COMMA] ");
703 break;
704 case Token::BIT_OR:
705 // Six character operand.
706 PrintF("BinaryOp[BIT_OR] ");
707 break;
708 case Token::BIT_XOR:
709 case Token::BIT_AND:
710 // Seven character operands.
711 PrintF("BinaryOp[%s] ", Token::Name(op()));
712 break;
713 default:
714 UNREACHABLE();
715 }
716 TwoOperandInstruction::Print();
717 PrintF("\n");
718 }
719
720
721 void ReturnInstr::Print() {
722 PrintF("Return ");
723 OneOperandInstruction::Print();
724 PrintF("\n");
725 }
726
727
728 void InstructionBlock::Print() {
729 if (!is_marked_) {
730 is_marked_ = true;
731 PrintF("L%d:\n", number());
732 for (int i = 0, len = instructions_.length(); i < len; i++) {
733 instructions_[i]->Print();
734 }
735 PrintF("Goto L%d\n\n", successor_->number());
736 successor_->Print();
737 }
738 }
739
740
741 void EntryNode::Print() {
742 if (!is_marked_) {
743 is_marked_ = true;
744 successor_->Print();
745 }
746 }
747
748
749 void ExitNode::Print() {
750 if (!is_marked_) {
751 is_marked_ = true;
752 PrintF("L%d:\nExit\n\n", number());
753 }
754 }
755
756 #endif // DEBUG
757
758 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/cfg.h ('k') | src/compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698