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