| 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 4036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4047 PrintF("Did not inline %s called from %s (%s).\n", | 4047 PrintF("Did not inline %s called from %s (%s).\n", |
| 4048 *target_name, *caller_name, reason); | 4048 *target_name, *caller_name, reason); |
| 4049 } | 4049 } |
| 4050 } | 4050 } |
| 4051 } | 4051 } |
| 4052 | 4052 |
| 4053 | 4053 |
| 4054 bool HGraphBuilder::TryInline(Call* expr) { | 4054 bool HGraphBuilder::TryInline(Call* expr) { |
| 4055 if (!FLAG_use_inlining) return false; | 4055 if (!FLAG_use_inlining) return false; |
| 4056 | 4056 |
| 4057 // The function call we are inlining is a method call if the call |
| 4058 // is a property call. |
| 4059 CallKind call_kind = (expr->expression()->AsProperty() == NULL) |
| 4060 ? CALL_AS_FUNCTION |
| 4061 : CALL_AS_METHOD; |
| 4062 |
| 4057 // Precondition: call is monomorphic and we have found a target with the | 4063 // Precondition: call is monomorphic and we have found a target with the |
| 4058 // appropriate arity. | 4064 // appropriate arity. |
| 4059 Handle<JSFunction> caller = info()->closure(); | 4065 Handle<JSFunction> caller = info()->closure(); |
| 4060 Handle<JSFunction> target = expr->target(); | 4066 Handle<JSFunction> target = expr->target(); |
| 4061 Handle<SharedFunctionInfo> target_shared(target->shared()); | 4067 Handle<SharedFunctionInfo> target_shared(target->shared()); |
| 4062 | 4068 |
| 4063 // Do a quick check on source code length to avoid parsing large | 4069 // Do a quick check on source code length to avoid parsing large |
| 4064 // inlining candidates. | 4070 // inlining candidates. |
| 4065 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) { | 4071 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) { |
| 4066 TraceInline(target, caller, "target text too big"); | 4072 TraceInline(target, caller, "target text too big"); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4182 TypeFeedbackOracle target_oracle( | 4188 TypeFeedbackOracle target_oracle( |
| 4183 Handle<Code>(target_shared->code()), | 4189 Handle<Code>(target_shared->code()), |
| 4184 Handle<Context>(target->context()->global_context())); | 4190 Handle<Context>(target->context()->global_context())); |
| 4185 FunctionState target_state(this, &target_info, &target_oracle); | 4191 FunctionState target_state(this, &target_info, &target_oracle); |
| 4186 | 4192 |
| 4187 HConstant* undefined = graph()->GetConstantUndefined(); | 4193 HConstant* undefined = graph()->GetConstantUndefined(); |
| 4188 HEnvironment* inner_env = | 4194 HEnvironment* inner_env = |
| 4189 environment()->CopyForInlining(target, | 4195 environment()->CopyForInlining(target, |
| 4190 function, | 4196 function, |
| 4191 HEnvironment::HYDROGEN, | 4197 HEnvironment::HYDROGEN, |
| 4192 undefined); | 4198 undefined, |
| 4199 call_kind); |
| 4193 HBasicBlock* body_entry = CreateBasicBlock(inner_env); | 4200 HBasicBlock* body_entry = CreateBasicBlock(inner_env); |
| 4194 current_block()->Goto(body_entry); | 4201 current_block()->Goto(body_entry); |
| 4195 | 4202 |
| 4196 body_entry->SetJoinId(expr->ReturnId()); | 4203 body_entry->SetJoinId(expr->ReturnId()); |
| 4197 set_current_block(body_entry); | 4204 set_current_block(body_entry); |
| 4198 AddInstruction(new(zone()) HEnterInlined(target, function)); | 4205 AddInstruction(new(zone()) HEnterInlined(target, |
| 4206 function, |
| 4207 call_kind)); |
| 4199 VisitStatements(function->body()); | 4208 VisitStatements(function->body()); |
| 4200 if (HasStackOverflow()) { | 4209 if (HasStackOverflow()) { |
| 4201 // Bail out if the inline function did, as we cannot residualize a call | 4210 // Bail out if the inline function did, as we cannot residualize a call |
| 4202 // instead. | 4211 // instead. |
| 4203 TraceInline(target, caller, "inline graph construction failed"); | 4212 TraceInline(target, caller, "inline graph construction failed"); |
| 4204 target_shared->DisableOptimization(*target); | 4213 target_shared->DisableOptimization(*target); |
| 4205 inline_bailout_ = true; | 4214 inline_bailout_ = true; |
| 4206 return true; | 4215 return true; |
| 4207 } | 4216 } |
| 4208 | 4217 |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4434 HValue* context = environment()->LookupContext(); | 4443 HValue* context = environment()->LookupContext(); |
| 4435 call = PreProcessCall( | 4444 call = PreProcessCall( |
| 4436 new(zone()) HCallKeyed(context, key, argument_count)); | 4445 new(zone()) HCallKeyed(context, key, argument_count)); |
| 4437 call->set_position(expr->position()); | 4446 call->set_position(expr->position()); |
| 4438 Drop(1); // Key. | 4447 Drop(1); // Key. |
| 4439 ast_context()->ReturnInstruction(call, expr->id()); | 4448 ast_context()->ReturnInstruction(call, expr->id()); |
| 4440 return; | 4449 return; |
| 4441 } | 4450 } |
| 4442 | 4451 |
| 4443 // Named function call. | 4452 // Named function call. |
| 4444 expr->RecordTypeFeedback(oracle()); | 4453 expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); |
| 4445 | 4454 |
| 4446 if (TryCallApply(expr)) return; | 4455 if (TryCallApply(expr)) return; |
| 4447 | 4456 |
| 4448 CHECK_ALIVE(VisitForValue(prop->obj())); | 4457 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 4449 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4458 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 4450 | 4459 |
| 4451 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 4460 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 4452 | 4461 |
| 4453 expr->RecordTypeFeedback(oracle()); | |
| 4454 ZoneMapList* types = expr->GetReceiverTypes(); | 4462 ZoneMapList* types = expr->GetReceiverTypes(); |
| 4455 | 4463 |
| 4456 HValue* receiver = | 4464 HValue* receiver = |
| 4457 environment()->ExpressionStackAt(expr->arguments()->length()); | 4465 environment()->ExpressionStackAt(expr->arguments()->length()); |
| 4458 if (expr->IsMonomorphic()) { | 4466 if (expr->IsMonomorphic()) { |
| 4459 Handle<Map> receiver_map = | 4467 Handle<Map> receiver_map = |
| 4460 (types == NULL) ? Handle<Map>::null() : types->first(); | 4468 (types == NULL) ? Handle<Map>::null() : types->first(); |
| 4461 if (TryInlineBuiltinFunction(expr, | 4469 if (TryInlineBuiltinFunction(expr, |
| 4462 receiver, | 4470 receiver, |
| 4463 receiver_map, | 4471 receiver_map, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4537 | 4545 |
| 4538 if (TryInline(expr)) return; | 4546 if (TryInline(expr)) return; |
| 4539 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 4547 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
| 4540 argument_count)); | 4548 argument_count)); |
| 4541 } else { | 4549 } else { |
| 4542 HValue* context = environment()->LookupContext(); | 4550 HValue* context = environment()->LookupContext(); |
| 4543 PushAndAdd(new(zone()) HGlobalObject(context)); | 4551 PushAndAdd(new(zone()) HGlobalObject(context)); |
| 4544 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4552 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 4545 | 4553 |
| 4546 call = PreProcessCall(new(zone()) HCallGlobal(context, | 4554 call = PreProcessCall(new(zone()) HCallGlobal(context, |
| 4547 var->name(), | 4555 var->name(), |
| 4548 argument_count)); | 4556 argument_count)); |
| 4549 } | 4557 } |
| 4550 | 4558 |
| 4551 } else { | 4559 } else { |
| 4552 HValue* context = environment()->LookupContext(); | 4560 HValue* context = environment()->LookupContext(); |
| 4553 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 4561 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 4554 AddInstruction(global_object); | 4562 AddInstruction(global_object); |
| 4555 PushAndAdd(new(zone()) HGlobalReceiver(global_object)); | 4563 PushAndAdd(new(zone()) HGlobalReceiver(global_object)); |
| 4556 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4564 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 4557 | 4565 |
| 4558 call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); | 4566 call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); |
| (...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5842 HPhi* phi = new(loop_header->zone()) HPhi(i); | 5850 HPhi* phi = new(loop_header->zone()) HPhi(i); |
| 5843 phi->AddInput(values_[i]); | 5851 phi->AddInput(values_[i]); |
| 5844 new_env->values_[i] = phi; | 5852 new_env->values_[i] = phi; |
| 5845 loop_header->AddPhi(phi); | 5853 loop_header->AddPhi(phi); |
| 5846 } | 5854 } |
| 5847 new_env->ClearHistory(); | 5855 new_env->ClearHistory(); |
| 5848 return new_env; | 5856 return new_env; |
| 5849 } | 5857 } |
| 5850 | 5858 |
| 5851 | 5859 |
| 5852 HEnvironment* HEnvironment::CopyForInlining(Handle<JSFunction> target, | 5860 HEnvironment* HEnvironment::CopyForInlining( |
| 5853 FunctionLiteral* function, | 5861 Handle<JSFunction> target, |
| 5854 CompilationPhase compilation_phase, | 5862 FunctionLiteral* function, |
| 5855 HConstant* undefined) const { | 5863 CompilationPhase compilation_phase, |
| 5864 HConstant* undefined, |
| 5865 CallKind call_kind) const { |
| 5856 // Outer environment is a copy of this one without the arguments. | 5866 // Outer environment is a copy of this one without the arguments. |
| 5857 int arity = function->scope()->num_parameters(); | 5867 int arity = function->scope()->num_parameters(); |
| 5858 HEnvironment* outer = Copy(); | 5868 HEnvironment* outer = Copy(); |
| 5859 outer->Drop(arity + 1); // Including receiver. | 5869 outer->Drop(arity + 1); // Including receiver. |
| 5860 outer->ClearHistory(); | 5870 outer->ClearHistory(); |
| 5861 Zone* zone = closure()->GetIsolate()->zone(); | 5871 Zone* zone = closure()->GetIsolate()->zone(); |
| 5862 HEnvironment* inner = | 5872 HEnvironment* inner = |
| 5863 new(zone) HEnvironment(outer, function->scope(), target); | 5873 new(zone) HEnvironment(outer, function->scope(), target); |
| 5864 // Get the argument values from the original environment. | 5874 // Get the argument values from the original environment. |
| 5865 if (compilation_phase == HYDROGEN) { | 5875 if (compilation_phase == HYDROGEN) { |
| 5866 for (int i = 0; i <= arity; ++i) { // Include receiver. | 5876 for (int i = 0; i <= arity; ++i) { // Include receiver. |
| 5867 HValue* push = ExpressionStackAt(arity - i); | 5877 HValue* push = ExpressionStackAt(arity - i); |
| 5868 inner->SetValueAt(i, push); | 5878 inner->SetValueAt(i, push); |
| 5869 } | 5879 } |
| 5870 } else { | 5880 } else { |
| 5871 ASSERT(compilation_phase == LITHIUM); | 5881 ASSERT(compilation_phase == LITHIUM); |
| 5872 for (int i = 0; i <= arity; ++i) { // Include receiver. | 5882 for (int i = 0; i <= arity; ++i) { // Include receiver. |
| 5873 HValue* push = ExpressionStackAt(arity - i); | 5883 HValue* push = ExpressionStackAt(arity - i); |
| 5874 inner->SetValueAt(i, push); | 5884 inner->SetValueAt(i, push); |
| 5875 } | 5885 } |
| 5876 } | 5886 } |
| 5887 // If the function we are inlining is a strict mode function, pass |
| 5888 // undefined as the receiver for function calls (instead of the |
| 5889 // global receiver). |
| 5890 if (function->strict_mode() && call_kind == CALL_AS_FUNCTION) { |
| 5891 inner->SetValueAt(0, undefined); |
| 5892 } |
| 5877 inner->SetValueAt(arity + 1, outer->LookupContext()); | 5893 inner->SetValueAt(arity + 1, outer->LookupContext()); |
| 5878 for (int i = arity + 2; i < inner->length(); ++i) { | 5894 for (int i = arity + 2; i < inner->length(); ++i) { |
| 5879 inner->SetValueAt(i, undefined); | 5895 inner->SetValueAt(i, undefined); |
| 5880 } | 5896 } |
| 5881 | 5897 |
| 5882 inner->set_ast_id(AstNode::kFunctionEntryId); | 5898 inner->set_ast_id(AstNode::kFunctionEntryId); |
| 5883 return inner; | 5899 return inner; |
| 5884 } | 5900 } |
| 5885 | 5901 |
| 5886 | 5902 |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6214 } | 6230 } |
| 6215 } | 6231 } |
| 6216 | 6232 |
| 6217 #ifdef DEBUG | 6233 #ifdef DEBUG |
| 6218 if (graph_ != NULL) graph_->Verify(); | 6234 if (graph_ != NULL) graph_->Verify(); |
| 6219 if (allocator_ != NULL) allocator_->Verify(); | 6235 if (allocator_ != NULL) allocator_->Verify(); |
| 6220 #endif | 6236 #endif |
| 6221 } | 6237 } |
| 6222 | 6238 |
| 6223 } } // namespace v8::internal | 6239 } } // namespace v8::internal |
| OLD | NEW |