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

Side by Side Diff: src/cfg.cc

Issue 159695: Basic infrastructure for fast two-pass compilation. A CFG is... (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
« src/cfg.h ('K') | « 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 ExitNode* Cfg::global_exit_ = NULL;
40
41
42 void CfgNode::Reset() {
43 #ifdef DEBUG
44 node_counter_ = 0;
45 #endif
46 }
47
48
49 void Cfg::Reset(FunctionLiteral* fun) {
50 global_exit_ = new ExitNode(fun);
51 CfgNode::Reset();
52 }
53
54
55 #define BAILOUT(reason) \
56 do { return NULL; } while (false)
57
58 Cfg* Cfg::Build(FunctionLiteral* fun) {
59 ZoneList<Statement*>* body = fun->body();
60 if (body->is_empty()) {
61 BAILOUT("empty function body");
62 }
63
64 Cfg::Reset(fun);
65 StatementBuilder builder;
66 builder.VisitStatements(body);
67 Cfg* cfg = builder.cfg();
68 if (cfg == NULL) {
69 BAILOUT("unsupported statement type");
70 }
71
72 ASSERT(!cfg->has_exit()); // Return on all paths.
73 cfg->PrependEntryNode(fun);
74 return cfg;
75 }
76
77 #undef BAILOUT
78
79
80 void Cfg::PrependEntryNode(FunctionLiteral* fun) {
81 ASSERT(!is_empty());
82 entry_ = new EntryNode(fun, InstructionBlock::cast(entry()));
83 }
84
85
86 void Cfg::Append(Instruction* instr) {
87 ASSERT(has_exit());
88 ASSERT(!is_empty());
89 InstructionBlock::cast(exit_)->Append(instr);
90 }
91
92
93 void Cfg::AppendReturnInstruction(Value* value) {
94 Append(new ReturnInstr(value));
95 InstructionBlock::cast(exit_)->set_successor(global_exit_);
96 exit_ = NULL;
97 }
98
99
100 EntryNode::EntryNode(FunctionLiteral* fun, InstructionBlock* succ)
101 : successor_(succ), local_count_(fun->scope()->num_stack_slots()) {
102 }
103
104
105 ExitNode::ExitNode(FunctionLiteral* fun)
106 : parameter_count_(fun->scope()->num_parameters()) {
107 }
108
109
110 void InstructionBlock::Unmark() {
111 if (is_marked_) {
112 is_marked_ = false;
113 successor_->Unmark();
114 }
115 }
116
117
118 void EntryNode::Unmark() {
119 if (is_marked_) {
120 is_marked_ = false;
121 successor_->Unmark();
122 }
123 }
124
125
126 void ExitNode::Unmark() {}
127
128
129 Handle<Code> Cfg::Compile(FunctionLiteral* fun, Handle<Script> script) {
130 const int kInitialBufferSize = 4 * KB;
131 MacroAssembler* masm = new MacroAssembler(NULL, kInitialBufferSize);
132 entry()->Compile(masm);
133 entry()->Unmark();
134 CodeDesc desc;
135 masm->GetCode(&desc);
136 ZoneScopeInfo info(fun->scope());
137 InLoopFlag in_loop = fun->loop_nesting() ? IN_LOOP : NOT_IN_LOOP;
138 Code::Flags flags = Code::ComputeFlags(Code::FUNCTION, in_loop);
139 Handle<Code> code = Factory::NewCode(desc, &info, flags, masm->CodeObject());
140
141 // Add unresolved entries in the code to the fixup list.
142 Bootstrapper::AddFixup(*code, masm);
143
144 #ifdef ENABLE_DISASSEMBLER
145 if (FLAG_print_code) {
146 // Print the source code if available.
147 if (!script->IsUndefined() && !script->source()->IsUndefined()) {
148 PrintF("--- Raw source ---\n");
149 StringInputBuffer stream(String::cast(script->source()));
150 stream.Seek(fun->start_position());
151 // fun->end_position() points to the last character in the stream. We
152 // need to compensate by adding one to calculate the length.
153 int source_len = fun->end_position() - fun->start_position() + 1;
154 for (int i = 0; i < source_len; i++) {
155 if (stream.has_more()) PrintF("%c", stream.GetNext());
156 }
157 PrintF("\n\n");
158 }
159 PrintF("--- Code ---\n");
160 code->Disassemble(*fun->name()->ToCString());
161 }
162 #endif
163
164 return code;
165 }
166
167
168 // The expression builder should not be used for declarations or statements.
169 void ExpressionBuilder::VisitDeclaration(Declaration* decl) { UNREACHABLE(); }
170
171 #define DEFINE_VISIT(type) \
172 void ExpressionBuilder::Visit##type(type* stmt) { UNREACHABLE(); }
173 STATEMENT_NODE_LIST(DEFINE_VISIT)
174 #undef DEFINE_VISIT
175
176
177 // Macros (temporarily) handling unsupported expression types.
178 #define BAILOUT(reason) \
179 do { \
180 value_ = NULL; \
181 return; \
182 } while (false)
183
184 #define CHECK_BAILOUT() \
185 if (value_ == NULL) { return; } else {}
186
187 void ExpressionBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
188 BAILOUT("FunctionLiteral");
189 }
190
191
192 void ExpressionBuilder::VisitFunctionBoilerplateLiteral(
193 FunctionBoilerplateLiteral* expr) {
194 BAILOUT("FunctionBoilerplateLiteral");
195 }
196
197
198 void ExpressionBuilder::VisitConditional(Conditional* expr) {
199 BAILOUT("Conditional");
200 }
201
202
203 void ExpressionBuilder::VisitSlot(Slot* expr) {
204 BAILOUT("Slot");
205 }
206
207
208 void ExpressionBuilder::VisitVariableProxy(VariableProxy* expr) {
209 BAILOUT("VariableProxy");
210 }
211
212
213 void ExpressionBuilder::VisitLiteral(Literal* expr) {
214 value_ = new Constant(expr->handle());
215 }
216
217
218 void ExpressionBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
219 BAILOUT("RegExpLiteral");
220 }
221
222
223 void ExpressionBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
224 BAILOUT("ObjectLiteral");
225 }
226
227
228 void ExpressionBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
229 BAILOUT("ArrayLiteral");
230 }
231
232
233 void ExpressionBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
234 BAILOUT("CatchExtensionObject");
235 }
236
237
238 void ExpressionBuilder::VisitAssignment(Assignment* expr) {
239 BAILOUT("Assignment");
240 }
241
242
243 void ExpressionBuilder::VisitThrow(Throw* expr) {
244 BAILOUT("Throw");
245 }
246
247
248 void ExpressionBuilder::VisitProperty(Property* expr) {
249 BAILOUT("Property");
250 }
251
252
253 void ExpressionBuilder::VisitCall(Call* expr) {
254 BAILOUT("Call");
255 }
256
257
258 void ExpressionBuilder::VisitCallEval(CallEval* expr) {
259 BAILOUT("CallEval");
260 }
261
262
263 void ExpressionBuilder::VisitCallNew(CallNew* expr) {
264 BAILOUT("CallNew");
265 }
266
267
268 void ExpressionBuilder::VisitCallRuntime(CallRuntime* expr) {
269 BAILOUT("CallRuntime");
270 }
271
272
273 void ExpressionBuilder::VisitUnaryOperation(UnaryOperation* expr) {
274 BAILOUT("UnaryOperation");
275 }
276
277
278 void ExpressionBuilder::VisitCountOperation(CountOperation* expr) {
279 BAILOUT("CountOperation");
280 }
281
282
283 void ExpressionBuilder::VisitBinaryOperation(BinaryOperation* expr) {
284 BAILOUT("BinaryOperation");
285 }
286
287
288 void ExpressionBuilder::VisitCompareOperation(CompareOperation* expr) {
289 BAILOUT("CompareOperation");
290 }
291
292
293 void ExpressionBuilder::VisitThisFunction(ThisFunction* expr) {
294 BAILOUT("ThisFunction");
295 }
296
297 #undef BAILOUT
298 #undef CHECK_BAILOUT
299
300
301 // Macros (temporarily) handling unsupported statement types.
302 #define BAILOUT(reason) \
303 do { \
304 cfg_ = NULL; \
305 return; \
306 } while (false)
307
308 #define CHECK_BAILOUT() \
309 if (cfg_ == NULL) { return; } else {}
310
311 void StatementBuilder::VisitStatements(ZoneList<Statement*>* stmts) {
312 for (int i = 0, len = stmts->length(); i < len; i++) {
313 Visit(stmts->at(i));
314 CHECK_BAILOUT();
315 if (!cfg_->has_exit()) return;
316 }
317 }
318
319
320 // The statement builder should not be used for declarations or expressions.
321 void StatementBuilder::VisitDeclaration(Declaration* decl) { UNREACHABLE(); }
322
323 #define DEFINE_VISIT(type) \
324 void StatementBuilder::Visit##type(type* expr) { UNREACHABLE(); }
325 EXPRESSION_NODE_LIST(DEFINE_VISIT)
326 #undef DEFINE_VISIT
327
328
329 void StatementBuilder::VisitBlock(Block* stmt) {
330 VisitStatements(stmt->statements());
331 }
332
333
334 void StatementBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
335 BAILOUT("ExpressionStatement");
336 }
337
338
339 void StatementBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
340 // Nothing to do.
341 }
342
343
344 void StatementBuilder::VisitIfStatement(IfStatement* stmt) {
345 BAILOUT("IfStatement");
346 }
347
348
349 void StatementBuilder::VisitContinueStatement(ContinueStatement* stmt) {
350 BAILOUT("ContinueStatement");
351 }
352
353
354 void StatementBuilder::VisitBreakStatement(BreakStatement* stmt) {
355 BAILOUT("BreakStatement");
356 }
357
358
359 void StatementBuilder::VisitReturnStatement(ReturnStatement* stmt) {
360 ExpressionBuilder builder;
361 builder.Visit(stmt->expression());
362 Value* value = builder.value();
363 if (value == NULL) BAILOUT("unsupported expression type");
364 cfg_->AppendReturnInstruction(value);
365 }
366
367
368 void StatementBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
369 BAILOUT("WithEnterStatement");
370 }
371
372
373 void StatementBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
374 BAILOUT("WithExitStatement");
375 }
376
377
378 void StatementBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
379 BAILOUT("SwitchStatement");
380 }
381
382
383 void StatementBuilder::VisitLoopStatement(LoopStatement* stmt) {
384 BAILOUT("LoopStatement");
385 }
386
387
388 void StatementBuilder::VisitForInStatement(ForInStatement* stmt) {
389 BAILOUT("ForInStatement");
390 }
391
392
393 void StatementBuilder::VisitTryCatch(TryCatch* stmt) {
394 BAILOUT("TryCatch");
395 }
396
397
398 void StatementBuilder::VisitTryFinally(TryFinally* stmt) {
399 BAILOUT("TryFinally");
400 }
401
402
403 void StatementBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
404 BAILOUT("DebuggerStatement");
405 }
406
407
408 #ifdef DEBUG
409 // CFG printing support (via depth-first, preorder block traversal).
410
411 void Cfg::Print() {
412 entry_->Print();
413 entry_->Unmark();
414 }
415
416
417 void Constant::Print() {
418 handle_->Print();
419 }
420
421
422 void ReturnInstr::Print() {
423 PrintF("Return ");
424 value_->Print();
425 PrintF("\n");
426 }
427
428
429 int CfgNode::node_counter_ = 0;
430
431
432 void InstructionBlock::Print() {
433 if (!is_marked_) {
434 is_marked_ = true;
435 PrintF("L%d:\n", number());
436 for (int i = 0, len = instructions_.length(); i < len; i++) {
437 instructions_[i]->Print();
438 }
439 PrintF("Goto L%d\n\n", successor_->number());
440 successor_->Print();
441 }
442 }
443
444
445 void EntryNode::Print() {
446 if (!is_marked_) {
447 is_marked_ = true;
448 successor_->Print();
449 }
450 }
451
452
453 void ExitNode::Print() {
454 if (!is_marked_) {
455 is_marked_ = true;
456 PrintF("L%d:\nExit\n\n", number());
457 }
458 }
459
460 #endif // DEBUG
461
462 } } // namespace v8::internal
OLDNEW
« src/cfg.h ('K') | « src/cfg.h ('k') | src/compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698