Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 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 "ast.h"
     31 #include "func-name-inferrer.h"
     32 #include "scopes.h"
     33 #include "rewriter.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 
     39 class AstOptimizer: public AstVisitor {
     40  public:
     41   explicit AstOptimizer() : has_function_literal_(false) {}
     42   explicit AstOptimizer(Handle<String> enclosing_name)
     43       : has_function_literal_(false) {
     44     func_name_inferrer_.PushEnclosingName(enclosing_name);
     45   }
     46 
     47   void Optimize(ZoneList<Statement*>* statements);
     48 
     49  private:
     50   // Used for loop condition analysis.  Cleared before visiting a loop
     51   // condition, set when a function literal is visited.
     52   bool has_function_literal_;
     53   // Helper object for function name inferring.
     54   FuncNameInferrer func_name_inferrer_;
     55 
     56   // Helpers
     57   void OptimizeArguments(ZoneList<Expression*>* arguments);
     58 
     59   // Node visitors.
     60 #define DEF_VISIT(type) \
     61   virtual void Visit##type(type* node);
     62   AST_NODE_LIST(DEF_VISIT)
     63 #undef DEF_VISIT
     64 
     65   DISALLOW_COPY_AND_ASSIGN(AstOptimizer);
     66 };
     67 
     68 
     69 void AstOptimizer::Optimize(ZoneList<Statement*>* statements) {
     70   int len = statements->length();
     71   for (int i = 0; i < len; i++) {
     72     Visit(statements->at(i));
     73   }
     74 }
     75 
     76 
     77 void AstOptimizer::OptimizeArguments(ZoneList<Expression*>* arguments) {
     78   for (int i = 0; i < arguments->length(); i++) {
     79     Visit(arguments->at(i));
     80   }
     81 }
     82 
     83 
     84 void AstOptimizer::VisitBlock(Block* node) {
     85   Optimize(node->statements());
     86 }
     87 
     88 
     89 void AstOptimizer::VisitExpressionStatement(ExpressionStatement* node) {
     90   Visit(node->expression());
     91 }
     92 
     93 
     94 void AstOptimizer::VisitIfStatement(IfStatement* node) {
     95   Visit(node->condition());
     96   Visit(node->then_statement());
     97   if (node->HasElseStatement()) {
     98     Visit(node->else_statement());
     99   }
    100 }
    101 
    102 
    103 void AstOptimizer::VisitDoWhileStatement(DoWhileStatement* node) {
    104   Visit(node->cond());
    105   Visit(node->body());
    106 }
    107 
    108 
    109 void AstOptimizer::VisitWhileStatement(WhileStatement* node) {
    110   has_function_literal_ = false;
    111   Visit(node->cond());
    112   node->may_have_function_literal_ = has_function_literal_;
    113   Visit(node->body());
    114 }
    115 
    116 
    117 void AstOptimizer::VisitForStatement(ForStatement* node) {
    118   if (node->init() != NULL) {
    119     Visit(node->init());
    120   }
    121   if (node->cond() != NULL) {
    122     has_function_literal_ = false;
    123     Visit(node->cond());
    124     node->may_have_function_literal_ = has_function_literal_;
    125   }
    126   Visit(node->body());
    127   if (node->next() != NULL) {
    128     Visit(node->next());
    129   }
    130 }
    131 
    132 
    133 void AstOptimizer::VisitForInStatement(ForInStatement* node) {
    134   Visit(node->each());
    135   Visit(node->enumerable());
    136   Visit(node->body());
    137 }
    138 
    139 
    140 void AstOptimizer::VisitTryCatchStatement(TryCatchStatement* node) {
    141   Visit(node->try_block());
    142   Visit(node->catch_var());
    143   Visit(node->catch_block());
    144 }
    145 
    146 
    147 void AstOptimizer::VisitTryFinallyStatement(TryFinallyStatement* node) {
    148   Visit(node->try_block());
    149   Visit(node->finally_block());
    150 }
    151 
    152 
    153 void AstOptimizer::VisitSwitchStatement(SwitchStatement* node) {
    154   Visit(node->tag());
    155   for (int i = 0; i < node->cases()->length(); i++) {
    156     CaseClause* clause = node->cases()->at(i);
    157     if (!clause->is_default()) {
    158       Visit(clause->label());
    159     }
    160     Optimize(clause->statements());
    161   }
    162 }
    163 
    164 
    165 void AstOptimizer::VisitContinueStatement(ContinueStatement* node) {
    166   USE(node);
    167 }
    168 
    169 
    170 void AstOptimizer::VisitBreakStatement(BreakStatement* node) {
    171   USE(node);
    172 }
    173 
    174 
    175 void AstOptimizer::VisitDeclaration(Declaration* node) {
    176   // Will not be reached by the current optimizations.
    177   USE(node);
    178 }
    179 
    180 
    181 void AstOptimizer::VisitEmptyStatement(EmptyStatement* node) {
    182   USE(node);
    183 }
    184 
    185 
    186 void AstOptimizer::VisitReturnStatement(ReturnStatement* node) {
    187   Visit(node->expression());
    188 }
    189 
    190 
    191 void AstOptimizer::VisitWithEnterStatement(WithEnterStatement* node) {
    192   Visit(node->expression());
    193 }
    194 
    195 
    196 void AstOptimizer::VisitWithExitStatement(WithExitStatement* node) {
    197   USE(node);
    198 }
    199 
    200 
    201 void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) {
    202   USE(node);
    203 }
    204 
    205 
    206 void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) {
    207   has_function_literal_ = true;
    208 
    209   if (node->name()->length() == 0) {
    210     // Anonymous function.
    211     func_name_inferrer_.AddFunction(node);
    212   }
    213 }
    214 
    215 
    216 void AstOptimizer::VisitFunctionBoilerplateLiteral(
    217     FunctionBoilerplateLiteral* node) {
    218   USE(node);
    219 }
    220 
    221 
    222 void AstOptimizer::VisitConditional(Conditional* node) {
    223   Visit(node->condition());
    224   Visit(node->then_expression());
    225   Visit(node->else_expression());
    226 }
    227 
    228 
    229 void AstOptimizer::VisitSlot(Slot* node) {
    230   USE(node);
    231 }
    232 
    233 
    234 void AstOptimizer::VisitVariableProxy(VariableProxy* node) {
    235   Variable* var = node->AsVariable();
    236   if (var != NULL) {
    237     if (var->type()->IsKnown()) {
    238       node->type()->CopyFrom(var->type());
    239     } else if (node->type()->IsLikelySmi()) {
    240       var->type()->SetAsLikelySmi();
    241     }
    242 
    243     if (!var->is_this() &&
    244         !Heap::result_symbol()->Equals(*var->name())) {
    245       func_name_inferrer_.PushName(var->name());
    246     }
    247   }
    248 }
    249 
    250 
    251 void AstOptimizer::VisitLiteral(Literal* node) {
    252   Handle<Object> literal = node->handle();
    253   if (literal->IsSmi()) {
    254     node->type()->SetAsLikelySmi();
    255   } else if (literal->IsString()) {
    256     Handle<String> lit_str(Handle<String>::cast(literal));
    257     if (!Heap::prototype_symbol()->Equals(*lit_str)) {
    258       func_name_inferrer_.PushName(lit_str);
    259     }
    260   }
    261 }
    262 
    263 
    264 void AstOptimizer::VisitRegExpLiteral(RegExpLiteral* node) {
    265   USE(node);
    266 }
    267 
    268 
    269 void AstOptimizer::VisitArrayLiteral(ArrayLiteral* node) {
    270   for (int i = 0; i < node->values()->length(); i++) {
    271     Visit(node->values()->at(i));
    272   }
    273 }
    274 
    275 void AstOptimizer::VisitObjectLiteral(ObjectLiteral* node) {
    276   for (int i = 0; i < node->properties()->length(); i++) {
    277     ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_);
    278     scoped_fni.Enter();
    279     Visit(node->properties()->at(i)->key());
    280     Visit(node->properties()->at(i)->value());
    281   }
    282 }
    283 
    284 
    285 void AstOptimizer::VisitCatchExtensionObject(CatchExtensionObject* node) {
    286   Visit(node->key());
    287   Visit(node->value());
    288 }
    289 
    290 
    291 void AstOptimizer::VisitAssignment(Assignment* node) {
    292   ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_);
    293   switch (node->op()) {
    294     case Token::INIT_VAR:
    295     case Token::INIT_CONST:
    296     case Token::ASSIGN:
    297       // No type can be infered from the general assignment.
    298 
    299       // Don't infer if it is "a = function(){...}();"-like expression.
    300       if (node->value()->AsCall() == NULL) {
    301         scoped_fni.Enter();
    302       }
    303       break;
    304     case Token::ASSIGN_BIT_OR:
    305     case Token::ASSIGN_BIT_XOR:
    306     case Token::ASSIGN_BIT_AND:
    307     case Token::ASSIGN_SHL:
    308     case Token::ASSIGN_SAR:
    309     case Token::ASSIGN_SHR:
    310       node->type()->SetAsLikelySmiIfUnknown();
    311       node->target()->type()->SetAsLikelySmiIfUnknown();
    312       node->value()->type()->SetAsLikelySmiIfUnknown();
    313       break;
    314     case Token::ASSIGN_ADD:
    315     case Token::ASSIGN_SUB:
    316     case Token::ASSIGN_MUL:
    317     case Token::ASSIGN_DIV:
    318     case Token::ASSIGN_MOD:
    319       if (node->type()->IsLikelySmi()) {
    320         node->target()->type()->SetAsLikelySmiIfUnknown();
    321         node->value()->type()->SetAsLikelySmiIfUnknown();
    322       }
    323       break;
    324     default:
    325       UNREACHABLE();
    326       break;
    327   }
    328 
    329   Visit(node->target());
    330   Visit(node->value());
    331 
    332   switch (node->op()) {
    333     case Token::INIT_VAR:
    334     case Token::INIT_CONST:
    335     case Token::ASSIGN:
    336       // Pure assignment copies the type from the value.
    337       node->type()->CopyFrom(node->value()->type());
    338       break;
    339     case Token::ASSIGN_BIT_OR:
    340     case Token::ASSIGN_BIT_XOR:
    341     case Token::ASSIGN_BIT_AND:
    342     case Token::ASSIGN_SHL:
    343     case Token::ASSIGN_SAR:
    344     case Token::ASSIGN_SHR:
    345       // Should have been setup above already.
    346       break;
    347     case Token::ASSIGN_ADD:
    348     case Token::ASSIGN_SUB:
    349     case Token::ASSIGN_MUL:
    350     case Token::ASSIGN_DIV:
    351     case Token::ASSIGN_MOD:
    352       if (node->type()->IsUnknown()) {
    353         if (node->target()->type()->IsLikelySmi() ||
    354             node->value()->type()->IsLikelySmi()) {
    355           node->type()->SetAsLikelySmi();
    356         }
    357       }
    358       break;
    359     default:
    360       UNREACHABLE();
    361       break;
    362   }
    363 
    364   // Since this is an assignment. We have to propagate this node's type to the
    365   // variable.
    366   VariableProxy* proxy = node->target()->AsVariableProxy();
    367   if (proxy != NULL) {
    368     Variable* var = proxy->AsVariable();
    369     if (var != NULL) {
    370       StaticType* var_type = var->type();
    371       if (var_type->IsUnknown()) {
    372         var_type->CopyFrom(node->type());
    373       } else if (var_type->IsLikelySmi()) {
    374         // We do not reset likely types to Unknown.
    375       }
    376     }
    377   }
    378 }
    379 
    380 
    381 void AstOptimizer::VisitThrow(Throw* node) {
    382   Visit(node->exception());
    383 }
    384 
    385 
    386 void AstOptimizer::VisitProperty(Property* node) {
    387   Visit(node->obj());
    388   Visit(node->key());
    389 }
    390 
    391 
    392 void AstOptimizer::VisitCall(Call* node) {
    393   Visit(node->expression());
    394   OptimizeArguments(node->arguments());
    395 }
    396 
    397 
    398 void AstOptimizer::VisitCallNew(CallNew* node) {
    399   Visit(node->expression());
    400   OptimizeArguments(node->arguments());
    401 }
    402 
    403 
    404 void AstOptimizer::VisitCallRuntime(CallRuntime* node) {
    405   ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_);
    406   if (Factory::InitializeVarGlobal_symbol()->Equals(*node->name()) &&
    407       node->arguments()->length() >= 2 &&
    408       node->arguments()->at(1)->AsFunctionLiteral() != NULL) {
    409       scoped_fni.Enter();
    410   }
    411   OptimizeArguments(node->arguments());
    412 }
    413 
    414 
    415 void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) {
    416   Visit(node->expression());
    417 }
    418 
    419 
    420 void AstOptimizer::VisitCountOperation(CountOperation* node) {
    421   // Count operations assume that they work on Smis.
    422   node->type()->SetAsLikelySmiIfUnknown();
    423   node->expression()->type()->SetAsLikelySmiIfUnknown();
    424   Visit(node->expression());
    425 }
    426 
    427 
    428 void AstOptimizer::VisitBinaryOperation(BinaryOperation* node) {
    429   // Depending on the operation we can propagate this node's type down the
    430   // AST nodes.
    431   switch (node->op()) {
    432     case Token::COMMA:
    433     case Token::OR:
    434     case Token::AND:
    435       break;
    436     case Token::BIT_OR:
    437     case Token::BIT_XOR:
    438     case Token::BIT_AND:
    439     case Token::SHL:
    440     case Token::SAR:
    441     case Token::SHR:
    442       node->type()->SetAsLikelySmiIfUnknown();
    443       node->left()->type()->SetAsLikelySmiIfUnknown();
    444       node->right()->type()->SetAsLikelySmiIfUnknown();
    445       break;
    446     case Token::ADD:
    447     case Token::SUB:
    448     case Token::MUL:
    449     case Token::DIV:
    450     case Token::MOD:
    451       if (node->type()->IsLikelySmi()) {
    452         node->left()->type()->SetAsLikelySmiIfUnknown();
    453         node->right()->type()->SetAsLikelySmiIfUnknown();
    454       }
    455       break;
    456     default:
    457       UNREACHABLE();
    458       break;
    459   }
    460 
    461   Visit(node->left());
    462   Visit(node->right());
    463 
    464   // After visiting the operand nodes we have to check if this node's type
    465   // can be updated. If it does, then we can push that information down
    466   // towards the leafs again if the new information is an upgrade over the
    467   // previous type of the operand nodes.
    468   if (node->type()->IsUnknown()) {
    469     if (node->left()->type()->IsLikelySmi() ||
    470         node->right()->type()->IsLikelySmi()) {
    471       node->type()->SetAsLikelySmi();
    472     }
    473     if (node->type()->IsLikelySmi()) {
    474       // The type of this node changed to LIKELY_SMI. Propagate this knowledge
    475       // down through the nodes.
    476       if (node->left()->type()->IsUnknown()) {
    477         node->left()->type()->SetAsLikelySmi();
    478         Visit(node->left());
    479       }
    480       if (node->right()->type()->IsUnknown()) {
    481         node->right()->type()->SetAsLikelySmi();
    482         Visit(node->right());
    483       }
    484     }
    485   }
    486 }
    487 
    488 
    489 void AstOptimizer::VisitCompareOperation(CompareOperation* node) {
    490   if (node->type()->IsKnown()) {
    491     // Propagate useful information down towards the leafs.
    492     node->left()->type()->SetAsLikelySmiIfUnknown();
    493     node->right()->type()->SetAsLikelySmiIfUnknown();
    494   }
    495 
    496   Visit(node->left());
    497   Visit(node->right());
    498 
    499   // After visiting the operand nodes we have to check if this node's type
    500   // can be updated. If it does, then we can push that information down
    501   // towards the leafs again if the new information is an upgrade over the
    502   // previous type of the operand nodes.
    503   if (node->type()->IsUnknown()) {
    504     if (node->left()->type()->IsLikelySmi() ||
    505         node->right()->type()->IsLikelySmi()) {
    506       node->type()->SetAsLikelySmi();
    507     }
    508     if (node->type()->IsLikelySmi()) {
    509       // The type of this node changed to LIKELY_SMI. Propagate this knowledge
    510       // down through the nodes.
    511       if (node->left()->type()->IsUnknown()) {
    512         node->left()->type()->SetAsLikelySmi();
    513         Visit(node->left());
    514       }
    515       if (node->right()->type()->IsUnknown()) {
    516         node->right()->type()->SetAsLikelySmi();
    517         Visit(node->right());
    518       }
    519     }
    520   }
    521 }
    522 
    523 
    524 void AstOptimizer::VisitThisFunction(ThisFunction* node) {
    525   USE(node);
    526 }
    527 
    528 
    529 class Processor: public AstVisitor {
    530  public:
    531   explicit Processor(VariableProxy* result)
    532       : result_(result),
    533         result_assigned_(false),
    534         is_set_(false),
    535         in_try_(false) {
    536   }
    537 
    538   void Process(ZoneList<Statement*>* statements);
    539   bool result_assigned() const  { return result_assigned_; }
    540 
    541  private:
    542   VariableProxy* result_;
    543 
    544   // We are not tracking result usage via the result_'s use
    545   // counts (we leave the accurate computation to the
    546   // usage analyzer). Instead we simple remember if
    547   // there was ever an assignment to result_.
    548   bool result_assigned_;
    549 
    550   // To avoid storing to .result all the time, we eliminate some of
    551   // the stores by keeping track of whether or not we're sure .result
    552   // will be overwritten anyway. This is a bit more tricky than what I
    553   // was hoping for
    554   bool is_set_;
    555   bool in_try_;
    556 
    557   Expression* SetResult(Expression* value) {
    558     result_assigned_ = true;
    559     return new Assignment(Token::ASSIGN, result_, value,
    560                           RelocInfo::kNoPosition);
    561   }
    562 
    563   // Node visitors.
    564 #define DEF_VISIT(type) \
    565   virtual void Visit##type(type* node);
    566   AST_NODE_LIST(DEF_VISIT)
    567 #undef DEF_VISIT
    568 
    569   void VisitIterationStatement(IterationStatement* stmt);
    570 };
    571 
    572 
    573 void Processor::Process(ZoneList<Statement*>* statements) {
    574   for (int i = statements->length() - 1; i >= 0; --i) {
    575     Visit(statements->at(i));
    576   }
    577 }
    578 
    579 
    580 void Processor::VisitBlock(Block* node) {
    581   // An initializer block is the rewritten form of a variable declaration
    582   // with initialization expressions. The initializer block contains the
    583   // list of assignments corresponding to the initialization expressions.
    584   // While unclear from the spec (ECMA-262, 3rd., 12.2), the value of
    585   // a variable declaration with initialization expression is 'undefined'
    586   // with some JS VMs: For instance, using smjs, print(eval('var x = 7'))
    587   // returns 'undefined'. To obtain the same behavior with v8, we need
    588   // to prevent rewriting in that case.
    589   if (!node->is_initializer_block()) Process(node->statements());
    590 }
    591 
    592 
    593 void Processor::VisitExpressionStatement(ExpressionStatement* node) {
    594   // Rewrite : <x>; -> .result = <x>;
    595   if (!is_set_) {
    596     node->set_expression(SetResult(node->expression()));
    597     if (!in_try_) is_set_ = true;
    598   }
    599 }
    600 
    601 
    602 void Processor::VisitIfStatement(IfStatement* node) {
    603   // Rewrite both then and else parts (reversed).
    604   bool save = is_set_;
    605   Visit(node->else_statement());
    606   bool set_after_then = is_set_;
    607   is_set_ = save;
    608   Visit(node->then_statement());
    609   is_set_ = is_set_ && set_after_then;
    610 }
    611 
    612 
    613 void Processor::VisitIterationStatement(IterationStatement* node) {
    614   // Rewrite the body.
    615   bool set_after_loop = is_set_;
    616   Visit(node->body());
    617   is_set_ = is_set_ && set_after_loop;
    618 }
    619 
    620 
    621 void Processor::VisitDoWhileStatement(DoWhileStatement* node) {
    622   VisitIterationStatement(node);
    623 }
    624 
    625 
    626 void Processor::VisitWhileStatement(WhileStatement* node) {
    627   VisitIterationStatement(node);
    628 }
    629 
    630 
    631 void Processor::VisitForStatement(ForStatement* node) {
    632   VisitIterationStatement(node);
    633 }
    634 
    635 
    636 void Processor::VisitForInStatement(ForInStatement* node) {
    637   VisitIterationStatement(node);
    638 }
    639 
    640 
    641 void Processor::VisitTryCatchStatement(TryCatchStatement* node) {
    642   // Rewrite both try and catch blocks (reversed order).
    643   bool set_after_catch = is_set_;
    644   Visit(node->catch_block());
    645   is_set_ = is_set_ && set_after_catch;
    646   bool save = in_try_;
    647   in_try_ = true;
    648   Visit(node->try_block());
    649   in_try_ = save;
    650 }
    651 
    652 
    653 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
    654   // Rewrite both try and finally block (reversed order).
    655   Visit(node->finally_block());
    656   bool save = in_try_;
    657   in_try_ = true;
    658   Visit(node->try_block());
    659   in_try_ = save;
    660 }
    661 
    662 
    663 void Processor::VisitSwitchStatement(SwitchStatement* node) {
    664   // Rewrite statements in all case clauses in reversed order.
    665   ZoneList<CaseClause*>* clauses = node->cases();
    666   bool set_after_switch = is_set_;
    667   for (int i = clauses->length() - 1; i >= 0; --i) {
    668     CaseClause* clause = clauses->at(i);
    669     Process(clause->statements());
    670   }
    671   is_set_ = is_set_ && set_after_switch;
    672 }
    673 
    674 
    675 void Processor::VisitContinueStatement(ContinueStatement* node) {
    676   is_set_ = false;
    677 }
    678 
    679 
    680 void Processor::VisitBreakStatement(BreakStatement* node) {
    681   is_set_ = false;
    682 }
    683 
    684 
    685 // Do nothing:
    686 void Processor::VisitDeclaration(Declaration* node) {}
    687 void Processor::VisitEmptyStatement(EmptyStatement* node) {}
    688 void Processor::VisitReturnStatement(ReturnStatement* node) {}
    689 void Processor::VisitWithEnterStatement(WithEnterStatement* node) {}
    690 void Processor::VisitWithExitStatement(WithExitStatement* node) {}
    691 void Processor::VisitDebuggerStatement(DebuggerStatement* node) {}
    692 
    693 
    694 // Expressions are never visited yet.
    695 void Processor::VisitFunctionLiteral(FunctionLiteral* node) {
    696   USE(node);
    697   UNREACHABLE();
    698 }
    699 
    700 
    701 void Processor::VisitFunctionBoilerplateLiteral(
    702     FunctionBoilerplateLiteral* node) {
    703   USE(node);
    704   UNREACHABLE();
    705 }
    706 
    707 
    708 void Processor::VisitConditional(Conditional* node) {
    709   USE(node);
    710   UNREACHABLE();
    711 }
    712 
    713 
    714 void Processor::VisitSlot(Slot* node) {
    715   USE(node);
    716   UNREACHABLE();
    717 }
    718 
    719 
    720 void Processor::VisitVariableProxy(VariableProxy* node) {
    721   USE(node);
    722   UNREACHABLE();
    723 }
    724 
    725 
    726 void Processor::VisitLiteral(Literal* node) {
    727   USE(node);
    728   UNREACHABLE();
    729 }
    730 
    731 
    732 void Processor::VisitRegExpLiteral(RegExpLiteral* node) {
    733   USE(node);
    734   UNREACHABLE();
    735 }
    736 
    737 
    738 void Processor::VisitArrayLiteral(ArrayLiteral* node) {
    739   USE(node);
    740   UNREACHABLE();
    741 }
    742 
    743 
    744 void Processor::VisitObjectLiteral(ObjectLiteral* node) {
    745   USE(node);
    746   UNREACHABLE();
    747 }
    748 
    749 
    750 void Processor::VisitCatchExtensionObject(CatchExtensionObject* node) {
    751   USE(node);
    752   UNREACHABLE();
    753 }
    754 
    755 
    756 void Processor::VisitAssignment(Assignment* node) {
    757   USE(node);
    758   UNREACHABLE();
    759 }
    760 
    761 
    762 void Processor::VisitThrow(Throw* node) {
    763   USE(node);
    764   UNREACHABLE();
    765 }
    766 
    767 
    768 void Processor::VisitProperty(Property* node) {
    769   USE(node);
    770   UNREACHABLE();
    771 }
    772 
    773 
    774 void Processor::VisitCall(Call* node) {
    775   USE(node);
    776   UNREACHABLE();
    777 }
    778 
    779 
    780 void Processor::VisitCallNew(CallNew* node) {
    781   USE(node);
    782   UNREACHABLE();
    783 }
    784 
    785 
    786 void Processor::VisitCallRuntime(CallRuntime* node) {
    787   USE(node);
    788   UNREACHABLE();
    789 }
    790 
    791 
    792 void Processor::VisitUnaryOperation(UnaryOperation* node) {
    793   USE(node);
    794   UNREACHABLE();
    795 }
    796 
    797 
    798 void Processor::VisitCountOperation(CountOperation* node) {
    799   USE(node);
    800   UNREACHABLE();
    801 }
    802 
    803 
    804 void Processor::VisitBinaryOperation(BinaryOperation* node) {
    805   USE(node);
    806   UNREACHABLE();
    807 }
    808 
    809 
    810 void Processor::VisitCompareOperation(CompareOperation* node) {
    811   USE(node);
    812   UNREACHABLE();
    813 }
    814 
    815 
    816 void Processor::VisitThisFunction(ThisFunction* node) {
    817   USE(node);
    818   UNREACHABLE();
    819 }
    820 
    821 
    822 bool Rewriter::Process(FunctionLiteral* function) {
    823   HistogramTimerScope timer(&Counters::rewriting);
    824   Scope* scope = function->scope();
    825   if (scope->is_function_scope()) return true;
    826 
    827   ZoneList<Statement*>* body = function->body();
    828   if (body->is_empty()) return true;
    829 
    830   VariableProxy* result = scope->NewTemporary(Factory::result_symbol());
    831   Processor processor(result);
    832   processor.Process(body);
    833   if (processor.HasStackOverflow()) return false;
    834 
    835   if (processor.result_assigned()) body->Add(new ReturnStatement(result));
    836   return true;
    837 }
    838 
    839 
    840 bool Rewriter::Optimize(FunctionLiteral* function) {
    841   ZoneList<Statement*>* body = function->body();
    842 
    843   if (FLAG_optimize_ast && !body->is_empty()) {
    844     HistogramTimerScope timer(&Counters::ast_optimization);
    845     AstOptimizer optimizer(function->name());
    846     optimizer.Optimize(body);
    847     if (optimizer.HasStackOverflow()) {
    848       return false;
    849     }
    850   }
    851   return true;
    852 }
    853 
    854 
    855 } }  // namespace v8::internal
    856