Chromium Code Reviews| 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 4628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4639 CallKind call_kind = (expr->expression()->AsProperty() == NULL) | 4639 CallKind call_kind = (expr->expression()->AsProperty() == NULL) |
| 4640 ? CALL_AS_FUNCTION | 4640 ? CALL_AS_FUNCTION |
| 4641 : CALL_AS_METHOD; | 4641 : CALL_AS_METHOD; |
| 4642 | 4642 |
| 4643 // Precondition: call is monomorphic and we have found a target with the | 4643 // Precondition: call is monomorphic and we have found a target with the |
| 4644 // appropriate arity. | 4644 // appropriate arity. |
| 4645 Handle<JSFunction> caller = info()->closure(); | 4645 Handle<JSFunction> caller = info()->closure(); |
| 4646 Handle<JSFunction> target = expr->target(); | 4646 Handle<JSFunction> target = expr->target(); |
| 4647 Handle<SharedFunctionInfo> target_shared(target->shared()); | 4647 Handle<SharedFunctionInfo> target_shared(target->shared()); |
| 4648 | 4648 |
| 4649 // Do a quick check on source code length to avoid parsing large | 4649 if (!target->shared()->is_compiled()) { |
|
ulan
2011/11/29 14:06:52
Is it OK?
It doesn't affect performance.
| |
| 4650 // inlining candidates. | 4650 // Do not inline a function that was never executed before. |
| 4651 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) { | 4651 // It might be lazily parsed, so the node count might be unknown. |
| 4652 TraceInline(target, caller, "target text too big"); | 4652 TraceInline(target, caller, "target was never executed before"); |
| 4653 return false; | 4653 return false; |
| 4654 } | 4654 } |
| 4655 | 4655 |
| 4656 if (FLAG_limit_inlining) { | |
| 4657 int ast_node_count = target_shared->ast_node_count(); | |
| 4658 | |
| 4659 if (ast_node_count > kMaxInlinedSize) { | |
| 4660 // Never inline big functions. | |
| 4661 TraceInline(target, caller, "target AST is too large"); | |
| 4662 return false; | |
| 4663 } | |
| 4664 | |
| 4665 if (target->shared()->SourceSize() > kMaxSourceSize) { | |
| 4666 // Never inline big functions. | |
| 4667 TraceInline(target, caller, "target text too big"); | |
| 4668 return false; | |
| 4669 } | |
| 4670 | |
| 4671 if (inlined_count_ > kMaxInlinedNodesHard) { | |
| 4672 // Do not inline after the hard limit is reached. | |
| 4673 TraceInline(target, caller, "hard cumulative AST node limit is reached"); | |
| 4674 return false; | |
| 4675 } | |
| 4676 | |
| 4677 if (inlined_count_ > kMaxInlinedNodesSoft) { | |
| 4678 // Inline only small "primitive" functions after reaching the soft limit, | |
| 4679 // where "primitive" is defined by syntactic criterion. | |
| 4680 if (ast_node_count > kMaxInlinedPrimitiveSize || | |
| 4681 !target_shared->is_primitive()) { | |
| 4682 TraceInline(target, caller, "soft cumulative AST node limit is reached " | |
| 4683 "and the target is not a small primitive."); | |
| 4684 return false; | |
| 4685 } | |
| 4686 } | |
| 4687 } | |
| 4688 | |
| 4656 // Target must be inlineable. | 4689 // Target must be inlineable. |
| 4657 if (!target->IsInlineable()) { | 4690 if (!target->IsInlineable()) { |
| 4658 TraceInline(target, caller, "target not inlineable"); | 4691 TraceInline(target, caller, "target not inlineable"); |
| 4659 return false; | 4692 return false; |
| 4660 } | 4693 } |
| 4661 | 4694 |
| 4662 #if !defined(V8_TARGET_ARCH_IA32) | 4695 #if !defined(V8_TARGET_ARCH_IA32) |
| 4663 // Target must be able to use caller's context. | 4696 // Target must be able to use caller's context. |
| 4664 CompilationInfo* outer_info = info(); | 4697 CompilationInfo* outer_info = info(); |
| 4665 if (target->context() != outer_info->closure()->context() || | 4698 if (target->context() != outer_info->closure()->context() || |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 4686 // Don't inline recursive functions. | 4719 // Don't inline recursive functions. |
| 4687 for (FunctionState* state = function_state(); | 4720 for (FunctionState* state = function_state(); |
| 4688 state != NULL; | 4721 state != NULL; |
| 4689 state = state->outer()) { | 4722 state = state->outer()) { |
| 4690 if (state->compilation_info()->closure()->shared() == *target_shared) { | 4723 if (state->compilation_info()->closure()->shared() == *target_shared) { |
| 4691 TraceInline(target, caller, "target is recursive"); | 4724 TraceInline(target, caller, "target is recursive"); |
| 4692 return false; | 4725 return false; |
| 4693 } | 4726 } |
| 4694 } | 4727 } |
| 4695 | 4728 |
| 4696 // We don't want to add more than a certain number of nodes from inlining. | |
| 4697 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) { | |
| 4698 TraceInline(target, caller, "cumulative AST node limit reached"); | |
| 4699 return false; | |
| 4700 } | |
| 4701 | |
| 4702 int count_before = AstNode::Count(); | |
| 4703 | |
| 4704 // Parse and allocate variables. | 4729 // Parse and allocate variables. |
| 4705 CompilationInfo target_info(target); | 4730 CompilationInfo target_info(target); |
| 4706 if (!ParserApi::Parse(&target_info) || | 4731 if (!ParserApi::Parse(&target_info) || |
| 4707 !Scope::Analyze(&target_info)) { | 4732 !Scope::Analyze(&target_info)) { |
| 4708 if (target_info.isolate()->has_pending_exception()) { | 4733 if (target_info.isolate()->has_pending_exception()) { |
| 4709 // Parse or scope error, never optimize this function. | 4734 // Parse or scope error, never optimize this function. |
| 4710 SetStackOverflow(); | 4735 SetStackOverflow(); |
| 4711 target_shared->DisableOptimization(*target); | 4736 target_shared->DisableOptimization(*target); |
| 4712 } | 4737 } |
| 4713 TraceInline(target, caller, "parse failure"); | 4738 TraceInline(target, caller, "parse failure"); |
| 4714 return false; | 4739 return false; |
| 4715 } | 4740 } |
| 4716 | 4741 |
| 4717 if (target_info.scope()->num_heap_slots() > 0) { | 4742 if (target_info.scope()->num_heap_slots() > 0) { |
| 4718 TraceInline(target, caller, "target has context-allocated variables"); | 4743 TraceInline(target, caller, "target has context-allocated variables"); |
| 4719 return false; | 4744 return false; |
| 4720 } | 4745 } |
| 4721 FunctionLiteral* function = target_info.function(); | 4746 FunctionLiteral* function = target_info.function(); |
| 4722 | 4747 |
| 4723 // Count the number of AST nodes added by inlining this call. | |
| 4724 int nodes_added = AstNode::Count() - count_before; | |
| 4725 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { | |
| 4726 TraceInline(target, caller, "target AST is too large"); | |
| 4727 return false; | |
| 4728 } | |
| 4729 | |
| 4730 // Don't inline functions that uses the arguments object or that | 4748 // Don't inline functions that uses the arguments object or that |
| 4731 // have a mismatching number of parameters. | 4749 // have a mismatching number of parameters. |
| 4732 int arity = expr->arguments()->length(); | 4750 int arity = expr->arguments()->length(); |
| 4733 if (function->scope()->arguments() != NULL || | 4751 if (function->scope()->arguments() != NULL || |
| 4734 arity != target_shared->formal_parameter_count()) { | 4752 arity != target_shared->formal_parameter_count()) { |
| 4735 TraceInline(target, caller, "target requires special argument handling"); | 4753 TraceInline(target, caller, "target requires special argument handling"); |
| 4736 return false; | 4754 return false; |
| 4737 } | 4755 } |
| 4738 | 4756 |
| 4739 // All declarations must be inlineable. | 4757 // All declarations must be inlineable. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4822 // Bail out if the inline function did, as we cannot residualize a call | 4840 // Bail out if the inline function did, as we cannot residualize a call |
| 4823 // instead. | 4841 // instead. |
| 4824 TraceInline(target, caller, "inline graph construction failed"); | 4842 TraceInline(target, caller, "inline graph construction failed"); |
| 4825 target_shared->DisableOptimization(*target); | 4843 target_shared->DisableOptimization(*target); |
| 4826 inline_bailout_ = true; | 4844 inline_bailout_ = true; |
| 4827 delete target_state; | 4845 delete target_state; |
| 4828 return true; | 4846 return true; |
| 4829 } | 4847 } |
| 4830 | 4848 |
| 4831 // Update inlined nodes count. | 4849 // Update inlined nodes count. |
| 4832 inlined_count_ += nodes_added; | 4850 inlined_count_ += function->ast_node_count(); |
| 4833 | 4851 |
| 4834 TraceInline(target, caller, NULL); | 4852 TraceInline(target, caller, NULL); |
| 4835 | 4853 |
| 4836 if (current_block() != NULL) { | 4854 if (current_block() != NULL) { |
| 4837 // Add a return of undefined if control can fall off the body. In a | 4855 // Add a return of undefined if control can fall off the body. In a |
| 4838 // test context, undefined is false. | 4856 // test context, undefined is false. |
| 4839 if (inlined_test_context() == NULL) { | 4857 if (inlined_test_context() == NULL) { |
| 4840 ASSERT(function_return() != NULL); | 4858 ASSERT(function_return() != NULL); |
| 4841 ASSERT(call_context()->IsEffect() || call_context()->IsValue()); | 4859 ASSERT(call_context()->IsEffect() || call_context()->IsValue()); |
| 4842 if (call_context()->IsEffect()) { | 4860 if (call_context()->IsEffect()) { |
| (...skipping 2309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7152 } | 7170 } |
| 7153 } | 7171 } |
| 7154 | 7172 |
| 7155 #ifdef DEBUG | 7173 #ifdef DEBUG |
| 7156 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 7174 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 7157 if (allocator_ != NULL) allocator_->Verify(); | 7175 if (allocator_ != NULL) allocator_->Verify(); |
| 7158 #endif | 7176 #endif |
| 7159 } | 7177 } |
| 7160 | 7178 |
| 7161 } } // namespace v8::internal | 7179 } } // namespace v8::internal |
| OLD | NEW |