| 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 4456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4467 TraceInline(target, caller, "target text too big"); | 4467 TraceInline(target, caller, "target text too big"); |
| 4468 return false; | 4468 return false; |
| 4469 } | 4469 } |
| 4470 | 4470 |
| 4471 // Target must be inlineable. | 4471 // Target must be inlineable. |
| 4472 if (!target->IsInlineable()) { | 4472 if (!target->IsInlineable()) { |
| 4473 TraceInline(target, caller, "target not inlineable"); | 4473 TraceInline(target, caller, "target not inlineable"); |
| 4474 return false; | 4474 return false; |
| 4475 } | 4475 } |
| 4476 | 4476 |
| 4477 // No context change required. | |
| 4478 CompilationInfo* outer_info = info(); | 4477 CompilationInfo* outer_info = info(); |
| 4479 if (target->context() != outer_info->closure()->context() || | 4478 bool context_changed = target->context() != outer_info->closure()->context() |
| 4480 outer_info->scope()->contains_with() || | 4479 || outer_info->scope()->contains_with() |
| 4481 outer_info->scope()->num_heap_slots() > 0) { | 4480 || outer_info->scope()->num_heap_slots() > 0; |
| 4481 |
| 4482 if (context_changed && !kInlineContextChangeAllowed) { |
| 4482 TraceInline(target, caller, "target requires context change"); | 4483 TraceInline(target, caller, "target requires context change"); |
| 4483 return false; | 4484 return false; |
| 4484 } | 4485 } |
| 4485 | 4486 |
| 4486 // Don't inline deeper than kMaxInliningLevels calls. | 4487 // Don't inline deeper than kMaxInliningLevels calls. |
| 4487 HEnvironment* env = environment(); | 4488 HEnvironment* env = environment(); |
| 4488 int current_level = 1; | 4489 int current_level = 1; |
| 4489 while (env->outer() != NULL) { | 4490 while (env->outer() != NULL) { |
| 4490 if (current_level == Compiler::kMaxInliningLevels) { | 4491 if (current_level == Compiler::kMaxInliningLevels) { |
| 4491 TraceInline(target, caller, "inline depth limit reached"); | 4492 TraceInline(target, caller, "inline depth limit reached"); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4594 TypeFeedbackOracle target_oracle( | 4595 TypeFeedbackOracle target_oracle( |
| 4595 Handle<Code>(target_shared->code()), | 4596 Handle<Code>(target_shared->code()), |
| 4596 Handle<Context>(target->context()->global_context())); | 4597 Handle<Context>(target->context()->global_context())); |
| 4597 FunctionState target_state(this, &target_info, &target_oracle); | 4598 FunctionState target_state(this, &target_info, &target_oracle); |
| 4598 | 4599 |
| 4599 HConstant* undefined = graph()->GetConstantUndefined(); | 4600 HConstant* undefined = graph()->GetConstantUndefined(); |
| 4600 HEnvironment* inner_env = | 4601 HEnvironment* inner_env = |
| 4601 environment()->CopyForInlining(target, | 4602 environment()->CopyForInlining(target, |
| 4602 function, | 4603 function, |
| 4603 undefined, | 4604 undefined, |
| 4604 call_kind); | 4605 call_kind, |
| 4606 context_changed); |
| 4605 HBasicBlock* body_entry = CreateBasicBlock(inner_env); | 4607 HBasicBlock* body_entry = CreateBasicBlock(inner_env); |
| 4606 current_block()->Goto(body_entry); | 4608 current_block()->Goto(body_entry); |
| 4607 body_entry->SetJoinId(expr->ReturnId()); | 4609 body_entry->SetJoinId(expr->ReturnId()); |
| 4608 set_current_block(body_entry); | 4610 set_current_block(body_entry); |
| 4609 AddInstruction(new(zone()) HEnterInlined(target, | 4611 AddInstruction(new(zone()) HEnterInlined(target, |
| 4610 function, | 4612 function, |
| 4611 call_kind)); | 4613 call_kind, |
| 4614 context_changed)); |
| 4612 VisitDeclarations(target_info.scope()->declarations()); | 4615 VisitDeclarations(target_info.scope()->declarations()); |
| 4616 if (context_changed) { |
| 4617 AddInstruction(HInstruction::cast(inner_env->LookupContext())); |
| 4618 } |
| 4613 VisitStatements(function->body()); | 4619 VisitStatements(function->body()); |
| 4614 if (HasStackOverflow()) { | 4620 if (HasStackOverflow()) { |
| 4615 // Bail out if the inline function did, as we cannot residualize a call | 4621 // Bail out if the inline function did, as we cannot residualize a call |
| 4616 // instead. | 4622 // instead. |
| 4617 TraceInline(target, caller, "inline graph construction failed"); | 4623 TraceInline(target, caller, "inline graph construction failed"); |
| 4618 target_shared->DisableOptimization(*target); | 4624 target_shared->DisableOptimization(*target); |
| 4619 inline_bailout_ = true; | 4625 inline_bailout_ = true; |
| 4620 return true; | 4626 return true; |
| 4621 } | 4627 } |
| 4622 | 4628 |
| (...skipping 1828 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6451 } | 6457 } |
| 6452 new_env->ClearHistory(); | 6458 new_env->ClearHistory(); |
| 6453 return new_env; | 6459 return new_env; |
| 6454 } | 6460 } |
| 6455 | 6461 |
| 6456 | 6462 |
| 6457 HEnvironment* HEnvironment::CopyForInlining( | 6463 HEnvironment* HEnvironment::CopyForInlining( |
| 6458 Handle<JSFunction> target, | 6464 Handle<JSFunction> target, |
| 6459 FunctionLiteral* function, | 6465 FunctionLiteral* function, |
| 6460 HConstant* undefined, | 6466 HConstant* undefined, |
| 6461 CallKind call_kind) const { | 6467 CallKind call_kind, |
| 6468 bool context_changed) const { |
| 6462 // Outer environment is a copy of this one without the arguments. | 6469 // Outer environment is a copy of this one without the arguments. |
| 6463 int arity = function->scope()->num_parameters(); | 6470 int arity = function->scope()->num_parameters(); |
| 6464 HEnvironment* outer = Copy(); | 6471 HEnvironment* outer = Copy(); |
| 6465 outer->Drop(arity + 1); // Including receiver. | 6472 outer->Drop(arity + 1); // Including receiver. |
| 6466 outer->ClearHistory(); | 6473 outer->ClearHistory(); |
| 6467 Zone* zone = closure()->GetIsolate()->zone(); | 6474 Zone* zone = closure()->GetIsolate()->zone(); |
| 6468 HEnvironment* inner = | 6475 HEnvironment* inner = |
| 6469 new(zone) HEnvironment(outer, function->scope(), target); | 6476 new(zone) HEnvironment(outer, function->scope(), target); |
| 6470 // Get the argument values from the original environment. | 6477 // Get the argument values from the original environment. |
| 6471 for (int i = 0; i <= arity; ++i) { // Include receiver. | 6478 for (int i = 0; i <= arity; ++i) { // Include receiver. |
| 6472 HValue* push = ExpressionStackAt(arity - i); | 6479 HValue* push = ExpressionStackAt(arity - i); |
| 6473 inner->SetValueAt(i, push); | 6480 inner->SetValueAt(i, push); |
| 6474 } | 6481 } |
| 6475 // If the function we are inlining is a strict mode function or a | 6482 // If the function we are inlining is a strict mode function or a |
| 6476 // builtin function, pass undefined as the receiver for function | 6483 // builtin function, pass undefined as the receiver for function |
| 6477 // calls (instead of the global receiver). | 6484 // calls (instead of the global receiver). |
| 6478 if ((target->shared()->native() || function->strict_mode()) && | 6485 if ((target->shared()->native() || function->strict_mode()) && |
| 6479 call_kind == CALL_AS_FUNCTION) { | 6486 call_kind == CALL_AS_FUNCTION) { |
| 6480 inner->SetValueAt(0, undefined); | 6487 inner->SetValueAt(0, undefined); |
| 6481 } | 6488 } |
| 6482 inner->SetValueAt(arity + 1, outer->LookupContext()); | 6489 if (context_changed) { |
| 6490 HInlinedContext* context = new(zone) HInlinedContext(target); |
| 6491 inner->SetValueAt(arity + 1, context); |
| 6492 } else { |
| 6493 inner->SetValueAt(arity + 1, LookupContext()); |
| 6494 } |
| 6483 for (int i = arity + 2; i < inner->length(); ++i) { | 6495 for (int i = arity + 2; i < inner->length(); ++i) { |
| 6484 inner->SetValueAt(i, undefined); | 6496 inner->SetValueAt(i, undefined); |
| 6485 } | 6497 } |
| 6486 | 6498 |
| 6487 inner->set_ast_id(AstNode::kFunctionEntryId); | 6499 inner->set_ast_id(AstNode::kFunctionEntryId); |
| 6488 return inner; | 6500 return inner; |
| 6489 } | 6501 } |
| 6490 | 6502 |
| 6491 | 6503 |
| 6492 void HEnvironment::PrintTo(StringStream* stream) { | 6504 void HEnvironment::PrintTo(StringStream* stream) { |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6821 } | 6833 } |
| 6822 } | 6834 } |
| 6823 | 6835 |
| 6824 #ifdef DEBUG | 6836 #ifdef DEBUG |
| 6825 if (graph_ != NULL) graph_->Verify(); | 6837 if (graph_ != NULL) graph_->Verify(); |
| 6826 if (allocator_ != NULL) allocator_->Verify(); | 6838 if (allocator_ != NULL) allocator_->Verify(); |
| 6827 #endif | 6839 #endif |
| 6828 } | 6840 } |
| 6829 | 6841 |
| 6830 } } // namespace v8::internal | 6842 } } // namespace v8::internal |
| OLD | NEW |