Home | History | Annotate | Download | only in src
      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
     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 
     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 
     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 
     76 AssignedVariablesAnalyzer::AssignedVariablesAnalyzer(CompilationInfo* info,
     77                                                      int size)
     78     : info_(info), av_(size) {
     79 }
     80 
     81 
     82 bool AssignedVariablesAnalyzer::Analyze() {
     83   ASSERT(av_.length() > 0);
     84   VisitStatements(info_->function()->body());
     85   return !HasStackOverflow();
     86 }
     87 
     88 
     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 
    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 
    163 void AssignedVariablesAnalyzer::RecordAssignedVar(Variable* var) {
    164   ASSERT(var != NULL);
    165   if (var->IsStackAllocated()) {
    166     av_.Add(BitIndex(var));
    167   }
    168 }
    169 
    170 
    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 
    183 void AssignedVariablesAnalyzer::ProcessExpression(Expression* expr) {
    184   BitVector saved_av(av_);
    185   av_.Clear();
    186   Visit(expr);
    187   av_.Union(saved_av);
    188 }
    189 
    190 void AssignedVariablesAnalyzer::VisitBlock(Block* stmt) {
    191   VisitStatements(stmt->statements());
    192 }
    193 
    194 
    195 void AssignedVariablesAnalyzer::VisitExpressionStatement(
    196     ExpressionStatement* stmt) {
    197   ProcessExpression(stmt->expression());
    198 }
    199 
    200 
    201 void AssignedVariablesAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) {
    202   // Do nothing.
    203 }
    204 
    205 
    206 void AssignedVariablesAnalyzer::VisitIfStatement(IfStatement* stmt) {
    207   ProcessExpression(stmt->condition());
    208   Visit(stmt->then_statement());
    209   Visit(stmt->else_statement());
    210 }
    211 
    212 
    213 void AssignedVariablesAnalyzer::VisitContinueStatement(
    214     ContinueStatement* stmt) {
    215   // Nothing to do.
    216 }
    217 
    218 
    219 void AssignedVariablesAnalyzer::VisitBreakStatement(BreakStatement* stmt) {
    220   // Nothing to do.
    221 }
    222 
    223 
    224 void AssignedVariablesAnalyzer::VisitReturnStatement(ReturnStatement* stmt) {
    225   ProcessExpression(stmt->expression());
    226 }
    227 
    228 
    229 void AssignedVariablesAnalyzer::VisitWithEnterStatement(
    230     WithEnterStatement* stmt) {
    231   ProcessExpression(stmt->expression());
    232 }
    233 
    234 
    235 void AssignedVariablesAnalyzer::VisitWithExitStatement(
    236     WithExitStatement* stmt) {
    237   // Nothing to do.
    238 }
    239 
    240 
    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 
    259 void AssignedVariablesAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) {
    260   ProcessExpression(stmt->cond());
    261   Visit(stmt->body());
    262 }
    263 
    264 
    265 void AssignedVariablesAnalyzer::VisitWhileStatement(WhileStatement* stmt) {
    266   ProcessExpression(stmt->cond());
    267   Visit(stmt->body());
    268 }
    269 
    270 
    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 
    290 void AssignedVariablesAnalyzer::VisitForInStatement(ForInStatement* stmt) {
    291   ProcessExpression(stmt->each());
    292   ProcessExpression(stmt->enumerable());
    293   Visit(stmt->body());
    294 }
    295 
    296 
    297 void AssignedVariablesAnalyzer::VisitTryCatchStatement(
    298     TryCatchStatement* stmt) {
    299   Visit(stmt->try_block());
    300   Visit(stmt->catch_block());
    301 }
    302 
    303 
    304 void AssignedVariablesAnalyzer::VisitTryFinallyStatement(
    305     TryFinallyStatement* stmt) {
    306   Visit(stmt->try_block());
    307   Visit(stmt->finally_block());
    308 }
    309 
    310 
    311 void AssignedVariablesAnalyzer::VisitDebuggerStatement(
    312     DebuggerStatement* stmt) {
    313   // Nothing to do.
    314 }
    315 
    316 
    317 void AssignedVariablesAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) {
    318   // Nothing to do.
    319   ASSERT(av_.IsEmpty());
    320 }
    321 
    322 
    323 void AssignedVariablesAnalyzer::VisitSharedFunctionInfoLiteral(
    324     SharedFunctionInfoLiteral* expr) {
    325   // Nothing to do.
    326   ASSERT(av_.IsEmpty());
    327 }
    328 
    329 
    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 
    346 void AssignedVariablesAnalyzer::VisitVariableProxy(VariableProxy* expr) {
    347   // Nothing to do.
    348   ASSERT(av_.IsEmpty());
    349 }
    350 
    351 
    352 void AssignedVariablesAnalyzer::VisitLiteral(Literal* expr) {
    353   // Nothing to do.
    354   ASSERT(av_.IsEmpty());
    355 }
    356 
    357 
    358 void AssignedVariablesAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) {
    359   // Nothing to do.
    360   ASSERT(av_.IsEmpty());
    361 }
    362 
    363 
    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 
    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 
    388 void AssignedVariablesAnalyzer::VisitCatchExtensionObject(
    389     CatchExtensionObject* expr) {
    390   ASSERT(av_.IsEmpty());
    391   Visit(expr->key());
    392   ProcessExpression(expr->value());
    393 }
    394 
    395 
    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 
    431 void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) {
    432   ASSERT(av_.IsEmpty());
    433   Visit(expr->exception());
    434 }
    435 
    436 
    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 
    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 
    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 
    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 
    486 void AssignedVariablesAnalyzer::VisitUnaryOperation(UnaryOperation* expr) {
    487   ASSERT(av_.IsEmpty());
    488   MarkIfTrivial(expr->expression());
    489   Visit(expr->expression());
    490 }
    491 
    492 
    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 
    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 
    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 
    521 void AssignedVariablesAnalyzer::VisitCompareToNull(CompareToNull* expr) {
    522   ASSERT(av_.IsEmpty());
    523   MarkIfTrivial(expr->expression());
    524   Visit(expr->expression());
    525 }
    526 
    527 
    528 void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) {
    529   // Nothing to do.
    530   ASSERT(av_.IsEmpty());
    531 }
    532 
    533 
    534 void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) {
    535   UNREACHABLE();
    536 }
    537 
    538 
    539 } }  // namespace v8::internal
    540