OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 5040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5051 function_return()->SetJoinId(expr->id()); | 5051 function_return()->SetJoinId(expr->id()); |
5052 set_current_block(function_return()); | 5052 set_current_block(function_return()); |
5053 } else { | 5053 } else { |
5054 set_current_block(NULL); | 5054 set_current_block(NULL); |
5055 } | 5055 } |
5056 delete target_state; | 5056 delete target_state; |
5057 return true; | 5057 return true; |
5058 } | 5058 } |
5059 | 5059 |
5060 | 5060 |
5061 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr, | 5061 bool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) { |
5062 HValue* receiver, | 5062 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
5063 Handle<Map> receiver_map, | 5063 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
5064 CheckType check_type) { | 5064 switch (id) { |
| 5065 case kMathRound: |
| 5066 case kMathFloor: |
| 5067 case kMathAbs: |
| 5068 case kMathSqrt: |
| 5069 case kMathLog: |
| 5070 case kMathSin: |
| 5071 case kMathCos: |
| 5072 if (expr->arguments()->length() == 1) { |
| 5073 HValue* argument = Pop(); |
| 5074 HValue* context = environment()->LookupContext(); |
| 5075 Drop(1); // Receiver. |
| 5076 HUnaryMathOperation* op = |
| 5077 new(zone()) HUnaryMathOperation(context, argument, id); |
| 5078 op->set_position(expr->position()); |
| 5079 if (drop_extra) Drop(1); // Optionally drop the function. |
| 5080 ast_context()->ReturnInstruction(op, expr->id()); |
| 5081 return true; |
| 5082 } |
| 5083 break; |
| 5084 default: |
| 5085 // Not supported for inlining yet. |
| 5086 break; |
| 5087 } |
| 5088 return false; |
| 5089 } |
| 5090 |
| 5091 |
| 5092 bool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr, |
| 5093 HValue* receiver, |
| 5094 Handle<Map> receiver_map, |
| 5095 CheckType check_type) { |
5065 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); | 5096 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); |
5066 // Try to inline calls like Math.* as operations in the calling function. | 5097 // Try to inline calls like Math.* as operations in the calling function. |
5067 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 5098 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
5068 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 5099 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
5069 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 5100 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
5070 switch (id) { | 5101 switch (id) { |
5071 case kStringCharCodeAt: | 5102 case kStringCharCodeAt: |
5072 case kStringCharAt: | 5103 case kStringCharAt: |
5073 if (argument_count == 2 && check_type == STRING_CHECK) { | 5104 if (argument_count == 2 && check_type == STRING_CHECK) { |
5074 HValue* index = Pop(); | 5105 HValue* index = Pop(); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5148 if (result == NULL) { | 5179 if (result == NULL) { |
5149 result = new(zone()) HPower(left, right); | 5180 result = new(zone()) HPower(left, right); |
5150 } | 5181 } |
5151 ast_context()->ReturnInstruction(result, expr->id()); | 5182 ast_context()->ReturnInstruction(result, expr->id()); |
5152 return true; | 5183 return true; |
5153 } | 5184 } |
5154 break; | 5185 break; |
5155 case kMathRandom: | 5186 case kMathRandom: |
5156 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { | 5187 if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { |
5157 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 5188 AddCheckConstantFunction(expr, receiver, receiver_map, true); |
5158 Drop(1); | 5189 Drop(1); // Receiver. |
5159 HValue* context = environment()->LookupContext(); | 5190 HValue* context = environment()->LookupContext(); |
5160 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 5191 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
5161 AddInstruction(global_object); | 5192 AddInstruction(global_object); |
5162 HRandom* result = new(zone()) HRandom(global_object); | 5193 HRandom* result = new(zone()) HRandom(global_object); |
5163 ast_context()->ReturnInstruction(result, expr->id()); | 5194 ast_context()->ReturnInstruction(result, expr->id()); |
5164 return true; | 5195 return true; |
5165 } | 5196 } |
5166 break; | 5197 break; |
5167 case kMathMax: | 5198 case kMathMax: |
5168 case kMathMin: | 5199 case kMathMin: |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5316 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 5347 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
5317 | 5348 |
5318 SmallMapList* types = expr->GetReceiverTypes(); | 5349 SmallMapList* types = expr->GetReceiverTypes(); |
5319 | 5350 |
5320 HValue* receiver = | 5351 HValue* receiver = |
5321 environment()->ExpressionStackAt(expr->arguments()->length()); | 5352 environment()->ExpressionStackAt(expr->arguments()->length()); |
5322 if (expr->IsMonomorphic()) { | 5353 if (expr->IsMonomorphic()) { |
5323 Handle<Map> receiver_map = (types == NULL || types->is_empty()) | 5354 Handle<Map> receiver_map = (types == NULL || types->is_empty()) |
5324 ? Handle<Map>::null() | 5355 ? Handle<Map>::null() |
5325 : types->first(); | 5356 : types->first(); |
5326 if (TryInlineBuiltinFunction(expr, | 5357 if (TryInlineBuiltinMethodCall(expr, |
5327 receiver, | 5358 receiver, |
5328 receiver_map, | 5359 receiver_map, |
5329 expr->check_type())) { | 5360 expr->check_type())) { |
| 5361 if (FLAG_trace_inlining) { |
| 5362 PrintF("Inlining builtin "); |
| 5363 expr->target()->ShortPrint(); |
| 5364 PrintF("\n"); |
| 5365 } |
5330 return; | 5366 return; |
5331 } | 5367 } |
5332 | 5368 |
5333 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || | 5369 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || |
5334 expr->check_type() != RECEIVER_MAP_CHECK) { | 5370 expr->check_type() != RECEIVER_MAP_CHECK) { |
5335 // When the target has a custom call IC generator, use the IC, | 5371 // When the target has a custom call IC generator, use the IC, |
5336 // because it is likely to generate better code. Also use the IC | 5372 // because it is likely to generate better code. Also use the IC |
5337 // when a primitive receiver check is required. | 5373 // when a primitive receiver check is required. |
5338 HValue* context = environment()->LookupContext(); | 5374 HValue* context = environment()->LookupContext(); |
5339 call = PreProcessCall( | 5375 call = PreProcessCall( |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5390 // Replace the global object with the global receiver. | 5426 // Replace the global object with the global receiver. |
5391 HGlobalReceiver* global_receiver = | 5427 HGlobalReceiver* global_receiver = |
5392 new(zone()) HGlobalReceiver(global_object); | 5428 new(zone()) HGlobalReceiver(global_object); |
5393 // Index of the receiver from the top of the expression stack. | 5429 // Index of the receiver from the top of the expression stack. |
5394 const int receiver_index = argument_count - 1; | 5430 const int receiver_index = argument_count - 1; |
5395 AddInstruction(global_receiver); | 5431 AddInstruction(global_receiver); |
5396 ASSERT(environment()->ExpressionStackAt(receiver_index)-> | 5432 ASSERT(environment()->ExpressionStackAt(receiver_index)-> |
5397 IsGlobalObject()); | 5433 IsGlobalObject()); |
5398 environment()->SetExpressionStackAt(receiver_index, global_receiver); | 5434 environment()->SetExpressionStackAt(receiver_index, global_receiver); |
5399 | 5435 |
| 5436 if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. |
| 5437 if (FLAG_trace_inlining) { |
| 5438 PrintF("Inlining builtin "); |
| 5439 expr->target()->ShortPrint(); |
| 5440 PrintF("\n"); |
| 5441 } |
| 5442 return; |
| 5443 } |
5400 if (TryInline(expr)) return; | 5444 if (TryInline(expr)) return; |
5401 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 5445 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
5402 argument_count)); | 5446 argument_count)); |
5403 } else { | 5447 } else { |
5404 HValue* context = environment()->LookupContext(); | 5448 HValue* context = environment()->LookupContext(); |
5405 HGlobalObject* receiver = new(zone()) HGlobalObject(context); | 5449 HGlobalObject* receiver = new(zone()) HGlobalObject(context); |
5406 AddInstruction(receiver); | 5450 AddInstruction(receiver); |
5407 PushAndAdd(new(zone()) HPushArgument(receiver)); | 5451 PushAndAdd(new(zone()) HPushArgument(receiver)); |
5408 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 5452 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
5409 | 5453 |
5410 call = new(zone()) HCallGlobal(context, var->name(), argument_count); | 5454 call = new(zone()) HCallGlobal(context, var->name(), argument_count); |
5411 Drop(argument_count); | 5455 Drop(argument_count); |
5412 } | 5456 } |
5413 | 5457 |
5414 } else if (expr->IsMonomorphic()) { | 5458 } else if (expr->IsMonomorphic()) { |
5415 // The function is on the stack in the unoptimized code during | 5459 // The function is on the stack in the unoptimized code during |
5416 // evaluation of the arguments. | 5460 // evaluation of the arguments. |
5417 CHECK_ALIVE(VisitForValue(expr->expression())); | 5461 CHECK_ALIVE(VisitForValue(expr->expression())); |
5418 HValue* function = Top(); | 5462 HValue* function = Top(); |
5419 HValue* context = environment()->LookupContext(); | 5463 HValue* context = environment()->LookupContext(); |
5420 HGlobalObject* global = new(zone()) HGlobalObject(context); | 5464 HGlobalObject* global = new(zone()) HGlobalObject(context); |
5421 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); | 5465 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); |
5422 AddInstruction(global); | 5466 AddInstruction(global); |
5423 PushAndAdd(receiver); | 5467 PushAndAdd(receiver); |
5424 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 5468 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
5425 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); | 5469 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); |
| 5470 |
| 5471 if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. |
| 5472 if (FLAG_trace_inlining) { |
| 5473 PrintF("Inlining builtin "); |
| 5474 expr->target()->ShortPrint(); |
| 5475 PrintF("\n"); |
| 5476 } |
| 5477 return; |
| 5478 } |
| 5479 |
5426 if (TryInline(expr, true)) { // Drop function from environment. | 5480 if (TryInline(expr, true)) { // Drop function from environment. |
5427 return; | 5481 return; |
5428 } else { | 5482 } else { |
5429 call = PreProcessCall(new(zone()) HInvokeFunction(context, | 5483 call = PreProcessCall(new(zone()) HInvokeFunction(context, |
5430 function, | 5484 function, |
5431 argument_count)); | 5485 argument_count)); |
5432 Drop(1); // The function. | 5486 Drop(1); // The function. |
5433 } | 5487 } |
5434 | 5488 |
5435 } else { | 5489 } else { |
(...skipping 2025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7461 } | 7515 } |
7462 } | 7516 } |
7463 | 7517 |
7464 #ifdef DEBUG | 7518 #ifdef DEBUG |
7465 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 7519 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
7466 if (allocator_ != NULL) allocator_->Verify(); | 7520 if (allocator_ != NULL) allocator_->Verify(); |
7467 #endif | 7521 #endif |
7468 } | 7522 } |
7469 | 7523 |
7470 } } // namespace v8::internal | 7524 } } // namespace v8::internal |
OLD | NEW |