• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2010 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 "data-flow.h"
31 
32 namespace v8 {
33 namespace internal {
34 
35 
Label(CompilationInfo * info)36 void AstLabeler::Label(CompilationInfo* info) {
37   info_ = info;
38   VisitStatements(info_->function()->body());
39 }
40 
41 
VisitStatements(ZoneList<Statement * > * stmts)42 void AstLabeler::VisitStatements(ZoneList<Statement*>* stmts) {
43   for (int i = 0, len = stmts->length(); i < len; i++) {
44     Visit(stmts->at(i));
45   }
46 }
47 
48 
VisitDeclarations(ZoneList<Declaration * > * decls)49 void AstLabeler::VisitDeclarations(ZoneList<Declaration*>* decls) {
50   UNREACHABLE();
51 }
52 
53 
VisitBlock(Block * stmt)54 void AstLabeler::VisitBlock(Block* stmt) {
55   VisitStatements(stmt->statements());
56 }
57 
58 
VisitExpressionStatement(ExpressionStatement * stmt)59 void AstLabeler::VisitExpressionStatement(
60     ExpressionStatement* stmt) {
61   Visit(stmt->expression());
62 }
63 
64 
VisitEmptyStatement(EmptyStatement * stmt)65 void AstLabeler::VisitEmptyStatement(EmptyStatement* stmt) {
66   // Do nothing.
67 }
68 
69 
VisitIfStatement(IfStatement * stmt)70 void AstLabeler::VisitIfStatement(IfStatement* stmt) {
71   UNREACHABLE();
72 }
73 
74 
VisitContinueStatement(ContinueStatement * stmt)75 void AstLabeler::VisitContinueStatement(ContinueStatement* stmt) {
76   UNREACHABLE();
77 }
78 
79 
VisitBreakStatement(BreakStatement * stmt)80 void AstLabeler::VisitBreakStatement(BreakStatement* stmt) {
81   UNREACHABLE();
82 }
83 
84 
VisitReturnStatement(ReturnStatement * stmt)85 void AstLabeler::VisitReturnStatement(ReturnStatement* stmt) {
86   UNREACHABLE();
87 }
88 
89 
VisitWithEnterStatement(WithEnterStatement * stmt)90 void AstLabeler::VisitWithEnterStatement(
91     WithEnterStatement* stmt) {
92   UNREACHABLE();
93 }
94 
95 
VisitWithExitStatement(WithExitStatement * stmt)96 void AstLabeler::VisitWithExitStatement(WithExitStatement* stmt) {
97   UNREACHABLE();
98 }
99 
100 
VisitSwitchStatement(SwitchStatement * stmt)101 void AstLabeler::VisitSwitchStatement(SwitchStatement* stmt) {
102   UNREACHABLE();
103 }
104 
105 
VisitDoWhileStatement(DoWhileStatement * stmt)106 void AstLabeler::VisitDoWhileStatement(DoWhileStatement* stmt) {
107   UNREACHABLE();
108 }
109 
110 
VisitWhileStatement(WhileStatement * stmt)111 void AstLabeler::VisitWhileStatement(WhileStatement* stmt) {
112   UNREACHABLE();
113 }
114 
115 
VisitForStatement(ForStatement * stmt)116 void AstLabeler::VisitForStatement(ForStatement* stmt) {
117   UNREACHABLE();
118 }
119 
120 
VisitForInStatement(ForInStatement * stmt)121 void AstLabeler::VisitForInStatement(ForInStatement* stmt) {
122   UNREACHABLE();
123 }
124 
125 
VisitTryCatchStatement(TryCatchStatement * stmt)126 void AstLabeler::VisitTryCatchStatement(TryCatchStatement* stmt) {
127   UNREACHABLE();
128 }
129 
130 
VisitTryFinallyStatement(TryFinallyStatement * stmt)131 void AstLabeler::VisitTryFinallyStatement(
132     TryFinallyStatement* stmt) {
133   UNREACHABLE();
134 }
135 
136 
VisitDebuggerStatement(DebuggerStatement * stmt)137 void AstLabeler::VisitDebuggerStatement(
138     DebuggerStatement* stmt) {
139   UNREACHABLE();
140 }
141 
142 
VisitFunctionLiteral(FunctionLiteral * expr)143 void AstLabeler::VisitFunctionLiteral(FunctionLiteral* expr) {
144   UNREACHABLE();
145 }
146 
147 
VisitFunctionBoilerplateLiteral(FunctionBoilerplateLiteral * expr)148 void AstLabeler::VisitFunctionBoilerplateLiteral(
149     FunctionBoilerplateLiteral* expr) {
150   UNREACHABLE();
151 }
152 
153 
VisitConditional(Conditional * expr)154 void AstLabeler::VisitConditional(Conditional* expr) {
155   UNREACHABLE();
156 }
157 
158 
VisitSlot(Slot * expr)159 void AstLabeler::VisitSlot(Slot* expr) {
160   UNREACHABLE();
161 }
162 
163 
VisitVariableProxy(VariableProxy * expr)164 void AstLabeler::VisitVariableProxy(VariableProxy* expr) {
165   expr->set_num(next_number_++);
166   Variable* var = expr->var();
167   if (var->is_global() && !var->is_this()) {
168     info_->set_has_globals(true);
169   }
170 }
171 
172 
VisitLiteral(Literal * expr)173 void AstLabeler::VisitLiteral(Literal* expr) {
174   UNREACHABLE();
175 }
176 
177 
VisitRegExpLiteral(RegExpLiteral * expr)178 void AstLabeler::VisitRegExpLiteral(RegExpLiteral* expr) {
179   UNREACHABLE();
180 }
181 
182 
VisitObjectLiteral(ObjectLiteral * expr)183 void AstLabeler::VisitObjectLiteral(ObjectLiteral* expr) {
184   UNREACHABLE();
185 }
186 
187 
VisitArrayLiteral(ArrayLiteral * expr)188 void AstLabeler::VisitArrayLiteral(ArrayLiteral* expr) {
189   UNREACHABLE();
190 }
191 
192 
VisitCatchExtensionObject(CatchExtensionObject * expr)193 void AstLabeler::VisitCatchExtensionObject(
194     CatchExtensionObject* expr) {
195   UNREACHABLE();
196 }
197 
198 
VisitAssignment(Assignment * expr)199 void AstLabeler::VisitAssignment(Assignment* expr) {
200   Property* prop = expr->target()->AsProperty();
201   ASSERT(prop != NULL);
202   ASSERT(prop->key()->IsPropertyName());
203   VariableProxy* proxy = prop->obj()->AsVariableProxy();
204   USE(proxy);
205   ASSERT(proxy != NULL && proxy->var()->is_this());
206   info()->set_has_this_properties(true);
207   Visit(expr->value());
208   expr->set_num(next_number_++);
209 }
210 
211 
VisitThrow(Throw * expr)212 void AstLabeler::VisitThrow(Throw* expr) {
213   UNREACHABLE();
214 }
215 
216 
VisitProperty(Property * expr)217 void AstLabeler::VisitProperty(Property* expr) {
218   ASSERT(expr->key()->IsPropertyName());
219   VariableProxy* proxy = expr->obj()->AsVariableProxy();
220   USE(proxy);
221   ASSERT(proxy != NULL && proxy->var()->is_this());
222   info()->set_has_this_properties(true);
223   expr->set_num(next_number_++);
224 }
225 
226 
VisitCall(Call * expr)227 void AstLabeler::VisitCall(Call* expr) {
228   UNREACHABLE();
229 }
230 
231 
VisitCallNew(CallNew * expr)232 void AstLabeler::VisitCallNew(CallNew* expr) {
233   UNREACHABLE();
234 }
235 
236 
VisitCallRuntime(CallRuntime * expr)237 void AstLabeler::VisitCallRuntime(CallRuntime* expr) {
238   UNREACHABLE();
239 }
240 
241 
VisitUnaryOperation(UnaryOperation * expr)242 void AstLabeler::VisitUnaryOperation(UnaryOperation* expr) {
243   UNREACHABLE();
244 }
245 
246 
VisitCountOperation(CountOperation * expr)247 void AstLabeler::VisitCountOperation(CountOperation* expr) {
248   UNREACHABLE();
249 }
250 
251 
VisitBinaryOperation(BinaryOperation * expr)252 void AstLabeler::VisitBinaryOperation(BinaryOperation* expr) {
253   Visit(expr->left());
254   Visit(expr->right());
255   expr->set_num(next_number_++);
256 }
257 
258 
VisitCompareOperation(CompareOperation * expr)259 void AstLabeler::VisitCompareOperation(CompareOperation* expr) {
260   UNREACHABLE();
261 }
262 
263 
VisitThisFunction(ThisFunction * expr)264 void AstLabeler::VisitThisFunction(ThisFunction* expr) {
265   UNREACHABLE();
266 }
267 
268 
VisitDeclaration(Declaration * decl)269 void AstLabeler::VisitDeclaration(Declaration* decl) {
270   UNREACHABLE();
271 }
272 
273 
Lookup(Variable * var)274 ZoneList<Expression*>* VarUseMap::Lookup(Variable* var) {
275   HashMap::Entry* entry = HashMap::Lookup(var, var->name()->Hash(), true);
276   if (entry->value == NULL) {
277     entry->value = new ZoneList<Expression*>(1);
278   }
279   return reinterpret_cast<ZoneList<Expression*>*>(entry->value);
280 }
281 
282 
Analyze(FunctionLiteral * fun)283 void LivenessAnalyzer::Analyze(FunctionLiteral* fun) {
284   // Process the function body.
285   VisitStatements(fun->body());
286 
287   // All variables are implicitly defined at the function start.
288   // Record a definition of all variables live at function entry.
289   for (HashMap::Entry* p = live_vars_.Start();
290        p != NULL;
291        p = live_vars_.Next(p)) {
292     Variable* var = reinterpret_cast<Variable*>(p->key);
293     RecordDef(var, fun);
294   }
295 }
296 
297 
VisitStatements(ZoneList<Statement * > * stmts)298 void LivenessAnalyzer::VisitStatements(ZoneList<Statement*>* stmts) {
299   // Visit statements right-to-left.
300   for (int i = stmts->length() - 1; i >= 0; i--) {
301     Visit(stmts->at(i));
302   }
303 }
304 
305 
RecordUse(Variable * var,Expression * expr)306 void LivenessAnalyzer::RecordUse(Variable* var, Expression* expr) {
307   ASSERT(var->is_global() || var->is_this());
308   ZoneList<Expression*>* uses = live_vars_.Lookup(var);
309   uses->Add(expr);
310 }
311 
312 
RecordDef(Variable * var,Expression * expr)313 void LivenessAnalyzer::RecordDef(Variable* var, Expression* expr) {
314   ASSERT(var->is_global() || var->is_this());
315 
316   // We do not support other expressions that can define variables.
317   ASSERT(expr->AsFunctionLiteral() != NULL);
318 
319   // Add the variable to the list of defined variables.
320   if (expr->defined_vars() == NULL) {
321     expr->set_defined_vars(new ZoneList<DefinitionInfo*>(1));
322   }
323   DefinitionInfo* def = new DefinitionInfo();
324   expr->AsFunctionLiteral()->defined_vars()->Add(def);
325 
326   // Compute the last use of the definition. The variable uses are
327   // inserted in reversed evaluation order. The first element
328   // in the list of live uses is the last use.
329   ZoneList<Expression*>* uses = live_vars_.Lookup(var);
330   while (uses->length() > 0) {
331     Expression* use_site = uses->RemoveLast();
332     use_site->set_var_def(def);
333     if (uses->length() == 0) {
334       def->set_last_use(use_site);
335     }
336   }
337 }
338 
339 
340 // Visitor functions for live variable analysis.
VisitDeclaration(Declaration * decl)341 void LivenessAnalyzer::VisitDeclaration(Declaration* decl) {
342   UNREACHABLE();
343 }
344 
345 
VisitBlock(Block * stmt)346 void LivenessAnalyzer::VisitBlock(Block* stmt) {
347   VisitStatements(stmt->statements());
348 }
349 
350 
VisitExpressionStatement(ExpressionStatement * stmt)351 void LivenessAnalyzer::VisitExpressionStatement(
352     ExpressionStatement* stmt) {
353   Visit(stmt->expression());
354 }
355 
356 
VisitEmptyStatement(EmptyStatement * stmt)357 void LivenessAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) {
358   // Do nothing.
359 }
360 
361 
VisitIfStatement(IfStatement * stmt)362 void LivenessAnalyzer::VisitIfStatement(IfStatement* stmt) {
363   UNREACHABLE();
364 }
365 
366 
VisitContinueStatement(ContinueStatement * stmt)367 void LivenessAnalyzer::VisitContinueStatement(ContinueStatement* stmt) {
368   UNREACHABLE();
369 }
370 
371 
VisitBreakStatement(BreakStatement * stmt)372 void LivenessAnalyzer::VisitBreakStatement(BreakStatement* stmt) {
373   UNREACHABLE();
374 }
375 
376 
VisitReturnStatement(ReturnStatement * stmt)377 void LivenessAnalyzer::VisitReturnStatement(ReturnStatement* stmt) {
378   UNREACHABLE();
379 }
380 
381 
VisitWithEnterStatement(WithEnterStatement * stmt)382 void LivenessAnalyzer::VisitWithEnterStatement(
383     WithEnterStatement* stmt) {
384   UNREACHABLE();
385 }
386 
387 
VisitWithExitStatement(WithExitStatement * stmt)388 void LivenessAnalyzer::VisitWithExitStatement(WithExitStatement* stmt) {
389   UNREACHABLE();
390 }
391 
392 
VisitSwitchStatement(SwitchStatement * stmt)393 void LivenessAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) {
394   UNREACHABLE();
395 }
396 
397 
VisitDoWhileStatement(DoWhileStatement * stmt)398 void LivenessAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) {
399   UNREACHABLE();
400 }
401 
402 
VisitWhileStatement(WhileStatement * stmt)403 void LivenessAnalyzer::VisitWhileStatement(WhileStatement* stmt) {
404   UNREACHABLE();
405 }
406 
407 
VisitForStatement(ForStatement * stmt)408 void LivenessAnalyzer::VisitForStatement(ForStatement* stmt) {
409   UNREACHABLE();
410 }
411 
412 
VisitForInStatement(ForInStatement * stmt)413 void LivenessAnalyzer::VisitForInStatement(ForInStatement* stmt) {
414   UNREACHABLE();
415 }
416 
417 
VisitTryCatchStatement(TryCatchStatement * stmt)418 void LivenessAnalyzer::VisitTryCatchStatement(TryCatchStatement* stmt) {
419   UNREACHABLE();
420 }
421 
422 
VisitTryFinallyStatement(TryFinallyStatement * stmt)423 void LivenessAnalyzer::VisitTryFinallyStatement(
424     TryFinallyStatement* stmt) {
425   UNREACHABLE();
426 }
427 
428 
VisitDebuggerStatement(DebuggerStatement * stmt)429 void LivenessAnalyzer::VisitDebuggerStatement(
430     DebuggerStatement* stmt) {
431   UNREACHABLE();
432 }
433 
434 
VisitFunctionLiteral(FunctionLiteral * expr)435 void LivenessAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) {
436   UNREACHABLE();
437 }
438 
439 
VisitFunctionBoilerplateLiteral(FunctionBoilerplateLiteral * expr)440 void LivenessAnalyzer::VisitFunctionBoilerplateLiteral(
441     FunctionBoilerplateLiteral* expr) {
442   UNREACHABLE();
443 }
444 
445 
VisitConditional(Conditional * expr)446 void LivenessAnalyzer::VisitConditional(Conditional* expr) {
447   UNREACHABLE();
448 }
449 
450 
VisitSlot(Slot * expr)451 void LivenessAnalyzer::VisitSlot(Slot* expr) {
452   UNREACHABLE();
453 }
454 
455 
VisitVariableProxy(VariableProxy * expr)456 void LivenessAnalyzer::VisitVariableProxy(VariableProxy* expr) {
457   Variable* var = expr->var();
458   ASSERT(var->is_global());
459   ASSERT(!var->is_this());
460   RecordUse(var, expr);
461 }
462 
463 
VisitLiteral(Literal * expr)464 void LivenessAnalyzer::VisitLiteral(Literal* expr) {
465   UNREACHABLE();
466 }
467 
468 
VisitRegExpLiteral(RegExpLiteral * expr)469 void LivenessAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) {
470   UNREACHABLE();
471 }
472 
473 
VisitObjectLiteral(ObjectLiteral * expr)474 void LivenessAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) {
475   UNREACHABLE();
476 }
477 
478 
VisitArrayLiteral(ArrayLiteral * expr)479 void LivenessAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) {
480   UNREACHABLE();
481 }
482 
483 
VisitCatchExtensionObject(CatchExtensionObject * expr)484 void LivenessAnalyzer::VisitCatchExtensionObject(
485     CatchExtensionObject* expr) {
486   UNREACHABLE();
487 }
488 
489 
VisitAssignment(Assignment * expr)490 void LivenessAnalyzer::VisitAssignment(Assignment* expr) {
491   Property* prop = expr->target()->AsProperty();
492   ASSERT(prop != NULL);
493   ASSERT(prop->key()->IsPropertyName());
494   VariableProxy* proxy = prop->obj()->AsVariableProxy();
495   ASSERT(proxy != NULL && proxy->var()->is_this());
496 
497   // Record use of this at the assignment node. Assignments to
498   // this-properties are treated like unary operations.
499   RecordUse(proxy->var(), expr);
500 
501   // Visit right-hand side.
502   Visit(expr->value());
503 }
504 
505 
VisitThrow(Throw * expr)506 void LivenessAnalyzer::VisitThrow(Throw* expr) {
507   UNREACHABLE();
508 }
509 
510 
VisitProperty(Property * expr)511 void LivenessAnalyzer::VisitProperty(Property* expr) {
512   ASSERT(expr->key()->IsPropertyName());
513   VariableProxy* proxy = expr->obj()->AsVariableProxy();
514   ASSERT(proxy != NULL && proxy->var()->is_this());
515   RecordUse(proxy->var(), expr);
516 }
517 
518 
VisitCall(Call * expr)519 void LivenessAnalyzer::VisitCall(Call* expr) {
520   UNREACHABLE();
521 }
522 
523 
VisitCallNew(CallNew * expr)524 void LivenessAnalyzer::VisitCallNew(CallNew* expr) {
525   UNREACHABLE();
526 }
527 
528 
VisitCallRuntime(CallRuntime * expr)529 void LivenessAnalyzer::VisitCallRuntime(CallRuntime* expr) {
530   UNREACHABLE();
531 }
532 
533 
VisitUnaryOperation(UnaryOperation * expr)534 void LivenessAnalyzer::VisitUnaryOperation(UnaryOperation* expr) {
535   UNREACHABLE();
536 }
537 
538 
VisitCountOperation(CountOperation * expr)539 void LivenessAnalyzer::VisitCountOperation(CountOperation* expr) {
540   UNREACHABLE();
541 }
542 
543 
VisitBinaryOperation(BinaryOperation * expr)544 void LivenessAnalyzer::VisitBinaryOperation(BinaryOperation* expr) {
545   // Visit child nodes in reverse evaluation order.
546   Visit(expr->right());
547   Visit(expr->left());
548 }
549 
550 
VisitCompareOperation(CompareOperation * expr)551 void LivenessAnalyzer::VisitCompareOperation(CompareOperation* expr) {
552   UNREACHABLE();
553 }
554 
555 
VisitThisFunction(ThisFunction * expr)556 void LivenessAnalyzer::VisitThisFunction(ThisFunction* expr) {
557   UNREACHABLE();
558 }
559 
560 
561 } }  // namespace v8::internal
562