• 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 #include "scopes.h"
32 
33 namespace v8 {
34 namespace internal {
35 
36 #ifdef DEBUG
Print()37 void BitVector::Print() {
38   bool first = true;
39   PrintF("{");
40   for (int i = 0; i < length(); i++) {
41     if (Contains(i)) {
42       if (!first) PrintF(",");
43       first = false;
44       PrintF("%d", i);
45     }
46   }
47   PrintF("}");
48 }
49 #endif
50 
51 
Advance()52 void BitVector::Iterator::Advance() {
53   current_++;
54   uint32_t val = current_value_;
55   while (val == 0) {
56     current_index_++;
57     if (Done()) return;
58     val = target_->data_[current_index_];
59     current_ = current_index_ << 5;
60   }
61   val = SkipZeroBytes(val);
62   val = SkipZeroBits(val);
63   current_value_ = val >> 1;
64 }
65 
66 
Analyze(CompilationInfo * info)67 bool AssignedVariablesAnalyzer::Analyze(CompilationInfo* info) {
68   Scope* scope = info->scope();
69   int size = scope->num_parameters() + scope->num_stack_slots();
70   if (size == 0) return true;
71   AssignedVariablesAnalyzer analyzer(info, size);
72   return analyzer.Analyze();
73 }
74 
75 
AssignedVariablesAnalyzer(CompilationInfo * info,int size)76 AssignedVariablesAnalyzer::AssignedVariablesAnalyzer(CompilationInfo* info,
77                                                      int size)
78     : info_(info), av_(size) {
79 }
80 
81 
Analyze()82 bool AssignedVariablesAnalyzer::Analyze() {
83   ASSERT(av_.length() > 0);
84   VisitStatements(info_->function()->body());
85   return !HasStackOverflow();
86 }
87 
88 
FindSmiLoopVariable(ForStatement * stmt)89 Variable* AssignedVariablesAnalyzer::FindSmiLoopVariable(ForStatement* stmt) {
90   // The loop must have all necessary parts.
91   if (stmt->init() == NULL || stmt->cond() == NULL || stmt->next() == NULL) {
92     return NULL;
93   }
94   // The initialization statement has to be a simple assignment.
95   Assignment* init = stmt->init()->StatementAsSimpleAssignment();
96   if (init == NULL) return NULL;
97 
98   // We only deal with local variables.
99   Variable* loop_var = init->target()->AsVariableProxy()->AsVariable();
100   if (loop_var == NULL || !loop_var->IsStackAllocated()) return NULL;
101 
102   // Don't try to get clever with const or dynamic variables.
103   if (loop_var->mode() != Variable::VAR) return NULL;
104 
105   // The initial value has to be a smi.
106   Literal* init_lit = init->value()->AsLiteral();
107   if (init_lit == NULL || !init_lit->handle()->IsSmi()) return NULL;
108   int init_value = Smi::cast(*init_lit->handle())->value();
109 
110   // The condition must be a compare of variable with <, <=, >, or >=.
111   CompareOperation* cond = stmt->cond()->AsCompareOperation();
112   if (cond == NULL) return NULL;
113   if (cond->op() != Token::LT
114       && cond->op() != Token::LTE
115       && cond->op() != Token::GT
116       && cond->op() != Token::GTE) return NULL;
117 
118   // The lhs must be the same variable as in the init expression.
119   if (cond->left()->AsVariableProxy()->AsVariable() != loop_var) return NULL;
120 
121   // The rhs must be a smi.
122   Literal* term_lit = cond->right()->AsLiteral();
123   if (term_lit == NULL || !term_lit->handle()->IsSmi()) return NULL;
124   int term_value = Smi::cast(*term_lit->handle())->value();
125 
126   // The count operation updates the same variable as in the init expression.
127   CountOperation* update = stmt->next()->StatementAsCountOperation();
128   if (update == NULL) return NULL;
129   if (update->expression()->AsVariableProxy()->AsVariable() != loop_var) {
130     return NULL;
131   }
132 
133   // The direction of the count operation must agree with the start and the end
134   // value. We currently do not allow the initial value to be the same as the
135   // terminal value. This _would_ be ok as long as the loop body never executes
136   // or executes exactly one time.
137   if (init_value == term_value) return NULL;
138   if (init_value < term_value && update->op() != Token::INC) return NULL;
139   if (init_value > term_value && update->op() != Token::DEC) return NULL;
140 
141   // Check that the update operation cannot overflow the smi range. This can
142   // occur in the two cases where the loop bound is equal to the largest or
143   // smallest smi.
144   if (update->op() == Token::INC && term_value == Smi::kMaxValue) return NULL;
145   if (update->op() == Token::DEC && term_value == Smi::kMinValue) return NULL;
146 
147   // Found a smi loop variable.
148   return loop_var;
149 }
150 
BitIndex(Variable * var)151 int AssignedVariablesAnalyzer::BitIndex(Variable* var) {
152   ASSERT(var != NULL);
153   ASSERT(var->IsStackAllocated());
154   Slot* slot = var->AsSlot();
155   if (slot->type() == Slot::PARAMETER) {
156     return slot->index();
157   } else {
158     return info_->scope()->num_parameters() + slot->index();
159   }
160 }
161 
162 
RecordAssignedVar(Variable * var)163 void AssignedVariablesAnalyzer::RecordAssignedVar(Variable* var) {
164   ASSERT(var != NULL);
165   if (var->IsStackAllocated()) {
166     av_.Add(BitIndex(var));
167   }
168 }
169 
170 
MarkIfTrivial(Expression * expr)171 void AssignedVariablesAnalyzer::MarkIfTrivial(Expression* expr) {
172   Variable* var = expr->AsVariableProxy()->AsVariable();
173   if (var != NULL &&
174       var->IsStackAllocated() &&
175       !var->is_arguments() &&
176       var->mode() != Variable::CONST &&
177       (var->is_this() || !av_.Contains(BitIndex(var)))) {
178     expr->AsVariableProxy()->MarkAsTrivial();
179   }
180 }
181 
182 
ProcessExpression(Expression * expr)183 void AssignedVariablesAnalyzer::ProcessExpression(Expression* expr) {
184   BitVector saved_av(av_);
185   av_.Clear();
186   Visit(expr);
187   av_.Union(saved_av);
188 }
189 
VisitBlock(Block * stmt)190 void AssignedVariablesAnalyzer::VisitBlock(Block* stmt) {
191   VisitStatements(stmt->statements());
192 }
193 
194 
VisitExpressionStatement(ExpressionStatement * stmt)195 void AssignedVariablesAnalyzer::VisitExpressionStatement(
196     ExpressionStatement* stmt) {
197   ProcessExpression(stmt->expression());
198 }
199 
200 
VisitEmptyStatement(EmptyStatement * stmt)201 void AssignedVariablesAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) {
202   // Do nothing.
203 }
204 
205 
VisitIfStatement(IfStatement * stmt)206 void AssignedVariablesAnalyzer::VisitIfStatement(IfStatement* stmt) {
207   ProcessExpression(stmt->condition());
208   Visit(stmt->then_statement());
209   Visit(stmt->else_statement());
210 }
211 
212 
VisitContinueStatement(ContinueStatement * stmt)213 void AssignedVariablesAnalyzer::VisitContinueStatement(
214     ContinueStatement* stmt) {
215   // Nothing to do.
216 }
217 
218 
VisitBreakStatement(BreakStatement * stmt)219 void AssignedVariablesAnalyzer::VisitBreakStatement(BreakStatement* stmt) {
220   // Nothing to do.
221 }
222 
223 
VisitReturnStatement(ReturnStatement * stmt)224 void AssignedVariablesAnalyzer::VisitReturnStatement(ReturnStatement* stmt) {
225   ProcessExpression(stmt->expression());
226 }
227 
228 
VisitWithEnterStatement(WithEnterStatement * stmt)229 void AssignedVariablesAnalyzer::VisitWithEnterStatement(
230     WithEnterStatement* stmt) {
231   ProcessExpression(stmt->expression());
232 }
233 
234 
VisitWithExitStatement(WithExitStatement * stmt)235 void AssignedVariablesAnalyzer::VisitWithExitStatement(
236     WithExitStatement* stmt) {
237   // Nothing to do.
238 }
239 
240 
VisitSwitchStatement(SwitchStatement * stmt)241 void AssignedVariablesAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) {
242   BitVector result(av_);
243   av_.Clear();
244   Visit(stmt->tag());
245   result.Union(av_);
246   for (int i = 0; i < stmt->cases()->length(); i++) {
247     CaseClause* clause = stmt->cases()->at(i);
248     if (!clause->is_default()) {
249       av_.Clear();
250       Visit(clause->label());
251       result.Union(av_);
252     }
253     VisitStatements(clause->statements());
254   }
255   av_.Union(result);
256 }
257 
258 
VisitDoWhileStatement(DoWhileStatement * stmt)259 void AssignedVariablesAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) {
260   ProcessExpression(stmt->cond());
261   Visit(stmt->body());
262 }
263 
264 
VisitWhileStatement(WhileStatement * stmt)265 void AssignedVariablesAnalyzer::VisitWhileStatement(WhileStatement* stmt) {
266   ProcessExpression(stmt->cond());
267   Visit(stmt->body());
268 }
269 
270 
VisitForStatement(ForStatement * stmt)271 void AssignedVariablesAnalyzer::VisitForStatement(ForStatement* stmt) {
272   if (stmt->init() != NULL) Visit(stmt->init());
273   if (stmt->cond() != NULL) ProcessExpression(stmt->cond());
274   if (stmt->next() != NULL) Visit(stmt->next());
275 
276   // Process loop body. After visiting the loop body av_ contains
277   // the assigned variables of the loop body.
278   BitVector saved_av(av_);
279   av_.Clear();
280   Visit(stmt->body());
281 
282   Variable* var = FindSmiLoopVariable(stmt);
283   if (var != NULL && !av_.Contains(BitIndex(var))) {
284     stmt->set_loop_variable(var);
285   }
286   av_.Union(saved_av);
287 }
288 
289 
VisitForInStatement(ForInStatement * stmt)290 void AssignedVariablesAnalyzer::VisitForInStatement(ForInStatement* stmt) {
291   ProcessExpression(stmt->each());
292   ProcessExpression(stmt->enumerable());
293   Visit(stmt->body());
294 }
295 
296 
VisitTryCatchStatement(TryCatchStatement * stmt)297 void AssignedVariablesAnalyzer::VisitTryCatchStatement(
298     TryCatchStatement* stmt) {
299   Visit(stmt->try_block());
300   Visit(stmt->catch_block());
301 }
302 
303 
VisitTryFinallyStatement(TryFinallyStatement * stmt)304 void AssignedVariablesAnalyzer::VisitTryFinallyStatement(
305     TryFinallyStatement* stmt) {
306   Visit(stmt->try_block());
307   Visit(stmt->finally_block());
308 }
309 
310 
VisitDebuggerStatement(DebuggerStatement * stmt)311 void AssignedVariablesAnalyzer::VisitDebuggerStatement(
312     DebuggerStatement* stmt) {
313   // Nothing to do.
314 }
315 
316 
VisitFunctionLiteral(FunctionLiteral * expr)317 void AssignedVariablesAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) {
318   // Nothing to do.
319   ASSERT(av_.IsEmpty());
320 }
321 
322 
VisitSharedFunctionInfoLiteral(SharedFunctionInfoLiteral * expr)323 void AssignedVariablesAnalyzer::VisitSharedFunctionInfoLiteral(
324     SharedFunctionInfoLiteral* expr) {
325   // Nothing to do.
326   ASSERT(av_.IsEmpty());
327 }
328 
329 
VisitConditional(Conditional * expr)330 void AssignedVariablesAnalyzer::VisitConditional(Conditional* expr) {
331   ASSERT(av_.IsEmpty());
332 
333   Visit(expr->condition());
334 
335   BitVector result(av_);
336   av_.Clear();
337   Visit(expr->then_expression());
338   result.Union(av_);
339 
340   av_.Clear();
341   Visit(expr->else_expression());
342   av_.Union(result);
343 }
344 
345 
VisitVariableProxy(VariableProxy * expr)346 void AssignedVariablesAnalyzer::VisitVariableProxy(VariableProxy* expr) {
347   // Nothing to do.
348   ASSERT(av_.IsEmpty());
349 }
350 
351 
VisitLiteral(Literal * expr)352 void AssignedVariablesAnalyzer::VisitLiteral(Literal* expr) {
353   // Nothing to do.
354   ASSERT(av_.IsEmpty());
355 }
356 
357 
VisitRegExpLiteral(RegExpLiteral * expr)358 void AssignedVariablesAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) {
359   // Nothing to do.
360   ASSERT(av_.IsEmpty());
361 }
362 
363 
VisitObjectLiteral(ObjectLiteral * expr)364 void AssignedVariablesAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) {
365   ASSERT(av_.IsEmpty());
366   BitVector result(av_.length());
367   for (int i = 0; i < expr->properties()->length(); i++) {
368     Visit(expr->properties()->at(i)->value());
369     result.Union(av_);
370     av_.Clear();
371   }
372   av_ = result;
373 }
374 
375 
VisitArrayLiteral(ArrayLiteral * expr)376 void AssignedVariablesAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) {
377   ASSERT(av_.IsEmpty());
378   BitVector result(av_.length());
379   for (int i = 0; i < expr->values()->length(); i++) {
380     Visit(expr->values()->at(i));
381     result.Union(av_);
382     av_.Clear();
383   }
384   av_ = result;
385 }
386 
387 
VisitCatchExtensionObject(CatchExtensionObject * expr)388 void AssignedVariablesAnalyzer::VisitCatchExtensionObject(
389     CatchExtensionObject* expr) {
390   ASSERT(av_.IsEmpty());
391   Visit(expr->key());
392   ProcessExpression(expr->value());
393 }
394 
395 
VisitAssignment(Assignment * expr)396 void AssignedVariablesAnalyzer::VisitAssignment(Assignment* expr) {
397   ASSERT(av_.IsEmpty());
398 
399   // There are three kinds of assignments: variable assignments, property
400   // assignments, and reference errors (invalid left-hand sides).
401   Variable* var = expr->target()->AsVariableProxy()->AsVariable();
402   Property* prop = expr->target()->AsProperty();
403   ASSERT(var == NULL || prop == NULL);
404 
405   if (var != NULL) {
406     MarkIfTrivial(expr->value());
407     Visit(expr->value());
408     if (expr->is_compound()) {
409       // Left-hand side occurs also as an rvalue.
410       MarkIfTrivial(expr->target());
411       ProcessExpression(expr->target());
412     }
413     RecordAssignedVar(var);
414 
415   } else if (prop != NULL) {
416     MarkIfTrivial(expr->value());
417     Visit(expr->value());
418     if (!prop->key()->IsPropertyName()) {
419       MarkIfTrivial(prop->key());
420       ProcessExpression(prop->key());
421     }
422     MarkIfTrivial(prop->obj());
423     ProcessExpression(prop->obj());
424 
425   } else {
426     Visit(expr->target());
427   }
428 }
429 
430 
VisitThrow(Throw * expr)431 void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) {
432   ASSERT(av_.IsEmpty());
433   Visit(expr->exception());
434 }
435 
436 
VisitProperty(Property * expr)437 void AssignedVariablesAnalyzer::VisitProperty(Property* expr) {
438   ASSERT(av_.IsEmpty());
439   if (!expr->key()->IsPropertyName()) {
440     MarkIfTrivial(expr->key());
441     Visit(expr->key());
442   }
443   MarkIfTrivial(expr->obj());
444   ProcessExpression(expr->obj());
445 }
446 
447 
VisitCall(Call * expr)448 void AssignedVariablesAnalyzer::VisitCall(Call* expr) {
449   ASSERT(av_.IsEmpty());
450   Visit(expr->expression());
451   BitVector result(av_);
452   for (int i = 0; i < expr->arguments()->length(); i++) {
453     av_.Clear();
454     Visit(expr->arguments()->at(i));
455     result.Union(av_);
456   }
457   av_ = result;
458 }
459 
460 
VisitCallNew(CallNew * expr)461 void AssignedVariablesAnalyzer::VisitCallNew(CallNew* expr) {
462   ASSERT(av_.IsEmpty());
463   Visit(expr->expression());
464   BitVector result(av_);
465   for (int i = 0; i < expr->arguments()->length(); i++) {
466     av_.Clear();
467     Visit(expr->arguments()->at(i));
468     result.Union(av_);
469   }
470   av_ = result;
471 }
472 
473 
VisitCallRuntime(CallRuntime * expr)474 void AssignedVariablesAnalyzer::VisitCallRuntime(CallRuntime* expr) {
475   ASSERT(av_.IsEmpty());
476   BitVector result(av_);
477   for (int i = 0; i < expr->arguments()->length(); i++) {
478     av_.Clear();
479     Visit(expr->arguments()->at(i));
480     result.Union(av_);
481   }
482   av_ = result;
483 }
484 
485 
VisitUnaryOperation(UnaryOperation * expr)486 void AssignedVariablesAnalyzer::VisitUnaryOperation(UnaryOperation* expr) {
487   ASSERT(av_.IsEmpty());
488   MarkIfTrivial(expr->expression());
489   Visit(expr->expression());
490 }
491 
492 
VisitCountOperation(CountOperation * expr)493 void AssignedVariablesAnalyzer::VisitCountOperation(CountOperation* expr) {
494   ASSERT(av_.IsEmpty());
495   if (expr->is_prefix()) MarkIfTrivial(expr->expression());
496   Visit(expr->expression());
497 
498   Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
499   if (var != NULL) RecordAssignedVar(var);
500 }
501 
502 
VisitBinaryOperation(BinaryOperation * expr)503 void AssignedVariablesAnalyzer::VisitBinaryOperation(BinaryOperation* expr) {
504   ASSERT(av_.IsEmpty());
505   MarkIfTrivial(expr->right());
506   Visit(expr->right());
507   MarkIfTrivial(expr->left());
508   ProcessExpression(expr->left());
509 }
510 
511 
VisitCompareOperation(CompareOperation * expr)512 void AssignedVariablesAnalyzer::VisitCompareOperation(CompareOperation* expr) {
513   ASSERT(av_.IsEmpty());
514   MarkIfTrivial(expr->right());
515   Visit(expr->right());
516   MarkIfTrivial(expr->left());
517   ProcessExpression(expr->left());
518 }
519 
520 
VisitCompareToNull(CompareToNull * expr)521 void AssignedVariablesAnalyzer::VisitCompareToNull(CompareToNull* expr) {
522   ASSERT(av_.IsEmpty());
523   MarkIfTrivial(expr->expression());
524   Visit(expr->expression());
525 }
526 
527 
VisitThisFunction(ThisFunction * expr)528 void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) {
529   // Nothing to do.
530   ASSERT(av_.IsEmpty());
531 }
532 
533 
VisitDeclaration(Declaration * decl)534 void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) {
535   UNREACHABLE();
536 }
537 
538 
539 } }  // namespace v8::internal
540