| 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 |