OLD | NEW |
---|---|
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 18 matching lines...) Expand all Loading... | |
29 | 29 |
30 #include "bootstrapper.h" | 30 #include "bootstrapper.h" |
31 #include "cfg.h" | 31 #include "cfg.h" |
32 #include "scopeinfo.h" | 32 #include "scopeinfo.h" |
33 #include "scopes.h" | 33 #include "scopes.h" |
34 | 34 |
35 namespace v8 { | 35 namespace v8 { |
36 namespace internal { | 36 namespace internal { |
37 | 37 |
38 | 38 |
39 ExitNode* Cfg::global_exit_ = NULL; | 39 CfgGlobals* CfgGlobals::top_ = NULL; |
40 | 40 |
41 | 41 |
42 void CfgNode::Reset() { | 42 CfgGlobals::CfgGlobals(FunctionLiteral* fun) |
43 : global_fun_(fun), | |
44 global_exit_(new ExitNode()), | |
43 #ifdef DEBUG | 45 #ifdef DEBUG |
44 node_counter_ = 0; | 46 node_counter_(0), |
45 #endif | 47 #endif |
46 } | 48 previous_(top_) { |
47 | 49 top_ = this; |
48 | |
49 void Cfg::Reset(FunctionLiteral* fun) { | |
50 global_exit_ = new ExitNode(fun); | |
51 CfgNode::Reset(); | |
52 } | 50 } |
53 | 51 |
54 | 52 |
55 #define BAILOUT(reason) \ | 53 #define BAILOUT(reason) \ |
56 do { return NULL; } while (false) | 54 do { return NULL; } while (false) |
57 | 55 |
58 Cfg* Cfg::Build(FunctionLiteral* fun) { | 56 Cfg* Cfg::Build() { |
57 FunctionLiteral* fun = CfgGlobals::current()->fun(); | |
58 if (fun->scope()->num_heap_slots() > 0) { | |
59 BAILOUT("function has context slots"); | |
60 } | |
61 if (fun->scope()->arguments() != NULL) { | |
62 BAILOUT("function uses .arguments"); | |
63 } | |
64 | |
59 ZoneList<Statement*>* body = fun->body(); | 65 ZoneList<Statement*>* body = fun->body(); |
60 if (body->is_empty()) { | 66 if (body->is_empty()) { |
61 BAILOUT("empty function body"); | 67 BAILOUT("empty function body"); |
62 } | 68 } |
63 | 69 |
64 Cfg::Reset(fun); | |
65 StatementBuilder builder; | 70 StatementBuilder builder; |
66 builder.VisitStatements(body); | 71 builder.VisitStatements(body); |
67 Cfg* cfg = builder.cfg(); | 72 Cfg* cfg = builder.cfg(); |
68 if (cfg == NULL) { | 73 if (cfg == NULL) { |
69 BAILOUT("unsupported statement type"); | 74 BAILOUT("unsupported statement type"); |
70 } | 75 } |
71 if (cfg->has_exit()) { | 76 if (cfg->has_exit()) { |
72 BAILOUT("control path without explicit return"); | 77 BAILOUT("control path without explicit return"); |
73 } | 78 } |
74 cfg->PrependEntryNode(fun); | 79 cfg->PrependEntryNode(); |
75 return cfg; | 80 return cfg; |
76 } | 81 } |
77 | 82 |
78 #undef BAILOUT | 83 #undef BAILOUT |
79 | 84 |
80 | 85 |
81 void Cfg::PrependEntryNode(FunctionLiteral* fun) { | 86 void Cfg::PrependEntryNode() { |
82 ASSERT(!is_empty()); | 87 ASSERT(!is_empty()); |
83 entry_ = new EntryNode(fun, InstructionBlock::cast(entry())); | 88 entry_ = new EntryNode(InstructionBlock::cast(entry())); |
84 } | 89 } |
85 | 90 |
86 | 91 |
87 void Cfg::Append(Instruction* instr) { | 92 void Cfg::Append(Instruction* instr) { |
88 ASSERT(has_exit()); | 93 ASSERT(has_exit()); |
89 ASSERT(!is_empty()); | 94 ASSERT(!is_empty()); |
90 InstructionBlock::cast(exit_)->Append(instr); | 95 InstructionBlock::cast(exit_)->Append(instr); |
91 } | 96 } |
92 | 97 |
93 | 98 |
94 void Cfg::AppendReturnInstruction(Value* value) { | 99 void Cfg::AppendReturnInstruction(Value* value) { |
95 Append(new ReturnInstr(value)); | 100 Append(new ReturnInstr(value)); |
96 InstructionBlock::cast(exit_)->set_successor(global_exit_); | 101 ExitNode* global_exit = CfgGlobals::current()->exit(); |
102 InstructionBlock::cast(exit_)->set_successor(global_exit); | |
97 exit_ = NULL; | 103 exit_ = NULL; |
98 } | 104 } |
99 | 105 |
100 | 106 |
101 EntryNode::EntryNode(FunctionLiteral* fun, InstructionBlock* succ) | |
102 : successor_(succ), local_count_(fun->scope()->num_stack_slots()) { | |
103 } | |
104 | |
105 | |
106 ExitNode::ExitNode(FunctionLiteral* fun) | |
107 : parameter_count_(fun->scope()->num_parameters()) { | |
108 } | |
109 | |
110 | |
111 void InstructionBlock::Unmark() { | 107 void InstructionBlock::Unmark() { |
112 if (is_marked_) { | 108 if (is_marked_) { |
113 is_marked_ = false; | 109 is_marked_ = false; |
114 successor_->Unmark(); | 110 successor_->Unmark(); |
115 } | 111 } |
116 } | 112 } |
117 | 113 |
118 | 114 |
119 void EntryNode::Unmark() { | 115 void EntryNode::Unmark() { |
120 if (is_marked_) { | 116 if (is_marked_) { |
121 is_marked_ = false; | 117 is_marked_ = false; |
122 successor_->Unmark(); | 118 successor_->Unmark(); |
123 } | 119 } |
124 } | 120 } |
125 | 121 |
126 | 122 |
127 void ExitNode::Unmark() {} | 123 void ExitNode::Unmark() { is_marked_ = false; } |
Kasper Lund
2009/08/03 05:55:44
I would put this on three lines.
Kevin Millikin (Chromium)
2009/08/03 07:54:43
Done.
| |
128 | 124 |
129 | 125 |
130 Handle<Code> Cfg::Compile(FunctionLiteral* fun, Handle<Script> script) { | 126 Handle<Code> Cfg::Compile(Handle<Script> script) { |
131 const int kInitialBufferSize = 4 * KB; | 127 const int kInitialBufferSize = 4 * KB; |
132 MacroAssembler* masm = new MacroAssembler(NULL, kInitialBufferSize); | 128 MacroAssembler* masm = new MacroAssembler(NULL, kInitialBufferSize); |
133 entry()->Compile(masm); | 129 entry()->Compile(masm); |
134 entry()->Unmark(); | 130 entry()->Unmark(); |
135 CodeDesc desc; | 131 CodeDesc desc; |
136 masm->GetCode(&desc); | 132 masm->GetCode(&desc); |
133 FunctionLiteral* fun = CfgGlobals::current()->fun(); | |
137 ZoneScopeInfo info(fun->scope()); | 134 ZoneScopeInfo info(fun->scope()); |
138 InLoopFlag in_loop = fun->loop_nesting() ? IN_LOOP : NOT_IN_LOOP; | 135 InLoopFlag in_loop = fun->loop_nesting() ? IN_LOOP : NOT_IN_LOOP; |
139 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop); | 136 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop); |
140 Handle<Code> code = Factory::NewCode(desc, &info, flags, masm->CodeObject()); | 137 Handle<Code> code = Factory::NewCode(desc, &info, flags, masm->CodeObject()); |
141 | 138 |
142 // Add unresolved entries in the code to the fixup list. | 139 // Add unresolved entries in the code to the fixup list. |
143 Bootstrapper::AddFixup(*code, masm); | 140 Bootstrapper::AddFixup(*code, masm); |
144 | 141 |
145 #ifdef ENABLE_DISASSEMBLER | 142 #ifdef ENABLE_DISASSEMBLER |
146 if (FLAG_print_code) { | 143 if (FLAG_print_code) { |
147 // Print the source code if available. | 144 // Print the source code if available. |
148 if (!script->IsUndefined() && !script->source()->IsUndefined()) { | 145 if (!script->IsUndefined() && !script->source()->IsUndefined()) { |
149 PrintF("--- Raw source ---\n"); | 146 PrintF("--- Raw source ---\n"); |
150 StringInputBuffer stream(String::cast(script->source())); | 147 StringInputBuffer stream(String::cast(script->source())); |
151 stream.Seek(fun->start_position()); | 148 stream.Seek(fun->start_position()); |
152 // fun->end_position() points to the last character in the stream. We | 149 // fun->end_position() points to the last character in the |
153 // need to compensate by adding one to calculate the length. | 150 // stream. We need to compensate by adding one to calculate the |
151 // length. | |
154 int source_len = fun->end_position() - fun->start_position() + 1; | 152 int source_len = fun->end_position() - fun->start_position() + 1; |
155 for (int i = 0; i < source_len; i++) { | 153 for (int i = 0; i < source_len; i++) { |
156 if (stream.has_more()) PrintF("%c", stream.GetNext()); | 154 if (stream.has_more()) PrintF("%c", stream.GetNext()); |
157 } | 155 } |
158 PrintF("\n\n"); | 156 PrintF("\n\n"); |
159 } | 157 } |
160 PrintF("--- Code ---\n"); | 158 PrintF("--- Code ---\n"); |
161 code->Disassemble(*fun->name()->ToCString()); | 159 code->Disassemble(*fun->name()->ToCString()); |
162 } | 160 } |
163 #endif | 161 #endif |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
200 BAILOUT("Conditional"); | 198 BAILOUT("Conditional"); |
201 } | 199 } |
202 | 200 |
203 | 201 |
204 void ExpressionBuilder::VisitSlot(Slot* expr) { | 202 void ExpressionBuilder::VisitSlot(Slot* expr) { |
205 BAILOUT("Slot"); | 203 BAILOUT("Slot"); |
206 } | 204 } |
207 | 205 |
208 | 206 |
209 void ExpressionBuilder::VisitVariableProxy(VariableProxy* expr) { | 207 void ExpressionBuilder::VisitVariableProxy(VariableProxy* expr) { |
210 BAILOUT("VariableProxy"); | 208 Expression* rewrite = expr->var()->rewrite(); |
209 if (rewrite == NULL || rewrite->AsSlot() == NULL) { | |
210 BAILOUT("unsupported variable (not a slot)"); | |
211 } | |
212 Slot* slot = rewrite->AsSlot(); | |
213 if (slot->type() != Slot::PARAMETER && slot->type() != Slot::LOCAL) { | |
214 BAILOUT("unsupported slot type (not a parameter or local)"); | |
215 } | |
216 value_ = new SlotLocation(slot->type(), slot->index()); | |
211 } | 217 } |
212 | 218 |
213 | 219 |
214 void ExpressionBuilder::VisitLiteral(Literal* expr) { | 220 void ExpressionBuilder::VisitLiteral(Literal* expr) { |
215 value_ = new Constant(expr->handle()); | 221 value_ = new Constant(expr->handle()); |
216 } | 222 } |
217 | 223 |
218 | 224 |
219 void ExpressionBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 225 void ExpressionBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
220 BAILOUT("RegExpLiteral"); | 226 BAILOUT("RegExpLiteral"); |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 #ifdef DEBUG | 415 #ifdef DEBUG |
410 // CFG printing support (via depth-first, preorder block traversal). | 416 // CFG printing support (via depth-first, preorder block traversal). |
411 | 417 |
412 void Cfg::Print() { | 418 void Cfg::Print() { |
413 entry_->Print(); | 419 entry_->Print(); |
414 entry_->Unmark(); | 420 entry_->Unmark(); |
415 } | 421 } |
416 | 422 |
417 | 423 |
418 void Constant::Print() { | 424 void Constant::Print() { |
425 PrintF("Constant("); | |
419 handle_->Print(); | 426 handle_->Print(); |
427 PrintF(")"); | |
428 } | |
429 | |
430 | |
431 void SlotLocation::Print() { | |
432 PrintF("Slot("); | |
433 switch (type_) { | |
434 case Slot::PARAMETER: | |
435 PrintF("PARAMETER, %d)", index_); | |
436 break; | |
437 case Slot::LOCAL: | |
438 PrintF("LOCAL, %d)", index_); | |
439 break; | |
440 default: | |
441 UNREACHABLE(); | |
442 } | |
420 } | 443 } |
421 | 444 |
422 | 445 |
423 void ReturnInstr::Print() { | 446 void ReturnInstr::Print() { |
424 PrintF("Return "); | 447 PrintF("Return "); |
425 value_->Print(); | 448 value_->Print(); |
426 PrintF("\n"); | 449 PrintF("\n"); |
427 } | 450 } |
428 | 451 |
429 | 452 |
430 int CfgNode::node_counter_ = 0; | |
431 | |
432 | |
433 void InstructionBlock::Print() { | 453 void InstructionBlock::Print() { |
434 if (!is_marked_) { | 454 if (!is_marked_) { |
435 is_marked_ = true; | 455 is_marked_ = true; |
436 PrintF("L%d:\n", number()); | 456 PrintF("L%d:\n", number()); |
437 for (int i = 0, len = instructions_.length(); i < len; i++) { | 457 for (int i = 0, len = instructions_.length(); i < len; i++) { |
438 instructions_[i]->Print(); | 458 instructions_[i]->Print(); |
439 } | 459 } |
440 PrintF("Goto L%d\n\n", successor_->number()); | 460 PrintF("Goto L%d\n\n", successor_->number()); |
441 successor_->Print(); | 461 successor_->Print(); |
442 } | 462 } |
(...skipping 11 matching lines...) Expand all Loading... | |
454 void ExitNode::Print() { | 474 void ExitNode::Print() { |
455 if (!is_marked_) { | 475 if (!is_marked_) { |
456 is_marked_ = true; | 476 is_marked_ = true; |
457 PrintF("L%d:\nExit\n\n", number()); | 477 PrintF("L%d:\nExit\n\n", number()); |
458 } | 478 } |
459 } | 479 } |
460 | 480 |
461 #endif // DEBUG | 481 #endif // DEBUG |
462 | 482 |
463 } } // namespace v8::internal | 483 } } // namespace v8::internal |
OLD | NEW |