| 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" | |
| 32 #include "scopes.h" | 31 #include "scopes.h" |
| 33 #include "rewriter.h" | 32 #include "rewriter.h" |
| 34 | 33 |
| 35 namespace v8 { | 34 namespace v8 { |
| 36 namespace internal { | 35 namespace internal { |
| 37 | 36 |
| 38 | 37 |
| 39 class AstOptimizer: public AstVisitor { | 38 class AstOptimizer: public AstVisitor { |
| 40 public: | 39 public: |
| 41 explicit AstOptimizer() : has_function_literal_(false) {} | 40 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 | 41 |
| 47 void Optimize(ZoneList<Statement*>* statements); | 42 void Optimize(ZoneList<Statement*>* statements); |
| 48 | 43 |
| 49 private: | 44 private: |
| 50 // Used for loop condition analysis. Cleared before visiting a loop | 45 // Used for loop condition analysis. Cleared before visiting a loop |
| 51 // condition, set when a function literal is visited. | 46 // condition, set when a function literal is visited. |
| 52 bool has_function_literal_; | 47 bool has_function_literal_; |
| 53 // Helper object for function name inferring. | |
| 54 FuncNameInferrer func_name_inferrer_; | |
| 55 | 48 |
| 56 // Helpers | 49 // Helpers |
| 57 void OptimizeArguments(ZoneList<Expression*>* arguments); | 50 void OptimizeArguments(ZoneList<Expression*>* arguments); |
| 58 | 51 |
| 59 // Node visitors. | 52 // Node visitors. |
| 60 #define DEF_VISIT(type) \ | 53 #define DEF_VISIT(type) \ |
| 61 virtual void Visit##type(type* node); | 54 virtual void Visit##type(type* node); |
| 62 AST_NODE_LIST(DEF_VISIT) | 55 AST_NODE_LIST(DEF_VISIT) |
| 63 #undef DEF_VISIT | 56 #undef DEF_VISIT |
| 64 | 57 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 } | 197 } |
| 205 | 198 |
| 206 | 199 |
| 207 void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) { | 200 void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) { |
| 208 USE(node); | 201 USE(node); |
| 209 } | 202 } |
| 210 | 203 |
| 211 | 204 |
| 212 void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) { | 205 void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) { |
| 213 has_function_literal_ = true; | 206 has_function_literal_ = true; |
| 214 | |
| 215 if (node->name()->length() == 0) { | |
| 216 // Anonymous function. | |
| 217 func_name_inferrer_.AddFunction(node); | |
| 218 } | |
| 219 } | 207 } |
| 220 | 208 |
| 221 | 209 |
| 222 void AstOptimizer::VisitSharedFunctionInfoLiteral( | 210 void AstOptimizer::VisitSharedFunctionInfoLiteral( |
| 223 SharedFunctionInfoLiteral* node) { | 211 SharedFunctionInfoLiteral* node) { |
| 224 USE(node); | 212 USE(node); |
| 225 } | 213 } |
| 226 | 214 |
| 227 | 215 |
| 228 void AstOptimizer::VisitConditional(Conditional* node) { | 216 void AstOptimizer::VisitConditional(Conditional* node) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 240 | 228 |
| 241 void AstOptimizer::VisitVariableProxy(VariableProxy* node) { | 229 void AstOptimizer::VisitVariableProxy(VariableProxy* node) { |
| 242 Variable* var = node->AsVariable(); | 230 Variable* var = node->AsVariable(); |
| 243 if (var != NULL) { | 231 if (var != NULL) { |
| 244 if (var->type()->IsKnown()) { | 232 if (var->type()->IsKnown()) { |
| 245 node->type()->CopyFrom(var->type()); | 233 node->type()->CopyFrom(var->type()); |
| 246 } else if (node->type()->IsLikelySmi()) { | 234 } else if (node->type()->IsLikelySmi()) { |
| 247 var->type()->SetAsLikelySmi(); | 235 var->type()->SetAsLikelySmi(); |
| 248 } | 236 } |
| 249 | 237 |
| 250 if (!var->is_this() && | |
| 251 !Heap::result_symbol()->Equals(*var->name())) { | |
| 252 func_name_inferrer_.PushName(var->name()); | |
| 253 } | |
| 254 | |
| 255 if (FLAG_safe_int32_compiler) { | 238 if (FLAG_safe_int32_compiler) { |
| 256 if (var->IsStackAllocated() && | 239 if (var->IsStackAllocated() && |
| 257 !var->is_arguments() && | 240 !var->is_arguments() && |
| 258 var->mode() != Variable::CONST) { | 241 var->mode() != Variable::CONST) { |
| 259 node->set_side_effect_free(true); | 242 node->set_side_effect_free(true); |
| 260 } | 243 } |
| 261 } | 244 } |
| 262 } | 245 } |
| 263 } | 246 } |
| 264 | 247 |
| 265 | 248 |
| 266 void AstOptimizer::VisitLiteral(Literal* node) { | 249 void AstOptimizer::VisitLiteral(Literal* node) { |
| 267 Handle<Object> literal = node->handle(); | 250 Handle<Object> literal = node->handle(); |
| 268 if (literal->IsSmi()) { | 251 if (literal->IsSmi()) { |
| 269 node->type()->SetAsLikelySmi(); | 252 node->type()->SetAsLikelySmi(); |
| 270 node->set_side_effect_free(true); | 253 node->set_side_effect_free(true); |
| 271 } else if (literal->IsString()) { | |
| 272 Handle<String> lit_str(Handle<String>::cast(literal)); | |
| 273 if (!Heap::prototype_symbol()->Equals(*lit_str)) { | |
| 274 func_name_inferrer_.PushName(lit_str); | |
| 275 } | |
| 276 } else if (literal->IsHeapNumber()) { | 254 } else if (literal->IsHeapNumber()) { |
| 277 if (node->to_int32()) { | 255 if (node->to_int32()) { |
| 278 // Any HeapNumber has an int32 value if it is the input to a bit op. | 256 // Any HeapNumber has an int32 value if it is the input to a bit op. |
| 279 node->set_side_effect_free(true); | 257 node->set_side_effect_free(true); |
| 280 } else { | 258 } else { |
| 281 double double_value = HeapNumber::cast(*literal)->value(); | 259 double double_value = HeapNumber::cast(*literal)->value(); |
| 282 int32_t int32_value = DoubleToInt32(double_value); | 260 int32_t int32_value = DoubleToInt32(double_value); |
| 283 node->set_side_effect_free(double_value == int32_value); | 261 node->set_side_effect_free(double_value == int32_value); |
| 284 } | 262 } |
| 285 } | 263 } |
| 286 } | 264 } |
| 287 | 265 |
| 288 | 266 |
| 289 void AstOptimizer::VisitRegExpLiteral(RegExpLiteral* node) { | 267 void AstOptimizer::VisitRegExpLiteral(RegExpLiteral* node) { |
| 290 USE(node); | 268 USE(node); |
| 291 } | 269 } |
| 292 | 270 |
| 293 | 271 |
| 294 void AstOptimizer::VisitArrayLiteral(ArrayLiteral* node) { | 272 void AstOptimizer::VisitArrayLiteral(ArrayLiteral* node) { |
| 295 for (int i = 0; i < node->values()->length(); i++) { | 273 for (int i = 0; i < node->values()->length(); i++) { |
| 296 Visit(node->values()->at(i)); | 274 Visit(node->values()->at(i)); |
| 297 } | 275 } |
| 298 } | 276 } |
| 299 | 277 |
| 300 void AstOptimizer::VisitObjectLiteral(ObjectLiteral* node) { | 278 void AstOptimizer::VisitObjectLiteral(ObjectLiteral* node) { |
| 301 for (int i = 0; i < node->properties()->length(); i++) { | 279 for (int i = 0; i < node->properties()->length(); i++) { |
| 302 ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_); | |
| 303 scoped_fni.Enter(); | |
| 304 Visit(node->properties()->at(i)->key()); | 280 Visit(node->properties()->at(i)->key()); |
| 305 Visit(node->properties()->at(i)->value()); | 281 Visit(node->properties()->at(i)->value()); |
| 306 } | 282 } |
| 307 } | 283 } |
| 308 | 284 |
| 309 | 285 |
| 310 void AstOptimizer::VisitCatchExtensionObject(CatchExtensionObject* node) { | 286 void AstOptimizer::VisitCatchExtensionObject(CatchExtensionObject* node) { |
| 311 Visit(node->key()); | 287 Visit(node->key()); |
| 312 Visit(node->value()); | 288 Visit(node->value()); |
| 313 } | 289 } |
| 314 | 290 |
| 315 | 291 |
| 316 void AstOptimizer::VisitAssignment(Assignment* node) { | 292 void AstOptimizer::VisitAssignment(Assignment* node) { |
| 317 ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_); | |
| 318 switch (node->op()) { | 293 switch (node->op()) { |
| 319 case Token::INIT_VAR: | 294 case Token::INIT_VAR: |
| 320 case Token::INIT_CONST: | 295 case Token::INIT_CONST: |
| 321 case Token::ASSIGN: | 296 case Token::ASSIGN: |
| 322 // No type can be infered from the general assignment. | 297 // No type can be infered from the general assignment. |
| 323 | |
| 324 // Don't infer if it is "a = function(){...}();"-like expression. | |
| 325 if (node->value()->AsCall() == NULL) { | |
| 326 scoped_fni.Enter(); | |
| 327 } | |
| 328 break; | 298 break; |
| 329 case Token::ASSIGN_BIT_OR: | 299 case Token::ASSIGN_BIT_OR: |
| 330 case Token::ASSIGN_BIT_XOR: | 300 case Token::ASSIGN_BIT_XOR: |
| 331 case Token::ASSIGN_BIT_AND: | 301 case Token::ASSIGN_BIT_AND: |
| 332 case Token::ASSIGN_SHL: | 302 case Token::ASSIGN_SHL: |
| 333 case Token::ASSIGN_SAR: | 303 case Token::ASSIGN_SAR: |
| 334 case Token::ASSIGN_SHR: | 304 case Token::ASSIGN_SHR: |
| 335 node->type()->SetAsLikelySmiIfUnknown(); | 305 node->type()->SetAsLikelySmiIfUnknown(); |
| 336 node->target()->type()->SetAsLikelySmiIfUnknown(); | 306 node->target()->type()->SetAsLikelySmiIfUnknown(); |
| 337 node->value()->type()->SetAsLikelySmiIfUnknown(); | 307 node->value()->type()->SetAsLikelySmiIfUnknown(); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 } | 393 } |
| 424 | 394 |
| 425 | 395 |
| 426 void AstOptimizer::VisitCallNew(CallNew* node) { | 396 void AstOptimizer::VisitCallNew(CallNew* node) { |
| 427 Visit(node->expression()); | 397 Visit(node->expression()); |
| 428 OptimizeArguments(node->arguments()); | 398 OptimizeArguments(node->arguments()); |
| 429 } | 399 } |
| 430 | 400 |
| 431 | 401 |
| 432 void AstOptimizer::VisitCallRuntime(CallRuntime* node) { | 402 void AstOptimizer::VisitCallRuntime(CallRuntime* node) { |
| 433 ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_); | |
| 434 if (Factory::InitializeVarGlobal_symbol()->Equals(*node->name()) && | |
| 435 node->arguments()->length() >= 2 && | |
| 436 node->arguments()->at(1)->AsFunctionLiteral() != NULL) { | |
| 437 scoped_fni.Enter(); | |
| 438 } | |
| 439 OptimizeArguments(node->arguments()); | 403 OptimizeArguments(node->arguments()); |
| 440 } | 404 } |
| 441 | 405 |
| 442 | 406 |
| 443 void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) { | 407 void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) { |
| 444 if (node->op() == Token::ADD || node->op() == Token::SUB) { | 408 if (node->op() == Token::ADD || node->op() == Token::SUB) { |
| 445 node->expression()->set_no_negative_zero(node->no_negative_zero()); | 409 node->expression()->set_no_negative_zero(node->no_negative_zero()); |
| 446 } else { | 410 } else { |
| 447 node->expression()->set_no_negative_zero(true); | 411 node->expression()->set_no_negative_zero(true); |
| 448 } | 412 } |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 if (processor.result_assigned()) body->Add(new ReturnStatement(result)); | 982 if (processor.result_assigned()) body->Add(new ReturnStatement(result)); |
| 1019 return true; | 983 return true; |
| 1020 } | 984 } |
| 1021 | 985 |
| 1022 | 986 |
| 1023 bool Rewriter::Optimize(FunctionLiteral* function) { | 987 bool Rewriter::Optimize(FunctionLiteral* function) { |
| 1024 ZoneList<Statement*>* body = function->body(); | 988 ZoneList<Statement*>* body = function->body(); |
| 1025 | 989 |
| 1026 if (FLAG_optimize_ast && !body->is_empty()) { | 990 if (FLAG_optimize_ast && !body->is_empty()) { |
| 1027 HistogramTimerScope timer(&Counters::ast_optimization); | 991 HistogramTimerScope timer(&Counters::ast_optimization); |
| 1028 AstOptimizer optimizer(function->name()); | 992 AstOptimizer optimizer; |
| 1029 optimizer.Optimize(body); | 993 optimizer.Optimize(body); |
| 1030 if (optimizer.HasStackOverflow()) { | 994 if (optimizer.HasStackOverflow()) { |
| 1031 return false; | 995 return false; |
| 1032 } | 996 } |
| 1033 } | 997 } |
| 1034 return true; | 998 return true; |
| 1035 } | 999 } |
| 1036 | 1000 |
| 1037 | 1001 |
| 1038 } } // namespace v8::internal | 1002 } } // namespace v8::internal |
| OLD | NEW |