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 |