OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/js-inlining-heuristic.h" | 5 #include "src/compiler/js-inlining-heuristic.h" |
6 | 6 |
7 #include "src/compilation-info.h" | 7 #include "src/compilation-info.h" |
8 #include "src/compiler/common-operator.h" | 8 #include "src/compiler/common-operator.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
10 #include "src/compiler/simplified-operator.h" | 10 #include "src/compiler/simplified-operator.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 // Quick check on the size of the AST to avoid parsing large candidate. | 58 // Quick check on the size of the AST to avoid parsing large candidate. |
59 if (shared->ast_node_count() > FLAG_max_inlined_nodes) { | 59 if (shared->ast_node_count() > FLAG_max_inlined_nodes) { |
60 return false; | 60 return false; |
61 } | 61 } |
62 | 62 |
63 // Avoid inlining across the boundary of asm.js code. | 63 // Avoid inlining across the boundary of asm.js code. |
64 if (shared->asm_function()) return false; | 64 if (shared->asm_function()) return false; |
65 return true; | 65 return true; |
66 } | 66 } |
67 | 67 |
| 68 bool IsSmallInlineFunction(Handle<SharedFunctionInfo> shared) { |
| 69 // Don't forcibly inline functions that weren't compiled yet. |
| 70 if (shared->ast_node_count() == 0) return false; |
| 71 |
| 72 // Forcibly inline small functions. |
| 73 if (shared->ast_node_count() <= FLAG_max_inlined_nodes_small) return true; |
| 74 return false; |
| 75 } |
| 76 |
68 } // namespace | 77 } // namespace |
69 | 78 |
70 Reduction JSInliningHeuristic::Reduce(Node* node) { | 79 Reduction JSInliningHeuristic::Reduce(Node* node) { |
71 if (!IrOpcode::IsInlineeOpcode(node->opcode())) return NoChange(); | 80 if (!IrOpcode::IsInlineeOpcode(node->opcode())) return NoChange(); |
72 | 81 |
73 // Check if we already saw that {node} before, and if so, just skip it. | 82 // Check if we already saw that {node} before, and if so, just skip it. |
74 if (seen_.find(node->id()) != seen_.end()) return NoChange(); | 83 if (seen_.find(node->id()) != seen_.end()) return NoChange(); |
75 seen_.insert(node->id()); | 84 seen_.insert(node->id()); |
76 | 85 |
77 // Check if the {node} is an appropriate candidate for inlining. | 86 // Check if the {node} is an appropriate candidate for inlining. |
78 Node* callee = node->InputAt(0); | 87 Node* callee = node->InputAt(0); |
79 Candidate candidate; | 88 Candidate candidate; |
80 candidate.node = node; | 89 candidate.node = node; |
81 candidate.num_functions = CollectFunctions( | 90 candidate.num_functions = CollectFunctions( |
82 callee, candidate.functions, kMaxCallPolymorphism, candidate.shared_info); | 91 callee, candidate.functions, kMaxCallPolymorphism, candidate.shared_info); |
83 if (candidate.num_functions == 0) { | 92 if (candidate.num_functions == 0) { |
84 return NoChange(); | 93 return NoChange(); |
85 } else if (candidate.num_functions > 1 && !FLAG_polymorphic_inlining) { | 94 } else if (candidate.num_functions > 1 && !FLAG_polymorphic_inlining) { |
86 TRACE( | 95 TRACE( |
87 "Not considering call site #%d:%s, because polymorphic inlining " | 96 "Not considering call site #%d:%s, because polymorphic inlining " |
88 "is disabled\n", | 97 "is disabled\n", |
89 node->id(), node->op()->mnemonic()); | 98 node->id(), node->op()->mnemonic()); |
90 return NoChange(); | 99 return NoChange(); |
91 } | 100 } |
92 | 101 |
93 // Functions marked with %SetForceInlineFlag are immediately inlined. | 102 // Functions marked with %SetForceInlineFlag are immediately inlined. |
94 bool can_inline = false, force_inline = true; | 103 bool can_inline = false, force_inline = true, small_inline = true; |
95 for (int i = 0; i < candidate.num_functions; ++i) { | 104 for (int i = 0; i < candidate.num_functions; ++i) { |
96 Handle<SharedFunctionInfo> shared = | 105 Handle<SharedFunctionInfo> shared = |
97 candidate.functions[i].is_null() | 106 candidate.functions[i].is_null() |
98 ? candidate.shared_info | 107 ? candidate.shared_info |
99 : handle(candidate.functions[i]->shared()); | 108 : handle(candidate.functions[i]->shared()); |
100 if (!shared->force_inline()) { | 109 if (!shared->force_inline()) { |
101 force_inline = false; | 110 force_inline = false; |
102 } | 111 } |
103 if (CanInlineFunction(shared)) { | 112 if (CanInlineFunction(shared)) { |
104 can_inline = true; | 113 can_inline = true; |
105 } | 114 } |
| 115 if (!IsSmallInlineFunction(shared)) { |
| 116 small_inline = false; |
| 117 } |
106 } | 118 } |
107 if (force_inline) return InlineCandidate(candidate); | 119 if (force_inline) return InlineCandidate(candidate); |
108 if (!can_inline) return NoChange(); | 120 if (!can_inline) return NoChange(); |
109 | 121 |
110 // Stop inlining once the maximum allowed level is reached. | 122 // Stop inlining once the maximum allowed level is reached. |
111 int level = 0; | 123 int level = 0; |
112 for (Node* frame_state = NodeProperties::GetFrameStateInput(node); | 124 for (Node* frame_state = NodeProperties::GetFrameStateInput(node); |
113 frame_state->opcode() == IrOpcode::kFrameState; | 125 frame_state->opcode() == IrOpcode::kFrameState; |
114 frame_state = NodeProperties::GetFrameStateInput(frame_state)) { | 126 frame_state = NodeProperties::GetFrameStateInput(frame_state)) { |
115 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state); | 127 FrameStateInfo const& frame_info = OpParameter<FrameStateInfo>(frame_state); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 } | 159 } |
148 | 160 |
149 // Don't consider a {candidate} whose frequency is below the | 161 // Don't consider a {candidate} whose frequency is below the |
150 // threshold, i.e. a call site that is only hit once every N | 162 // threshold, i.e. a call site that is only hit once every N |
151 // invocations of the caller. | 163 // invocations of the caller. |
152 if (candidate.frequency.IsKnown() && | 164 if (candidate.frequency.IsKnown() && |
153 candidate.frequency.value() < FLAG_min_inlining_frequency) { | 165 candidate.frequency.value() < FLAG_min_inlining_frequency) { |
154 return NoChange(); | 166 return NoChange(); |
155 } | 167 } |
156 | 168 |
| 169 // Forcibly inline small functions here. |
| 170 if (small_inline) { |
| 171 TRACE("Inlining small function(s) at call site #%d:%s\n", node->id(), |
| 172 node->op()->mnemonic()); |
| 173 return InlineCandidate(candidate); |
| 174 } |
| 175 |
157 // In the general case we remember the candidate for later. | 176 // In the general case we remember the candidate for later. |
158 candidates_.insert(candidate); | 177 candidates_.insert(candidate); |
159 return NoChange(); | 178 return NoChange(); |
160 } | 179 } |
161 | 180 |
162 void JSInliningHeuristic::Finalize() { | 181 void JSInliningHeuristic::Finalize() { |
163 if (candidates_.empty()) return; // Nothing to do without candidates. | 182 if (candidates_.empty()) return; // Nothing to do without candidates. |
164 if (FLAG_trace_turbo_inlining) PrintCandidates(); | 183 if (FLAG_trace_turbo_inlining) PrintCandidates(); |
165 | 184 |
166 // We inline at most one candidate in every iteration of the fixpoint. | 185 // We inline at most one candidate in every iteration of the fixpoint. |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 return jsgraph()->common(); | 342 return jsgraph()->common(); |
324 } | 343 } |
325 | 344 |
326 SimplifiedOperatorBuilder* JSInliningHeuristic::simplified() const { | 345 SimplifiedOperatorBuilder* JSInliningHeuristic::simplified() const { |
327 return jsgraph()->simplified(); | 346 return jsgraph()->simplified(); |
328 } | 347 } |
329 | 348 |
330 } // namespace compiler | 349 } // namespace compiler |
331 } // namespace internal | 350 } // namespace internal |
332 } // namespace v8 | 351 } // namespace v8 |
OLD | NEW |