OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 3967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3978 PrintF("Did not inline %s called from %s (%s).\n", | 3978 PrintF("Did not inline %s called from %s (%s).\n", |
3979 *callee, *caller, reason); | 3979 *callee, *caller, reason); |
3980 } | 3980 } |
3981 } | 3981 } |
3982 } | 3982 } |
3983 | 3983 |
3984 | 3984 |
3985 bool HGraphBuilder::TryInline(Call* expr) { | 3985 bool HGraphBuilder::TryInline(Call* expr) { |
3986 if (!FLAG_use_inlining) return false; | 3986 if (!FLAG_use_inlining) return false; |
3987 | 3987 |
| 3988 // The function call we are inlining has an explicit receiver if it |
| 3989 // is a property call. |
| 3990 ReceiverType receiver_type = (expr->expression()->AsProperty() == NULL) |
| 3991 ? IMPLICIT_RECEIVER |
| 3992 : EXPLICIT_RECEIVER; |
| 3993 |
3988 // Precondition: call is monomorphic and we have found a target with the | 3994 // Precondition: call is monomorphic and we have found a target with the |
3989 // appropriate arity. | 3995 // appropriate arity. |
3990 Handle<JSFunction> target = expr->target(); | 3996 Handle<JSFunction> target = expr->target(); |
3991 | 3997 |
3992 // Do a quick check on source code length to avoid parsing large | 3998 // Do a quick check on source code length to avoid parsing large |
3993 // inlining candidates. | 3999 // inlining candidates. |
3994 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) { | 4000 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) { |
3995 TraceInline(target, "target text too big"); | 4001 TraceInline(target, "target text too big"); |
3996 return false; | 4002 return false; |
3997 } | 4003 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4112 TypeFeedbackOracle target_oracle( | 4118 TypeFeedbackOracle target_oracle( |
4113 Handle<Code>(target_shared->code()), | 4119 Handle<Code>(target_shared->code()), |
4114 Handle<Context>(target->context()->global_context())); | 4120 Handle<Context>(target->context()->global_context())); |
4115 FunctionState target_state(this, &target_info, &target_oracle); | 4121 FunctionState target_state(this, &target_info, &target_oracle); |
4116 | 4122 |
4117 HConstant* undefined = graph()->GetConstantUndefined(); | 4123 HConstant* undefined = graph()->GetConstantUndefined(); |
4118 HEnvironment* inner_env = | 4124 HEnvironment* inner_env = |
4119 environment()->CopyForInlining(target, | 4125 environment()->CopyForInlining(target, |
4120 function, | 4126 function, |
4121 HEnvironment::HYDROGEN, | 4127 HEnvironment::HYDROGEN, |
4122 undefined); | 4128 undefined, |
| 4129 receiver_type); |
4123 HBasicBlock* body_entry = CreateBasicBlock(inner_env); | 4130 HBasicBlock* body_entry = CreateBasicBlock(inner_env); |
4124 current_block()->Goto(body_entry); | 4131 current_block()->Goto(body_entry); |
4125 | 4132 |
4126 body_entry->SetJoinId(expr->ReturnId()); | 4133 body_entry->SetJoinId(expr->ReturnId()); |
4127 set_current_block(body_entry); | 4134 set_current_block(body_entry); |
4128 AddInstruction(new(zone()) HEnterInlined(target, function)); | 4135 AddInstruction(new(zone()) HEnterInlined(target, |
| 4136 function, |
| 4137 receiver_type)); |
4129 VisitStatements(function->body()); | 4138 VisitStatements(function->body()); |
4130 if (HasStackOverflow()) { | 4139 if (HasStackOverflow()) { |
4131 // Bail out if the inline function did, as we cannot residualize a call | 4140 // Bail out if the inline function did, as we cannot residualize a call |
4132 // instead. | 4141 // instead. |
4133 TraceInline(target, "inline graph construction failed"); | 4142 TraceInline(target, "inline graph construction failed"); |
4134 return true; | 4143 return true; |
4135 } | 4144 } |
4136 | 4145 |
4137 // Update inlined nodes count. | 4146 // Update inlined nodes count. |
4138 inlined_count_ += nodes_added; | 4147 inlined_count_ += nodes_added; |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4362 HValue* context = environment()->LookupContext(); | 4371 HValue* context = environment()->LookupContext(); |
4363 call = PreProcessCall( | 4372 call = PreProcessCall( |
4364 new(zone()) HCallKeyed(context, key, argument_count)); | 4373 new(zone()) HCallKeyed(context, key, argument_count)); |
4365 call->set_position(expr->position()); | 4374 call->set_position(expr->position()); |
4366 Drop(1); // Key. | 4375 Drop(1); // Key. |
4367 ast_context()->ReturnInstruction(call, expr->id()); | 4376 ast_context()->ReturnInstruction(call, expr->id()); |
4368 return; | 4377 return; |
4369 } | 4378 } |
4370 | 4379 |
4371 // Named function call. | 4380 // Named function call. |
4372 expr->RecordTypeFeedback(oracle()); | 4381 expr->RecordTypeFeedback(oracle(), EXPLICIT_RECEIVER); |
4373 | 4382 |
4374 if (TryCallApply(expr)) return; | 4383 if (TryCallApply(expr)) return; |
4375 | 4384 |
4376 CHECK_ALIVE(VisitForValue(prop->obj())); | 4385 CHECK_ALIVE(VisitForValue(prop->obj())); |
4377 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4386 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
4378 | 4387 |
4379 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 4388 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
4380 | 4389 |
4381 expr->RecordTypeFeedback(oracle()); | |
4382 ZoneMapList* types = expr->GetReceiverTypes(); | 4390 ZoneMapList* types = expr->GetReceiverTypes(); |
4383 | 4391 |
4384 HValue* receiver = | 4392 HValue* receiver = |
4385 environment()->ExpressionStackAt(expr->arguments()->length()); | 4393 environment()->ExpressionStackAt(expr->arguments()->length()); |
4386 if (expr->IsMonomorphic()) { | 4394 if (expr->IsMonomorphic()) { |
4387 Handle<Map> receiver_map = | 4395 Handle<Map> receiver_map = |
4388 (types == NULL) ? Handle<Map>::null() : types->first(); | 4396 (types == NULL) ? Handle<Map>::null() : types->first(); |
4389 if (TryInlineBuiltinFunction(expr, | 4397 if (TryInlineBuiltinFunction(expr, |
4390 receiver, | 4398 receiver, |
4391 receiver_map, | 4399 receiver_map, |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4465 | 4473 |
4466 if (TryInline(expr)) return; | 4474 if (TryInline(expr)) return; |
4467 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 4475 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
4468 argument_count)); | 4476 argument_count)); |
4469 } else { | 4477 } else { |
4470 HValue* context = environment()->LookupContext(); | 4478 HValue* context = environment()->LookupContext(); |
4471 PushAndAdd(new(zone()) HGlobalObject(context)); | 4479 PushAndAdd(new(zone()) HGlobalObject(context)); |
4472 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4480 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
4473 | 4481 |
4474 call = PreProcessCall(new(zone()) HCallGlobal(context, | 4482 call = PreProcessCall(new(zone()) HCallGlobal(context, |
4475 var->name(), | 4483 var->name(), |
4476 argument_count)); | 4484 argument_count)); |
4477 } | 4485 } |
4478 | 4486 |
4479 } else { | 4487 } else { |
4480 HValue* context = environment()->LookupContext(); | 4488 HValue* context = environment()->LookupContext(); |
4481 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 4489 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
4482 AddInstruction(global_object); | 4490 AddInstruction(global_object); |
4483 PushAndAdd(new(zone()) HGlobalReceiver(global_object)); | 4491 PushAndAdd(new(zone()) HGlobalReceiver(global_object)); |
4484 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4492 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
4485 | 4493 |
4486 call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); | 4494 call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); |
(...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5770 HPhi* phi = new(loop_header->zone()) HPhi(i); | 5778 HPhi* phi = new(loop_header->zone()) HPhi(i); |
5771 phi->AddInput(values_[i]); | 5779 phi->AddInput(values_[i]); |
5772 new_env->values_[i] = phi; | 5780 new_env->values_[i] = phi; |
5773 loop_header->AddPhi(phi); | 5781 loop_header->AddPhi(phi); |
5774 } | 5782 } |
5775 new_env->ClearHistory(); | 5783 new_env->ClearHistory(); |
5776 return new_env; | 5784 return new_env; |
5777 } | 5785 } |
5778 | 5786 |
5779 | 5787 |
5780 HEnvironment* HEnvironment::CopyForInlining(Handle<JSFunction> target, | 5788 HEnvironment* HEnvironment::CopyForInlining( |
5781 FunctionLiteral* function, | 5789 Handle<JSFunction> target, |
5782 CompilationPhase compilation_phase, | 5790 FunctionLiteral* function, |
5783 HConstant* undefined) const { | 5791 CompilationPhase compilation_phase, |
| 5792 HConstant* undefined, |
| 5793 ReceiverType receiver_type) const { |
5784 // Outer environment is a copy of this one without the arguments. | 5794 // Outer environment is a copy of this one without the arguments. |
5785 int arity = function->scope()->num_parameters(); | 5795 int arity = function->scope()->num_parameters(); |
5786 HEnvironment* outer = Copy(); | 5796 HEnvironment* outer = Copy(); |
5787 outer->Drop(arity + 1); // Including receiver. | 5797 outer->Drop(arity + 1); // Including receiver. |
5788 outer->ClearHistory(); | 5798 outer->ClearHistory(); |
5789 Zone* zone = closure()->GetIsolate()->zone(); | 5799 Zone* zone = closure()->GetIsolate()->zone(); |
5790 HEnvironment* inner = | 5800 HEnvironment* inner = |
5791 new(zone) HEnvironment(outer, function->scope(), target); | 5801 new(zone) HEnvironment(outer, function->scope(), target); |
5792 // Get the argument values from the original environment. | 5802 // Get the argument values from the original environment. |
5793 if (compilation_phase == HYDROGEN) { | 5803 if (compilation_phase == HYDROGEN) { |
5794 for (int i = 0; i <= arity; ++i) { // Include receiver. | 5804 for (int i = 0; i <= arity; ++i) { // Include receiver. |
5795 HValue* push = ExpressionStackAt(arity - i); | 5805 HValue* push = ExpressionStackAt(arity - i); |
5796 inner->SetValueAt(i, push); | 5806 inner->SetValueAt(i, push); |
5797 } | 5807 } |
5798 } else { | 5808 } else { |
5799 ASSERT(compilation_phase == LITHIUM); | 5809 ASSERT(compilation_phase == LITHIUM); |
5800 for (int i = 0; i <= arity; ++i) { // Include receiver. | 5810 for (int i = 0; i <= arity; ++i) { // Include receiver. |
5801 HValue* push = ExpressionStackAt(arity - i); | 5811 HValue* push = ExpressionStackAt(arity - i); |
5802 inner->SetValueAt(i, push); | 5812 inner->SetValueAt(i, push); |
5803 } | 5813 } |
5804 } | 5814 } |
| 5815 // If the function we are inlining is a strict mode function, pass |
| 5816 // undefined as the implicit receiver. |
| 5817 if (function->strict_mode() && receiver_type == IMPLICIT_RECEIVER) { |
| 5818 inner->SetValueAt(0, undefined); |
| 5819 } |
5805 inner->SetValueAt(arity + 1, outer->LookupContext()); | 5820 inner->SetValueAt(arity + 1, outer->LookupContext()); |
5806 for (int i = arity + 2; i < inner->length(); ++i) { | 5821 for (int i = arity + 2; i < inner->length(); ++i) { |
5807 inner->SetValueAt(i, undefined); | 5822 inner->SetValueAt(i, undefined); |
5808 } | 5823 } |
5809 | 5824 |
5810 inner->set_ast_id(AstNode::kFunctionEntryId); | 5825 inner->set_ast_id(AstNode::kFunctionEntryId); |
5811 return inner; | 5826 return inner; |
5812 } | 5827 } |
5813 | 5828 |
5814 | 5829 |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6142 } | 6157 } |
6143 } | 6158 } |
6144 | 6159 |
6145 #ifdef DEBUG | 6160 #ifdef DEBUG |
6146 if (graph_ != NULL) graph_->Verify(); | 6161 if (graph_ != NULL) graph_->Verify(); |
6147 if (allocator_ != NULL) allocator_->Verify(); | 6162 if (allocator_ != NULL) allocator_->Verify(); |
6148 #endif | 6163 #endif |
6149 } | 6164 } |
6150 | 6165 |
6151 } } // namespace v8::internal | 6166 } } // namespace v8::internal |
OLD | NEW |