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 int ast_node_count = target_shared->ast_node_count(); |
| 4650 // inlining candidates. | 4650 |
| 4651 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) { | 4651 if (FLAG_limit_inlining) { |
| 4652 TraceInline(target, caller, "target text too big"); | 4652 if (ast_node_count > kMaxInlinedSize) { |
| 4653 return false; | 4653 // Never inline big functions. |
| 4654 TraceInline(target, caller, "target AST is too large"); | |
| 4655 return false; | |
| 4656 } | |
| 4657 | |
| 4658 if (target->shared()->SourceSize() > kMaxSourceSize) { | |
| 4659 // Never inline big functions. | |
| 4660 TraceInline(target, caller, "target text too big"); | |
| 4661 return false; | |
| 4662 } | |
| 4663 | |
| 4664 if (inlined_count_ > kMaxInlinedNodesHard) { | |
| 4665 // Do not inline after the hard limit is reached. | |
| 4666 TraceInline(target, caller, "cumulative AST node limit reached"); | |
| 4667 return false; | |
| 4668 } | |
| 4669 | |
| 4670 if (inlined_count_ > kMaxInlinedNodesSoft) { | |
| 4671 // Inline only small "primitive" functions after reaching the soft limit, | |
| 4672 // where "primitive" is defined by syntactic criterion. | |
| 4673 if (ast_node_count > kMaxInlinedPrimitiveSize || | |
| 4674 inlined_count_ > kMaxInlinedNodesHard || | |
|
Kevin Millikin (Chromium)
2011/11/28 12:11:59
I think 'inlined_count_ > MaxInlinedNodesHard' is
ulan
2011/11/29 14:06:52
Done.
| |
| 4675 !target_shared->is_primitive()) { | |
| 4676 TraceInline(target, caller, "cumulative AST node limit reached"); | |
|
Kevin Millikin (Chromium)
2011/11/28 12:11:59
This should be a distinct bailout message from the
ulan
2011/11/29 14:06:52
Done.
| |
| 4677 return false; | |
| 4678 } | |
| 4679 } | |
| 4654 } | 4680 } |
| 4655 | 4681 |
| 4656 // Target must be inlineable. | 4682 // Target must be inlineable. |
| 4657 if (!target->IsInlineable()) { | 4683 if (!target->IsInlineable()) { |
| 4658 TraceInline(target, caller, "target not inlineable"); | 4684 TraceInline(target, caller, "target not inlineable"); |
| 4659 return false; | 4685 return false; |
| 4660 } | 4686 } |
| 4661 | 4687 |
| 4662 #if !defined(V8_TARGET_ARCH_IA32) | 4688 #if !defined(V8_TARGET_ARCH_IA32) |
| 4663 // Target must be able to use caller's context. | 4689 // Target must be able to use caller's context. |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 4686 // Don't inline recursive functions. | 4712 // Don't inline recursive functions. |
| 4687 for (FunctionState* state = function_state(); | 4713 for (FunctionState* state = function_state(); |
| 4688 state != NULL; | 4714 state != NULL; |
| 4689 state = state->outer()) { | 4715 state = state->outer()) { |
| 4690 if (state->compilation_info()->closure()->shared() == *target_shared) { | 4716 if (state->compilation_info()->closure()->shared() == *target_shared) { |
| 4691 TraceInline(target, caller, "target is recursive"); | 4717 TraceInline(target, caller, "target is recursive"); |
| 4692 return false; | 4718 return false; |
| 4693 } | 4719 } |
| 4694 } | 4720 } |
| 4695 | 4721 |
| 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. | 4722 // Parse and allocate variables. |
| 4705 CompilationInfo target_info(target); | 4723 CompilationInfo target_info(target); |
| 4706 if (!ParserApi::Parse(&target_info) || | 4724 if (!ParserApi::Parse(&target_info) || |
| 4707 !Scope::Analyze(&target_info)) { | 4725 !Scope::Analyze(&target_info)) { |
| 4708 if (target_info.isolate()->has_pending_exception()) { | 4726 if (target_info.isolate()->has_pending_exception()) { |
| 4709 // Parse or scope error, never optimize this function. | 4727 // Parse or scope error, never optimize this function. |
| 4710 SetStackOverflow(); | 4728 SetStackOverflow(); |
| 4711 target_shared->DisableOptimization(*target); | 4729 target_shared->DisableOptimization(*target); |
| 4712 } | 4730 } |
| 4713 TraceInline(target, caller, "parse failure"); | 4731 TraceInline(target, caller, "parse failure"); |
| 4714 return false; | 4732 return false; |
| 4715 } | 4733 } |
| 4716 | 4734 |
| 4717 if (target_info.scope()->num_heap_slots() > 0) { | 4735 if (target_info.scope()->num_heap_slots() > 0) { |
| 4718 TraceInline(target, caller, "target has context-allocated variables"); | 4736 TraceInline(target, caller, "target has context-allocated variables"); |
| 4719 return false; | 4737 return false; |
| 4720 } | 4738 } |
| 4721 FunctionLiteral* function = target_info.function(); | 4739 FunctionLiteral* function = target_info.function(); |
| 4722 | 4740 |
| 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 | 4741 // Don't inline functions that uses the arguments object or that |
| 4731 // have a mismatching number of parameters. | 4742 // have a mismatching number of parameters. |
| 4732 int arity = expr->arguments()->length(); | 4743 int arity = expr->arguments()->length(); |
| 4733 if (function->scope()->arguments() != NULL || | 4744 if (function->scope()->arguments() != NULL || |
| 4734 arity != target_shared->formal_parameter_count()) { | 4745 arity != target_shared->formal_parameter_count()) { |
| 4735 TraceInline(target, caller, "target requires special argument handling"); | 4746 TraceInline(target, caller, "target requires special argument handling"); |
| 4736 return false; | 4747 return false; |
| 4737 } | 4748 } |
| 4738 | 4749 |
| 4739 // All declarations must be inlineable. | 4750 // 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 | 4833 // Bail out if the inline function did, as we cannot residualize a call |
| 4823 // instead. | 4834 // instead. |
| 4824 TraceInline(target, caller, "inline graph construction failed"); | 4835 TraceInline(target, caller, "inline graph construction failed"); |
| 4825 target_shared->DisableOptimization(*target); | 4836 target_shared->DisableOptimization(*target); |
| 4826 inline_bailout_ = true; | 4837 inline_bailout_ = true; |
| 4827 delete target_state; | 4838 delete target_state; |
| 4828 return true; | 4839 return true; |
| 4829 } | 4840 } |
| 4830 | 4841 |
| 4831 // Update inlined nodes count. | 4842 // Update inlined nodes count. |
| 4832 inlined_count_ += nodes_added; | 4843 inlined_count_ += ast_node_count; |
| 4833 | 4844 |
| 4834 TraceInline(target, caller, NULL); | 4845 TraceInline(target, caller, NULL); |
| 4835 | 4846 |
| 4836 if (current_block() != NULL) { | 4847 if (current_block() != NULL) { |
| 4837 // Add a return of undefined if control can fall off the body. In a | 4848 // Add a return of undefined if control can fall off the body. In a |
| 4838 // test context, undefined is false. | 4849 // test context, undefined is false. |
| 4839 if (inlined_test_context() == NULL) { | 4850 if (inlined_test_context() == NULL) { |
| 4840 ASSERT(function_return() != NULL); | 4851 ASSERT(function_return() != NULL); |
| 4841 ASSERT(call_context()->IsEffect() || call_context()->IsValue()); | 4852 ASSERT(call_context()->IsEffect() || call_context()->IsValue()); |
| 4842 if (call_context()->IsEffect()) { | 4853 if (call_context()->IsEffect()) { |
| (...skipping 2309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7152 } | 7163 } |
| 7153 } | 7164 } |
| 7154 | 7165 |
| 7155 #ifdef DEBUG | 7166 #ifdef DEBUG |
| 7156 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 7167 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 7157 if (allocator_ != NULL) allocator_->Verify(); | 7168 if (allocator_ != NULL) allocator_->Verify(); |
| 7158 #endif | 7169 #endif |
| 7159 } | 7170 } |
| 7160 | 7171 |
| 7161 } } // namespace v8::internal | 7172 } } // namespace v8::internal |
| OLD | NEW |