| OLD | NEW | 
|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without | 
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are | 
| 4 // met: | 4 // met: | 
| 5 // | 5 // | 
| 6 //     * Redistributions of source code must retain the above copyright | 6 //     * Redistributions of source code must retain the above copyright | 
| 7 //       notice, this list of conditions and the following disclaimer. | 7 //       notice, this list of conditions and the following disclaimer. | 
| 8 //     * Redistributions in binary form must reproduce the above | 8 //     * Redistributions in binary form must reproduce the above | 
| 9 //       copyright notice, this list of conditions and the following | 9 //       copyright notice, this list of conditions and the following | 
| 10 //       disclaimer in the documentation and/or other materials provided | 10 //       disclaimer in the documentation and/or other materials provided | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 27 | 27 | 
| 28 #include "v8.h" | 28 #include "v8.h" | 
| 29 | 29 | 
| 30 #include "ast.h" | 30 #include "ast.h" | 
|  | 31 #include "func-name-inferrer.h" | 
| 31 #include "scopes.h" | 32 #include "scopes.h" | 
| 32 #include "rewriter.h" | 33 #include "rewriter.h" | 
| 33 | 34 | 
| 34 namespace v8 { namespace internal { | 35 namespace v8 { namespace internal { | 
| 35 | 36 | 
| 36 | 37 | 
| 37 class AstOptimizer: public AstVisitor { | 38 class AstOptimizer: public AstVisitor { | 
| 38  public: | 39  public: | 
| 39   explicit AstOptimizer() { | 40   explicit AstOptimizer() {} | 
|  | 41   explicit AstOptimizer(Handle<String> enclosing_name) { | 
|  | 42     func_name_inferrer_.PushEnclosingName(enclosing_name); | 
| 40   } | 43   } | 
| 41 | 44 | 
| 42   void Optimize(ZoneList<Statement*>* statements); | 45   void Optimize(ZoneList<Statement*>* statements); | 
| 43 | 46 | 
| 44  private: | 47  private: | 
| 45   // Used for loop condition analysis.  Cleared before visiting a loop | 48   // Used for loop condition analysis.  Cleared before visiting a loop | 
| 46   // condition, set when a function literal is visited. | 49   // condition, set when a function literal is visited. | 
| 47   bool has_function_literal_; | 50   bool has_function_literal_; | 
|  | 51   // Helper object for function name inferring. | 
|  | 52   FuncNameInferrer func_name_inferrer_; | 
| 48 | 53 | 
| 49   // Helpers | 54   // Helpers | 
| 50   void OptimizeArguments(ZoneList<Expression*>* arguments); | 55   void OptimizeArguments(ZoneList<Expression*>* arguments); | 
| 51 | 56 | 
| 52   // Node visitors. | 57   // Node visitors. | 
| 53 #define DEF_VISIT(type) \ | 58 #define DEF_VISIT(type) \ | 
| 54   virtual void Visit##type(type* node); | 59   virtual void Visit##type(type* node); | 
| 55   NODE_LIST(DEF_VISIT) | 60   NODE_LIST(DEF_VISIT) | 
| 56 #undef DEF_VISIT | 61 #undef DEF_VISIT | 
| 57 | 62 | 
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 178   USE(node); | 183   USE(node); | 
| 179 } | 184 } | 
| 180 | 185 | 
| 181 | 186 | 
| 182 void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) { | 187 void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) { | 
| 183   USE(node); | 188   USE(node); | 
| 184 } | 189 } | 
| 185 | 190 | 
| 186 | 191 | 
| 187 void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) { | 192 void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) { | 
| 188   USE(node); |  | 
| 189   has_function_literal_ = true; | 193   has_function_literal_ = true; | 
|  | 194 | 
|  | 195   if (node->name()->length() == 0) { | 
|  | 196     // Anonymous function. | 
|  | 197     func_name_inferrer_.SetFuncToInfer(node); | 
|  | 198   } | 
| 190 } | 199 } | 
| 191 | 200 | 
| 192 | 201 | 
| 193 void AstOptimizer::VisitFunctionBoilerplateLiteral( | 202 void AstOptimizer::VisitFunctionBoilerplateLiteral( | 
| 194     FunctionBoilerplateLiteral* node) { | 203     FunctionBoilerplateLiteral* node) { | 
| 195   USE(node); | 204   USE(node); | 
| 196 } | 205 } | 
| 197 | 206 | 
| 198 | 207 | 
| 199 void AstOptimizer::VisitConditional(Conditional* node) { | 208 void AstOptimizer::VisitConditional(Conditional* node) { | 
| 200   Visit(node->condition()); | 209   Visit(node->condition()); | 
| 201   Visit(node->then_expression()); | 210   Visit(node->then_expression()); | 
| 202   Visit(node->else_expression()); | 211   Visit(node->else_expression()); | 
| 203 } | 212 } | 
| 204 | 213 | 
| 205 | 214 | 
| 206 void AstOptimizer::VisitSlot(Slot* node) { | 215 void AstOptimizer::VisitSlot(Slot* node) { | 
| 207   USE(node); | 216   USE(node); | 
| 208 } | 217 } | 
| 209 | 218 | 
| 210 | 219 | 
| 211 void AstOptimizer::VisitVariableProxy(VariableProxy* node) { | 220 void AstOptimizer::VisitVariableProxy(VariableProxy* node) { | 
| 212   Variable* var = node->AsVariable(); | 221   Variable* var = node->AsVariable(); | 
| 213   if (var != NULL) { | 222   if (var != NULL) { | 
| 214     if (var->type()->IsKnown()) { | 223     if (var->type()->IsKnown()) { | 
| 215       node->type()->CopyFrom(var->type()); | 224       node->type()->CopyFrom(var->type()); | 
| 216     } else if (node->type()->IsLikelySmi()) { | 225     } else if (node->type()->IsLikelySmi()) { | 
| 217       var->type()->SetAsLikelySmi(); | 226       var->type()->SetAsLikelySmi(); | 
| 218     } | 227     } | 
|  | 228 | 
|  | 229     if (!var->is_this() && | 
|  | 230         !Heap::result_symbol()->Equals(*var->name())) { | 
|  | 231       func_name_inferrer_.PushName(var->name()); | 
|  | 232     } | 
| 219   } | 233   } | 
| 220 } | 234 } | 
| 221 | 235 | 
| 222 | 236 | 
| 223 void AstOptimizer::VisitLiteral(Literal* node) { | 237 void AstOptimizer::VisitLiteral(Literal* node) { | 
| 224   Handle<Object> literal = node->handle(); | 238   Handle<Object> literal = node->handle(); | 
| 225   if (literal->IsSmi()) { | 239   if (literal->IsSmi()) { | 
| 226     node->type()->SetAsLikelySmi(); | 240     node->type()->SetAsLikelySmi(); | 
|  | 241   } else if (literal->IsString()) { | 
|  | 242     Handle<String> lit_str(Handle<String>::cast(literal)); | 
|  | 243     if (!Heap::prototype_symbol()->Equals(*lit_str)) { | 
|  | 244       func_name_inferrer_.PushName(lit_str); | 
|  | 245     } | 
| 227   } | 246   } | 
| 228 } | 247 } | 
| 229 | 248 | 
| 230 | 249 | 
| 231 void AstOptimizer::VisitRegExpLiteral(RegExpLiteral* node) { | 250 void AstOptimizer::VisitRegExpLiteral(RegExpLiteral* node) { | 
| 232   USE(node); | 251   USE(node); | 
| 233 } | 252 } | 
| 234 | 253 | 
| 235 | 254 | 
| 236 void AstOptimizer::VisitArrayLiteral(ArrayLiteral* node) { | 255 void AstOptimizer::VisitArrayLiteral(ArrayLiteral* node) { | 
| 237   for (int i = 0; i < node->values()->length(); i++) { | 256   for (int i = 0; i < node->values()->length(); i++) { | 
| 238     Visit(node->values()->at(i)); | 257     Visit(node->values()->at(i)); | 
| 239   } | 258   } | 
| 240 } | 259 } | 
| 241 | 260 | 
| 242 |  | 
| 243 void AstOptimizer::VisitObjectLiteral(ObjectLiteral* node) { | 261 void AstOptimizer::VisitObjectLiteral(ObjectLiteral* node) { | 
| 244   for (int i = 0; i < node->properties()->length(); i++) { | 262   for (int i = 0; i < node->properties()->length(); i++) { | 
|  | 263     ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_); | 
|  | 264     scoped_fni.Enter(); | 
| 245     Visit(node->properties()->at(i)->key()); | 265     Visit(node->properties()->at(i)->key()); | 
| 246     Visit(node->properties()->at(i)->value()); | 266     Visit(node->properties()->at(i)->value()); | 
| 247   } | 267   } | 
| 248 } | 268 } | 
| 249 | 269 | 
| 250 | 270 | 
| 251 void AstOptimizer::VisitCatchExtensionObject(CatchExtensionObject* node) { | 271 void AstOptimizer::VisitCatchExtensionObject(CatchExtensionObject* node) { | 
| 252   Visit(node->key()); | 272   Visit(node->key()); | 
| 253   Visit(node->value()); | 273   Visit(node->value()); | 
| 254 } | 274 } | 
| 255 | 275 | 
| 256 | 276 | 
| 257 void AstOptimizer::VisitAssignment(Assignment* node) { | 277 void AstOptimizer::VisitAssignment(Assignment* node) { | 
|  | 278   ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_); | 
| 258   switch (node->op()) { | 279   switch (node->op()) { | 
| 259     case Token::INIT_VAR: | 280     case Token::INIT_VAR: | 
| 260     case Token::INIT_CONST: | 281     case Token::INIT_CONST: | 
| 261     case Token::ASSIGN: | 282     case Token::ASSIGN: | 
| 262       // No type can be infered from the general assignment. | 283       // No type can be infered from the general assignment. | 
|  | 284 | 
|  | 285       if (node->value()->AsFunctionLiteral() != NULL || | 
|  | 286           node->value()->AsObjectLiteral() != NULL) { | 
|  | 287         scoped_fni.Enter(); | 
|  | 288       } | 
| 263       break; | 289       break; | 
| 264     case Token::ASSIGN_BIT_OR: | 290     case Token::ASSIGN_BIT_OR: | 
| 265     case Token::ASSIGN_BIT_XOR: | 291     case Token::ASSIGN_BIT_XOR: | 
| 266     case Token::ASSIGN_BIT_AND: | 292     case Token::ASSIGN_BIT_AND: | 
| 267     case Token::ASSIGN_SHL: | 293     case Token::ASSIGN_SHL: | 
| 268     case Token::ASSIGN_SAR: | 294     case Token::ASSIGN_SAR: | 
| 269     case Token::ASSIGN_SHR: | 295     case Token::ASSIGN_SHR: | 
| 270       node->type()->SetAsLikelySmiIfUnknown(); | 296       node->type()->SetAsLikelySmiIfUnknown(); | 
| 271       node->target()->type()->SetAsLikelySmiIfUnknown(); | 297       node->target()->type()->SetAsLikelySmiIfUnknown(); | 
| 272       node->value()->type()->SetAsLikelySmiIfUnknown(); | 298       node->value()->type()->SetAsLikelySmiIfUnknown(); | 
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 361 } | 387 } | 
| 362 | 388 | 
| 363 | 389 | 
| 364 void AstOptimizer::VisitCallNew(CallNew* node) { | 390 void AstOptimizer::VisitCallNew(CallNew* node) { | 
| 365   Visit(node->expression()); | 391   Visit(node->expression()); | 
| 366   OptimizeArguments(node->arguments()); | 392   OptimizeArguments(node->arguments()); | 
| 367 } | 393 } | 
| 368 | 394 | 
| 369 | 395 | 
| 370 void AstOptimizer::VisitCallRuntime(CallRuntime* node) { | 396 void AstOptimizer::VisitCallRuntime(CallRuntime* node) { | 
|  | 397   ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_); | 
|  | 398   if (Factory::InitializeVarGlobal_symbol()->Equals(*node->name()) && | 
|  | 399       node->arguments()->length() >= 2 && | 
|  | 400       node->arguments()->at(1)->AsFunctionLiteral() != NULL) { | 
|  | 401       scoped_fni.Enter(); | 
|  | 402   } | 
| 371   OptimizeArguments(node->arguments()); | 403   OptimizeArguments(node->arguments()); | 
| 372 } | 404 } | 
| 373 | 405 | 
| 374 | 406 | 
| 375 void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) { | 407 void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) { | 
| 376   Visit(node->expression()); | 408   Visit(node->expression()); | 
| 377 } | 409 } | 
| 378 | 410 | 
| 379 | 411 | 
| 380 void AstOptimizer::VisitCountOperation(CountOperation* node) { | 412 void AstOptimizer::VisitCountOperation(CountOperation* node) { | 
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 787 | 819 | 
| 788   if (processor.result_assigned()) body->Add(new ReturnStatement(result)); | 820   if (processor.result_assigned()) body->Add(new ReturnStatement(result)); | 
| 789   return true; | 821   return true; | 
| 790 } | 822 } | 
| 791 | 823 | 
| 792 | 824 | 
| 793 bool Rewriter::Optimize(FunctionLiteral* function) { | 825 bool Rewriter::Optimize(FunctionLiteral* function) { | 
| 794   ZoneList<Statement*>* body = function->body(); | 826   ZoneList<Statement*>* body = function->body(); | 
| 795 | 827 | 
| 796   if (FLAG_optimize_ast && !body->is_empty()) { | 828   if (FLAG_optimize_ast && !body->is_empty()) { | 
| 797     Scope* scope = function->scope(); | 829     AstOptimizer optimizer(function->name()); | 
| 798     if (!scope->is_global_scope()) { | 830     optimizer.Optimize(body); | 
| 799       AstOptimizer optimizer; | 831     if (optimizer.HasStackOverflow()) { | 
| 800       optimizer.Optimize(body); | 832       return false; | 
| 801       if (optimizer.HasStackOverflow()) { |  | 
| 802         return false; |  | 
| 803       } |  | 
| 804     } | 833     } | 
| 805   } | 834   } | 
| 806   return true; | 835   return true; | 
| 807 } | 836 } | 
| 808 | 837 | 
| 809 | 838 | 
| 810 } }  // namespace v8::internal | 839 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|