Mercurial > hg > truffle
annotate src/share/vm/opto/callGenerator.cpp @ 17716:cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | de95063c0e34 |
children | 45467c53f178 |
rev | line source |
---|---|
0 | 1 /* |
17467
55fb97c4c58d
8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
mikael
parents:
13081
diff
changeset
|
2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1265
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1265
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1265
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "ci/bcEscapeAnalyzer.hpp" | |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
27 #include "ci/ciCallSite.hpp" |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
28 #include "ci/ciObjArray.hpp" |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
29 #include "ci/ciMemberName.hpp" |
1972 | 30 #include "ci/ciMethodHandle.hpp" |
31 #include "classfile/javaClasses.hpp" | |
32 #include "compiler/compileLog.hpp" | |
33 #include "opto/addnode.hpp" | |
34 #include "opto/callGenerator.hpp" | |
35 #include "opto/callnode.hpp" | |
36 #include "opto/cfgnode.hpp" | |
37 #include "opto/connode.hpp" | |
38 #include "opto/parse.hpp" | |
39 #include "opto/rootnode.hpp" | |
40 #include "opto/runtime.hpp" | |
41 #include "opto/subnode.hpp" | |
0 | 42 |
43 | |
44 // Utility function. | |
45 const TypeFunc* CallGenerator::tf() const { | |
46 return TypeFunc::make(method()); | |
47 } | |
48 | |
49 //-----------------------------ParseGenerator--------------------------------- | |
50 // Internal class which handles all direct bytecode traversal. | |
51 class ParseGenerator : public InlineCallGenerator { | |
52 private: | |
53 bool _is_osr; | |
54 float _expected_uses; | |
55 | |
56 public: | |
57 ParseGenerator(ciMethod* method, float expected_uses, bool is_osr = false) | |
58 : InlineCallGenerator(method) | |
59 { | |
60 _is_osr = is_osr; | |
61 _expected_uses = expected_uses; | |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3894
diff
changeset
|
62 assert(InlineTree::check_can_parse(method) == NULL, "parse must be possible"); |
0 | 63 } |
64 | |
65 virtual bool is_parse() const { return true; } | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
66 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser); |
0 | 67 int is_osr() { return _is_osr; } |
68 | |
69 }; | |
70 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
71 JVMState* ParseGenerator::generate(JVMState* jvms, Parse* parent_parser) { |
0 | 72 Compile* C = Compile::current(); |
73 | |
74 if (is_osr()) { | |
75 // The JVMS for a OSR has a single argument (see its TypeFunc). | |
76 assert(jvms->depth() == 1, "no inline OSR"); | |
77 } | |
78 | |
79 if (C->failing()) { | |
80 return NULL; // bailing out of the compile; do not try to parse | |
81 } | |
82 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
83 Parse parser(jvms, method(), _expected_uses, parent_parser); |
0 | 84 // Grab signature for matching/allocation |
85 #ifdef ASSERT | |
86 if (parser.tf() != (parser.depth() == 1 ? C->tf() : tf())) { | |
87 MutexLockerEx ml(Compile_lock, Mutex::_no_safepoint_check_flag); | |
88 assert(C->env()->system_dictionary_modification_counter_changed(), | |
89 "Must invalidate if TypeFuncs differ"); | |
90 } | |
91 #endif | |
92 | |
93 GraphKit& exits = parser.exits(); | |
94 | |
95 if (C->failing()) { | |
96 while (exits.pop_exception_state() != NULL) ; | |
97 return NULL; | |
98 } | |
99 | |
100 assert(exits.jvms()->same_calls_as(jvms), "sanity"); | |
101 | |
102 // Simply return the exit state of the parser, | |
103 // augmented by any exceptional states. | |
104 return exits.transfer_exceptions_into_jvms(); | |
105 } | |
106 | |
107 //---------------------------DirectCallGenerator------------------------------ | |
108 // Internal class which handles all out-of-line calls w/o receiver type checks. | |
109 class DirectCallGenerator : public CallGenerator { | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
110 private: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
111 CallStaticJavaNode* _call_node; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
112 // Force separate memory and I/O projections for the exceptional |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
113 // paths to facilitate late inlinig. |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
114 bool _separate_io_proj; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
115 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
116 public: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
117 DirectCallGenerator(ciMethod* method, bool separate_io_proj) |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
118 : CallGenerator(method), |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
119 _separate_io_proj(separate_io_proj) |
0 | 120 { |
121 } | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
122 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser); |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
123 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
124 CallStaticJavaNode* call_node() const { return _call_node; } |
0 | 125 }; |
126 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
127 JVMState* DirectCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { |
0 | 128 GraphKit kit(jvms); |
129 bool is_static = method()->is_static(); | |
130 address target = is_static ? SharedRuntime::get_resolve_static_call_stub() | |
131 : SharedRuntime::get_resolve_opt_virtual_call_stub(); | |
132 | |
133 if (kit.C->log() != NULL) { | |
134 kit.C->log()->elem("direct_call bci='%d'", jvms->bci()); | |
135 } | |
136 | |
10278 | 137 CallStaticJavaNode *call = new (kit.C) CallStaticJavaNode(kit.C, tf(), target, method(), kit.bci()); |
6042
847da049d62f
7162094: LateInlineCallGenerator::do_late_inline crashed on uninitialized _call_node
never
parents:
4117
diff
changeset
|
138 _call_node = call; // Save the call node in case we need it later |
0 | 139 if (!is_static) { |
140 // Make an explicit receiver null_check as part of this call. | |
141 // Since we share a map with the caller, his JVMS gets adjusted. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
142 kit.null_check_receiver_before_call(method()); |
0 | 143 if (kit.stopped()) { |
144 // And dump it back to the caller, decorated with any exceptions: | |
145 return kit.transfer_exceptions_into_jvms(); | |
146 } | |
147 // Mark the call node as virtual, sort of: | |
148 call->set_optimized_virtual(true); | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
149 if (method()->is_method_handle_intrinsic() || |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
150 method()->is_compiled_lambda_form()) { |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
151 call->set_method_handle_invoke(true); |
1265 | 152 } |
0 | 153 } |
154 kit.set_arguments_for_java_call(call); | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
155 kit.set_edges_for_java_call(call, false, _separate_io_proj); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
156 Node* ret = kit.set_results_for_java_call(call, _separate_io_proj); |
0 | 157 kit.push_node(method()->return_type()->basic_type(), ret); |
158 return kit.transfer_exceptions_into_jvms(); | |
159 } | |
160 | |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
161 //--------------------------VirtualCallGenerator------------------------------ |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
162 // Internal class which handles all out-of-line calls checking receiver type. |
0 | 163 class VirtualCallGenerator : public CallGenerator { |
164 private: | |
165 int _vtable_index; | |
166 public: | |
167 VirtualCallGenerator(ciMethod* method, int vtable_index) | |
168 : CallGenerator(method), _vtable_index(vtable_index) | |
169 { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
170 assert(vtable_index == Method::invalid_vtable_index || |
0 | 171 vtable_index >= 0, "either invalid or usable"); |
172 } | |
173 virtual bool is_virtual() const { return true; } | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
174 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser); |
0 | 175 }; |
176 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
177 JVMState* VirtualCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { |
0 | 178 GraphKit kit(jvms); |
179 Node* receiver = kit.argument(0); | |
180 | |
181 if (kit.C->log() != NULL) { | |
182 kit.C->log()->elem("virtual_call bci='%d'", jvms->bci()); | |
183 } | |
184 | |
185 // If the receiver is a constant null, do not torture the system | |
186 // by attempting to call through it. The compile will proceed | |
187 // correctly, but may bail out in final_graph_reshaping, because | |
188 // the call instruction will have a seemingly deficient out-count. | |
189 // (The bailout says something misleading about an "infinite loop".) | |
190 if (kit.gvn().type(receiver)->higher_equal(TypePtr::NULL_PTR)) { | |
191 kit.inc_sp(method()->arg_size()); // restore arguments | |
192 kit.uncommon_trap(Deoptimization::Reason_null_check, | |
193 Deoptimization::Action_none, | |
194 NULL, "null receiver"); | |
195 return kit.transfer_exceptions_into_jvms(); | |
196 } | |
197 | |
198 // Ideally we would unconditionally do a null check here and let it | |
199 // be converted to an implicit check based on profile information. | |
200 // However currently the conversion to implicit null checks in | |
201 // Block::implicit_null_check() only looks for loads and stores, not calls. | |
202 ciMethod *caller = kit.method(); | |
203 ciMethodData *caller_md = (caller == NULL) ? NULL : caller->method_data(); | |
204 if (!UseInlineCaches || !ImplicitNullChecks || | |
205 ((ImplicitNullCheckThreshold > 0) && caller_md && | |
206 (caller_md->trap_count(Deoptimization::Reason_null_check) | |
207 >= (uint)ImplicitNullCheckThreshold))) { | |
208 // Make an explicit receiver null_check as part of this call. | |
209 // Since we share a map with the caller, his JVMS gets adjusted. | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
210 receiver = kit.null_check_receiver_before_call(method()); |
0 | 211 if (kit.stopped()) { |
212 // And dump it back to the caller, decorated with any exceptions: | |
213 return kit.transfer_exceptions_into_jvms(); | |
214 } | |
215 } | |
216 | |
217 assert(!method()->is_static(), "virtual call must not be to static"); | |
218 assert(!method()->is_final(), "virtual call should not be to final"); | |
219 assert(!method()->is_private(), "virtual call should not be to private"); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
220 assert(_vtable_index == Method::invalid_vtable_index || !UseInlineCaches, |
0 | 221 "no vtable calls if +UseInlineCaches "); |
222 address target = SharedRuntime::get_resolve_virtual_call_stub(); | |
223 // Normal inline cache used for call | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
224 CallDynamicJavaNode *call = new (kit.C) CallDynamicJavaNode(tf(), target, method(), _vtable_index, kit.bci()); |
0 | 225 kit.set_arguments_for_java_call(call); |
226 kit.set_edges_for_java_call(call); | |
227 Node* ret = kit.set_results_for_java_call(call); | |
228 kit.push_node(method()->return_type()->basic_type(), ret); | |
229 | |
230 // Represent the effect of an implicit receiver null_check | |
231 // as part of this call. Since we share a map with the caller, | |
232 // his JVMS gets adjusted. | |
233 kit.cast_not_null(receiver); | |
234 return kit.transfer_exceptions_into_jvms(); | |
235 } | |
236 | |
237 CallGenerator* CallGenerator::for_inline(ciMethod* m, float expected_uses) { | |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3894
diff
changeset
|
238 if (InlineTree::check_can_parse(m) != NULL) return NULL; |
0 | 239 return new ParseGenerator(m, expected_uses); |
240 } | |
241 | |
242 // As a special case, the JVMS passed to this CallGenerator is | |
243 // for the method execution already in progress, not just the JVMS | |
244 // of the caller. Thus, this CallGenerator cannot be mixed with others! | |
245 CallGenerator* CallGenerator::for_osr(ciMethod* m, int osr_bci) { | |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3894
diff
changeset
|
246 if (InlineTree::check_can_parse(m) != NULL) return NULL; |
0 | 247 float past_uses = m->interpreter_invocation_count(); |
248 float expected_uses = past_uses; | |
249 return new ParseGenerator(m, expected_uses, true); | |
250 } | |
251 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
252 CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) { |
0 | 253 assert(!m->is_abstract(), "for_direct_call mismatch"); |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
254 return new DirectCallGenerator(m, separate_io_proj); |
0 | 255 } |
256 | |
257 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) { | |
258 assert(!m->is_static(), "for_virtual_call mismatch"); | |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
259 assert(!m->is_method_handle_intrinsic(), "should be a direct call"); |
0 | 260 return new VirtualCallGenerator(m, vtable_index); |
261 } | |
262 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
263 // Allow inlining decisions to be delayed |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
264 class LateInlineCallGenerator : public DirectCallGenerator { |
7473 | 265 protected: |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
266 CallGenerator* _inline_cg; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
267 |
7473 | 268 virtual bool do_late_inline_check(JVMState* jvms) { return true; } |
269 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
270 public: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
271 LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) : |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
272 DirectCallGenerator(method, true), _inline_cg(inline_cg) {} |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
273 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
274 virtual bool is_late_inline() const { return true; } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
275 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
276 // Convert the CallStaticJava into an inline |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
277 virtual void do_late_inline(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
278 |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
279 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7194
diff
changeset
|
280 Compile *C = Compile::current(); |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7194
diff
changeset
|
281 C->print_inlining_skip(this); |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7194
diff
changeset
|
282 |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
283 // Record that this call site should be revisited once the main |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
284 // parse is finished. |
7473 | 285 if (!is_mh_late_inline()) { |
286 C->add_late_inline(this); | |
287 } | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
288 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
289 // Emit the CallStaticJava and request separate projections so |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
290 // that the late inlining logic can distinguish between fall |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
291 // through and exceptional uses of the memory and io projections |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
292 // as is done for allocations and macro expansion. |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
293 return DirectCallGenerator::generate(jvms, parent_parser); |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
294 } |
7473 | 295 |
296 virtual void print_inlining_late(const char* msg) { | |
297 CallNode* call = call_node(); | |
298 Compile* C = Compile::current(); | |
299 C->print_inlining_insert(this); | |
300 C->print_inlining(method(), call->jvms()->depth()-1, call->jvms()->bci(), msg); | |
301 } | |
302 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
303 }; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
304 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
305 void LateInlineCallGenerator::do_late_inline() { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
306 // Can't inline it |
10278 | 307 CallStaticJavaNode* call = call_node(); |
308 if (call == NULL || call->outcnt() == 0 || | |
309 call->in(0) == NULL || call->in(0)->is_top()) { | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
310 return; |
7997
8bd61471a109
8007144: Incremental inlining mistakes some call sites for dead ones and doesn't inline them
roland
parents:
7478
diff
changeset
|
311 } |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
312 |
10278 | 313 const TypeTuple *r = call->tf()->domain(); |
7473 | 314 for (int i1 = 0; i1 < method()->arg_size(); i1++) { |
10278 | 315 if (call->in(TypeFunc::Parms + i1)->is_top() && r->field_at(TypeFunc::Parms + i1) != Type::HALF) { |
7473 | 316 assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing"); |
317 return; | |
318 } | |
319 } | |
320 | |
10278 | 321 if (call->in(TypeFunc::Memory)->is_top()) { |
7473 | 322 assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing"); |
323 return; | |
324 } | |
325 | |
10278 | 326 Compile* C = Compile::current(); |
327 // Remove inlined methods from Compiler's lists. | |
328 if (call->is_macro()) { | |
329 C->remove_macro_node(call); | |
330 } | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
331 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
332 // Make a clone of the JVMState that appropriate to use for driving a parse |
10278 | 333 JVMState* old_jvms = call->jvms(); |
334 JVMState* jvms = old_jvms->clone_shallow(C); | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
335 uint size = call->req(); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
336 SafePointNode* map = new (C) SafePointNode(size, jvms); |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
337 for (uint i1 = 0; i1 < size; i1++) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
338 map->init_req(i1, call->in(i1)); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
339 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
340 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
341 // Make sure the state is a MergeMem for parsing. |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
342 if (!map->in(TypeFunc::Memory)->is_MergeMem()) { |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7194
diff
changeset
|
343 Node* mem = MergeMemNode::make(C, map->in(TypeFunc::Memory)); |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7194
diff
changeset
|
344 C->initial_gvn()->set_type_bottom(mem); |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7194
diff
changeset
|
345 map->set_req(TypeFunc::Memory, mem); |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
346 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
347 |
10278 | 348 uint nargs = method()->arg_size(); |
349 // blow away old call arguments | |
350 Node* top = C->top(); | |
351 for (uint i1 = 0; i1 < nargs; i1++) { | |
352 map->set_req(TypeFunc::Parms + i1, top); | |
353 } | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
354 jvms->set_map(map); |
10278 | 355 |
356 // Make enough space in the expression stack to transfer | |
357 // the incoming arguments and return value. | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
358 map->ensure_stack(jvms, jvms->method()->max_stack()); |
10278 | 359 for (uint i1 = 0; i1 < nargs; i1++) { |
360 map->set_argument(jvms, i1, call->in(TypeFunc::Parms + i1)); | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
361 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
362 |
10278 | 363 // This check is done here because for_method_handle_inline() method |
364 // needs jvms for inlined state. | |
7473 | 365 if (!do_late_inline_check(jvms)) { |
366 map->disconnect_inputs(NULL, C); | |
367 return; | |
368 } | |
369 | |
7421
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7194
diff
changeset
|
370 C->print_inlining_insert(this); |
ad5dd04754ee
8005031: Some cleanup in c2 to prepare for incremental inlining support
roland
parents:
7194
diff
changeset
|
371 |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
372 CompileLog* log = C->log(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
373 if (log != NULL) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
374 log->head("late_inline method='%d'", log->identify(method())); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
375 JVMState* p = jvms; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
376 while (p != NULL) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
377 log->elem("jvms bci='%d' method='%d'", p->bci(), log->identify(p->method())); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
378 p = p->caller(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
379 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
380 log->tail("late_inline"); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
381 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
382 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
383 // Setup default node notes to be picked up by the inlining |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
384 Node_Notes* old_nn = C->default_node_notes(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
385 if (old_nn != NULL) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
386 Node_Notes* entry_nn = old_nn->clone(C); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
387 entry_nn->set_jvms(jvms); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
388 C->set_default_node_notes(entry_nn); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
389 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
390 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
391 // Now perform the inling using the synthesized JVMState |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
392 JVMState* new_jvms = _inline_cg->generate(jvms, NULL); |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
393 if (new_jvms == NULL) return; // no change |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
394 if (C->failing()) return; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
395 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
396 // Capture any exceptional control flow |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
397 GraphKit kit(new_jvms); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
398 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
399 // Find the result object |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
400 Node* result = C->top(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
401 int result_size = method()->return_type()->size(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
402 if (result_size != 0 && !kit.stopped()) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
403 result = (result_size == 1) ? kit.pop() : kit.pop_pair(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
404 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
405 |
7473 | 406 C->set_has_loops(C->has_loops() || _inline_cg->method()->has_loops()); |
407 C->env()->notice_inlined_method(_inline_cg->method()); | |
408 C->set_inlining_progress(true); | |
409 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
410 kit.replace_call(call, result); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
411 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
412 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
413 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
414 CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* inline_cg) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
415 return new LateInlineCallGenerator(method, inline_cg); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
416 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
417 |
7473 | 418 class LateInlineMHCallGenerator : public LateInlineCallGenerator { |
419 ciMethod* _caller; | |
420 int _attempt; | |
421 bool _input_not_const; | |
422 | |
423 virtual bool do_late_inline_check(JVMState* jvms); | |
424 virtual bool already_attempted() const { return _attempt > 0; } | |
425 | |
426 public: | |
427 LateInlineMHCallGenerator(ciMethod* caller, ciMethod* callee, bool input_not_const) : | |
428 LateInlineCallGenerator(callee, NULL), _caller(caller), _attempt(0), _input_not_const(input_not_const) {} | |
429 | |
430 virtual bool is_mh_late_inline() const { return true; } | |
431 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
432 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { |
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
433 JVMState* new_jvms = LateInlineCallGenerator::generate(jvms, parent_parser); |
7473 | 434 if (_input_not_const) { |
435 // inlining won't be possible so no need to enqueue right now. | |
436 call_node()->set_generator(this); | |
437 } else { | |
438 Compile::current()->add_late_inline(this); | |
439 } | |
440 return new_jvms; | |
441 } | |
442 | |
443 virtual void print_inlining_late(const char* msg) { | |
444 if (!_input_not_const) return; | |
445 LateInlineCallGenerator::print_inlining_late(msg); | |
446 } | |
447 }; | |
448 | |
449 bool LateInlineMHCallGenerator::do_late_inline_check(JVMState* jvms) { | |
450 | |
451 CallGenerator* cg = for_method_handle_inline(jvms, _caller, method(), _input_not_const); | |
452 | |
453 if (!_input_not_const) { | |
454 _attempt++; | |
455 } | |
456 | |
457 if (cg != NULL) { | |
458 assert(!cg->is_late_inline() && cg->is_inline(), "we're doing late inlining"); | |
459 _inline_cg = cg; | |
460 Compile::current()->dec_number_of_mh_late_inlines(); | |
461 return true; | |
462 } | |
463 | |
464 call_node()->set_generator(this); | |
465 return false; | |
466 } | |
467 | |
468 CallGenerator* CallGenerator::for_mh_late_inline(ciMethod* caller, ciMethod* callee, bool input_not_const) { | |
469 Compile::current()->inc_number_of_mh_late_inlines(); | |
470 CallGenerator* cg = new LateInlineMHCallGenerator(caller, callee, input_not_const); | |
471 return cg; | |
472 } | |
473 | |
474 class LateInlineStringCallGenerator : public LateInlineCallGenerator { | |
475 | |
476 public: | |
477 LateInlineStringCallGenerator(ciMethod* method, CallGenerator* inline_cg) : | |
478 LateInlineCallGenerator(method, inline_cg) {} | |
479 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
480 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { |
7473 | 481 Compile *C = Compile::current(); |
482 C->print_inlining_skip(this); | |
483 | |
484 C->add_string_late_inline(this); | |
485 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
486 JVMState* new_jvms = DirectCallGenerator::generate(jvms, parent_parser); |
7473 | 487 return new_jvms; |
488 } | |
12966 | 489 |
490 virtual bool is_string_late_inline() const { return true; } | |
7473 | 491 }; |
492 | |
493 CallGenerator* CallGenerator::for_string_late_inline(ciMethod* method, CallGenerator* inline_cg) { | |
494 return new LateInlineStringCallGenerator(method, inline_cg); | |
495 } | |
496 | |
10278 | 497 class LateInlineBoxingCallGenerator : public LateInlineCallGenerator { |
498 | |
499 public: | |
500 LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) : | |
501 LateInlineCallGenerator(method, inline_cg) {} | |
502 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
503 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) { |
10278 | 504 Compile *C = Compile::current(); |
505 C->print_inlining_skip(this); | |
506 | |
507 C->add_boxing_late_inline(this); | |
508 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
509 JVMState* new_jvms = DirectCallGenerator::generate(jvms, parent_parser); |
10278 | 510 return new_jvms; |
511 } | |
512 }; | |
513 | |
514 CallGenerator* CallGenerator::for_boxing_late_inline(ciMethod* method, CallGenerator* inline_cg) { | |
515 return new LateInlineBoxingCallGenerator(method, inline_cg); | |
516 } | |
0 | 517 |
518 //---------------------------WarmCallGenerator-------------------------------- | |
519 // Internal class which handles initial deferral of inlining decisions. | |
520 class WarmCallGenerator : public CallGenerator { | |
521 WarmCallInfo* _call_info; | |
522 CallGenerator* _if_cold; | |
523 CallGenerator* _if_hot; | |
524 bool _is_virtual; // caches virtuality of if_cold | |
525 bool _is_inline; // caches inline-ness of if_hot | |
526 | |
527 public: | |
528 WarmCallGenerator(WarmCallInfo* ci, | |
529 CallGenerator* if_cold, | |
530 CallGenerator* if_hot) | |
531 : CallGenerator(if_cold->method()) | |
532 { | |
533 assert(method() == if_hot->method(), "consistent choices"); | |
534 _call_info = ci; | |
535 _if_cold = if_cold; | |
536 _if_hot = if_hot; | |
537 _is_virtual = if_cold->is_virtual(); | |
538 _is_inline = if_hot->is_inline(); | |
539 } | |
540 | |
541 virtual bool is_inline() const { return _is_inline; } | |
542 virtual bool is_virtual() const { return _is_virtual; } | |
543 virtual bool is_deferred() const { return true; } | |
544 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
545 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser); |
0 | 546 }; |
547 | |
548 | |
549 CallGenerator* CallGenerator::for_warm_call(WarmCallInfo* ci, | |
550 CallGenerator* if_cold, | |
551 CallGenerator* if_hot) { | |
552 return new WarmCallGenerator(ci, if_cold, if_hot); | |
553 } | |
554 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
555 JVMState* WarmCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { |
0 | 556 Compile* C = Compile::current(); |
557 if (C->log() != NULL) { | |
558 C->log()->elem("warm_call bci='%d'", jvms->bci()); | |
559 } | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
560 jvms = _if_cold->generate(jvms, parent_parser); |
0 | 561 if (jvms != NULL) { |
562 Node* m = jvms->map()->control(); | |
563 if (m->is_CatchProj()) m = m->in(0); else m = C->top(); | |
564 if (m->is_Catch()) m = m->in(0); else m = C->top(); | |
565 if (m->is_Proj()) m = m->in(0); else m = C->top(); | |
566 if (m->is_CallJava()) { | |
567 _call_info->set_call(m->as_Call()); | |
568 _call_info->set_hot_cg(_if_hot); | |
569 #ifndef PRODUCT | |
570 if (PrintOpto || PrintOptoInlining) { | |
571 tty->print_cr("Queueing for warm inlining at bci %d:", jvms->bci()); | |
572 tty->print("WCI: "); | |
573 _call_info->print(); | |
574 } | |
575 #endif | |
576 _call_info->set_heat(_call_info->compute_heat()); | |
577 C->set_warm_calls(_call_info->insert_into(C->warm_calls())); | |
578 } | |
579 } | |
580 return jvms; | |
581 } | |
582 | |
583 void WarmCallInfo::make_hot() { | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
584 Unimplemented(); |
0 | 585 } |
586 | |
587 void WarmCallInfo::make_cold() { | |
588 // No action: Just dequeue. | |
589 } | |
590 | |
591 | |
592 //------------------------PredictedCallGenerator------------------------------ | |
593 // Internal class which handles all out-of-line calls checking receiver type. | |
594 class PredictedCallGenerator : public CallGenerator { | |
595 ciKlass* _predicted_receiver; | |
596 CallGenerator* _if_missed; | |
597 CallGenerator* _if_hit; | |
598 float _hit_prob; | |
599 | |
600 public: | |
601 PredictedCallGenerator(ciKlass* predicted_receiver, | |
602 CallGenerator* if_missed, | |
603 CallGenerator* if_hit, float hit_prob) | |
604 : CallGenerator(if_missed->method()) | |
605 { | |
606 // The call profile data may predict the hit_prob as extreme as 0 or 1. | |
607 // Remove the extremes values from the range. | |
608 if (hit_prob > PROB_MAX) hit_prob = PROB_MAX; | |
609 if (hit_prob < PROB_MIN) hit_prob = PROB_MIN; | |
610 | |
611 _predicted_receiver = predicted_receiver; | |
612 _if_missed = if_missed; | |
613 _if_hit = if_hit; | |
614 _hit_prob = hit_prob; | |
615 } | |
616 | |
617 virtual bool is_virtual() const { return true; } | |
618 virtual bool is_inline() const { return _if_hit->is_inline(); } | |
619 virtual bool is_deferred() const { return _if_hit->is_deferred(); } | |
620 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
621 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser); |
0 | 622 }; |
623 | |
624 | |
625 CallGenerator* CallGenerator::for_predicted_call(ciKlass* predicted_receiver, | |
626 CallGenerator* if_missed, | |
627 CallGenerator* if_hit, | |
628 float hit_prob) { | |
629 return new PredictedCallGenerator(predicted_receiver, if_missed, if_hit, hit_prob); | |
630 } | |
631 | |
632 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
633 JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { |
0 | 634 GraphKit kit(jvms); |
635 PhaseGVN& gvn = kit.gvn(); | |
636 // We need an explicit receiver null_check before checking its type. | |
637 // We share a map with the caller, so his JVMS gets adjusted. | |
638 Node* receiver = kit.argument(0); | |
639 | |
640 CompileLog* log = kit.C->log(); | |
641 if (log != NULL) { | |
642 log->elem("predicted_call bci='%d' klass='%d'", | |
643 jvms->bci(), log->identify(_predicted_receiver)); | |
644 } | |
645 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
646 receiver = kit.null_check_receiver_before_call(method()); |
0 | 647 if (kit.stopped()) { |
648 return kit.transfer_exceptions_into_jvms(); | |
649 } | |
650 | |
651 Node* exact_receiver = receiver; // will get updated in place... | |
652 Node* slow_ctl = kit.type_check_receiver(receiver, | |
653 _predicted_receiver, _hit_prob, | |
654 &exact_receiver); | |
655 | |
656 SafePointNode* slow_map = NULL; | |
657 JVMState* slow_jvms; | |
658 { PreserveJVMState pjvms(&kit); | |
659 kit.set_control(slow_ctl); | |
660 if (!kit.stopped()) { | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
661 slow_jvms = _if_missed->generate(kit.sync_jvms(), parent_parser); |
4117
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
662 if (kit.failing()) |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
663 return NULL; // might happen because of NodeCountInliningCutoff |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
664 assert(slow_jvms != NULL, "must be"); |
0 | 665 kit.add_exception_states_from(slow_jvms); |
666 kit.set_map(slow_jvms->map()); | |
667 if (!kit.stopped()) | |
668 slow_map = kit.stop(); | |
669 } | |
670 } | |
671 | |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
0
diff
changeset
|
672 if (kit.stopped()) { |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
0
diff
changeset
|
673 // Instance exactly does not matches the desired type. |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
0
diff
changeset
|
674 kit.set_jvms(slow_jvms); |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
0
diff
changeset
|
675 return kit.transfer_exceptions_into_jvms(); |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
0
diff
changeset
|
676 } |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
0
diff
changeset
|
677 |
0 | 678 // fall through if the instance exactly matches the desired type |
679 kit.replace_in_map(receiver, exact_receiver); | |
680 | |
681 // Make the hot call: | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
682 JVMState* new_jvms = _if_hit->generate(kit.sync_jvms(), parent_parser); |
0 | 683 if (new_jvms == NULL) { |
684 // Inline failed, so make a direct call. | |
685 assert(_if_hit->is_inline(), "must have been a failed inline"); | |
686 CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method()); | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
687 new_jvms = cg->generate(kit.sync_jvms(), parent_parser); |
0 | 688 } |
689 kit.add_exception_states_from(new_jvms); | |
690 kit.set_jvms(new_jvms); | |
691 | |
692 // Need to merge slow and fast? | |
693 if (slow_map == NULL) { | |
694 // The fast path is the only path remaining. | |
695 return kit.transfer_exceptions_into_jvms(); | |
696 } | |
697 | |
698 if (kit.stopped()) { | |
699 // Inlined method threw an exception, so it's just the slow path after all. | |
700 kit.set_jvms(slow_jvms); | |
701 return kit.transfer_exceptions_into_jvms(); | |
702 } | |
703 | |
704 // Finish the diamond. | |
705 kit.C->set_has_split_ifs(true); // Has chance for split-if optimization | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
706 RegionNode* region = new (kit.C) RegionNode(3); |
0 | 707 region->init_req(1, kit.control()); |
708 region->init_req(2, slow_map->control()); | |
709 kit.set_control(gvn.transform(region)); | |
710 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO); | |
711 iophi->set_req(2, slow_map->i_o()); | |
712 kit.set_i_o(gvn.transform(iophi)); | |
713 kit.merge_memory(slow_map->merged_memory(), region, 2); | |
714 uint tos = kit.jvms()->stkoff() + kit.sp(); | |
715 uint limit = slow_map->req(); | |
716 for (uint i = TypeFunc::Parms; i < limit; i++) { | |
717 // Skip unused stack slots; fast forward to monoff(); | |
718 if (i == tos) { | |
719 i = kit.jvms()->monoff(); | |
720 if( i >= limit ) break; | |
721 } | |
722 Node* m = kit.map()->in(i); | |
723 Node* n = slow_map->in(i); | |
724 if (m != n) { | |
17671
de95063c0e34
8027422: assert(_gvn.type(obj)->higher_equal(tjp)) failed: cast_up is no longer needed
roland
parents:
17467
diff
changeset
|
725 const Type* t = gvn.type(m)->meet_speculative(gvn.type(n)); |
0 | 726 Node* phi = PhiNode::make(region, m, t); |
727 phi->set_req(2, n); | |
728 kit.map()->set_req(i, gvn.transform(phi)); | |
729 } | |
730 } | |
731 return kit.transfer_exceptions_into_jvms(); | |
732 } | |
733 | |
734 | |
7473 | 735 CallGenerator* CallGenerator::for_method_handle_call(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool delayed_forbidden) { |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
736 assert(callee->is_method_handle_intrinsic() || |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
737 callee->is_compiled_lambda_form(), "for_method_handle_call mismatch"); |
7473 | 738 bool input_not_const; |
739 CallGenerator* cg = CallGenerator::for_method_handle_inline(jvms, caller, callee, input_not_const); | |
740 Compile* C = Compile::current(); | |
741 if (cg != NULL) { | |
742 if (!delayed_forbidden && AlwaysIncrementalInline) { | |
743 return CallGenerator::for_late_inline(callee, cg); | |
744 } else { | |
745 return cg; | |
746 } | |
747 } | |
748 int bci = jvms->bci(); | |
749 ciCallProfile profile = caller->call_profile_at_bci(bci); | |
750 int call_site_count = caller->scale_count(profile.count()); | |
751 | |
752 if (IncrementalInline && call_site_count > 0 && | |
753 (input_not_const || !C->inlining_incrementally() || C->over_inlining_cutoff())) { | |
754 return CallGenerator::for_mh_late_inline(caller, callee, input_not_const); | |
755 } else { | |
7478 | 756 // Out-of-line call. |
7473 | 757 return CallGenerator::for_direct_call(callee); |
758 } | |
4117
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
759 } |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
760 |
7473 | 761 CallGenerator* CallGenerator::for_method_handle_inline(JVMState* jvms, ciMethod* caller, ciMethod* callee, bool& input_not_const) { |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
762 GraphKit kit(jvms); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
763 PhaseGVN& gvn = kit.gvn(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
764 Compile* C = kit.C; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
765 vmIntrinsics::ID iid = callee->intrinsic_id(); |
7473 | 766 input_not_const = true; |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
767 switch (iid) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
768 case vmIntrinsics::_invokeBasic: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
769 { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
770 // Get MethodHandle receiver: |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
771 Node* receiver = kit.argument(0); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
772 if (receiver->Opcode() == Op_ConP) { |
7473 | 773 input_not_const = false; |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
774 const TypeOopPtr* oop_ptr = receiver->bottom_type()->is_oopptr(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
775 ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
776 guarantee(!target->is_method_handle_intrinsic(), "should not happen"); // XXX remove |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
6616
diff
changeset
|
777 const int vtable_index = Method::invalid_vtable_index; |
12966 | 778 CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, NULL, true, true); |
13081
e74074c34312
8028159: C2: compiler stack overflow during inlining of @ForceInline methods
vlivanov
parents:
12966
diff
changeset
|
779 assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
780 if (cg != NULL && cg->is_inline()) |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
781 return cg; |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
782 } |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
783 } |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
784 break; |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
785 |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
786 case vmIntrinsics::_linkToVirtual: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
787 case vmIntrinsics::_linkToStatic: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
788 case vmIntrinsics::_linkToSpecial: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
789 case vmIntrinsics::_linkToInterface: |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
790 { |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6894
diff
changeset
|
791 // Get MemberName argument: |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
792 Node* member_name = kit.argument(callee->arg_size() - 1); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
793 if (member_name->Opcode() == Op_ConP) { |
7473 | 794 input_not_const = false; |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
795 const TypeOopPtr* oop_ptr = member_name->bottom_type()->is_oopptr(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
796 ciMethod* target = oop_ptr->const_oop()->as_member_name()->get_vmtarget(); |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
797 |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
798 // In lamda forms we erase signature types to avoid resolving issues |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
799 // involving class loaders. When we optimize a method handle invoke |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
800 // to a direct call we must cast the receiver and arguments to its |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
801 // actual types. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
802 ciSignature* signature = target->signature(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
803 const int receiver_skip = target->is_static() ? 0 : 1; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
804 // Cast receiver to its type. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
805 if (!target->is_static()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
806 Node* arg = kit.argument(0); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
807 const TypeOopPtr* arg_type = arg->bottom_type()->isa_oopptr(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
808 const Type* sig_type = TypeOopPtr::make_from_klass(signature->accessing_klass()); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
809 if (arg_type != NULL && !arg_type->higher_equal(sig_type)) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
810 Node* cast_obj = gvn.transform(new (C) CheckCastPPNode(kit.control(), arg, sig_type)); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
811 kit.set_argument(0, cast_obj); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
812 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
813 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
814 // Cast reference arguments to its type. |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
815 for (int i = 0; i < signature->count(); i++) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
816 ciType* t = signature->type_at(i); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
817 if (t->is_klass()) { |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
818 Node* arg = kit.argument(receiver_skip + i); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
819 const TypeOopPtr* arg_type = arg->bottom_type()->isa_oopptr(); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
820 const Type* sig_type = TypeOopPtr::make_from_klass(t->as_klass()); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
821 if (arg_type != NULL && !arg_type->higher_equal(sig_type)) { |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
822 Node* cast_obj = gvn.transform(new (C) CheckCastPPNode(kit.control(), arg, sig_type)); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
823 kit.set_argument(receiver_skip + i, cast_obj); |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
824 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
825 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
826 } |
7478 | 827 |
828 // Try to get the most accurate receiver type | |
829 const bool is_virtual = (iid == vmIntrinsics::_linkToVirtual); | |
830 const bool is_virtual_or_interface = (is_virtual || iid == vmIntrinsics::_linkToInterface); | |
831 int vtable_index = Method::invalid_vtable_index; | |
832 bool call_does_dispatch = false; | |
833 | |
12966 | 834 ciKlass* speculative_receiver_type = NULL; |
7478 | 835 if (is_virtual_or_interface) { |
836 ciInstanceKlass* klass = target->holder(); | |
837 Node* receiver_node = kit.argument(0); | |
838 const TypeOopPtr* receiver_type = gvn.type(receiver_node)->isa_oopptr(); | |
839 // call_does_dispatch and vtable_index are out-parameters. They might be changed. | |
840 target = C->optimize_virtual_call(caller, jvms->bci(), klass, target, receiver_type, | |
841 is_virtual, | |
842 call_does_dispatch, vtable_index); // out-parameters | |
12966 | 843 // We lack profiling at this call but type speculation may |
844 // provide us with a type | |
845 speculative_receiver_type = receiver_type->speculative_type(); | |
7478 | 846 } |
847 | |
12966 | 848 CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, speculative_receiver_type, true, true); |
13081
e74074c34312
8028159: C2: compiler stack overflow during inlining of @ForceInline methods
vlivanov
parents:
12966
diff
changeset
|
849 assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here"); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
850 if (cg != NULL && cg->is_inline()) |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
851 return cg; |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
852 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
853 } |
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
854 break; |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
855 |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
856 default: |
6268
6c5b7a6becc8
7187454: stack overflow in C2 compiler thread on Solaris x86
kvn
parents:
6266
diff
changeset
|
857 fatal(err_msg_res("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid))); |
6266
1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
twisti
parents:
6182
diff
changeset
|
858 break; |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
859 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
860 return NULL; |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
861 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
862 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
863 |
6894 | 864 //------------------------PredictedIntrinsicGenerator------------------------------ |
865 // Internal class which handles all predicted Intrinsic calls. | |
866 class PredictedIntrinsicGenerator : public CallGenerator { | |
867 CallGenerator* _intrinsic; | |
868 CallGenerator* _cg; | |
869 | |
870 public: | |
871 PredictedIntrinsicGenerator(CallGenerator* intrinsic, | |
872 CallGenerator* cg) | |
873 : CallGenerator(cg->method()) | |
874 { | |
875 _intrinsic = intrinsic; | |
876 _cg = cg; | |
877 } | |
878 | |
879 virtual bool is_virtual() const { return true; } | |
880 virtual bool is_inlined() const { return true; } | |
881 virtual bool is_intrinsic() const { return true; } | |
882 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
883 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser); |
6894 | 884 }; |
885 | |
886 | |
887 CallGenerator* CallGenerator::for_predicted_intrinsic(CallGenerator* intrinsic, | |
888 CallGenerator* cg) { | |
889 return new PredictedIntrinsicGenerator(intrinsic, cg); | |
890 } | |
891 | |
892 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
893 JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms, Parse* parent_parser) { |
6894 | 894 GraphKit kit(jvms); |
895 PhaseGVN& gvn = kit.gvn(); | |
896 | |
897 CompileLog* log = kit.C->log(); | |
898 if (log != NULL) { | |
899 log->elem("predicted_intrinsic bci='%d' method='%d'", | |
900 jvms->bci(), log->identify(method())); | |
901 } | |
902 | |
903 Node* slow_ctl = _intrinsic->generate_predicate(kit.sync_jvms()); | |
904 if (kit.failing()) | |
905 return NULL; // might happen because of NodeCountInliningCutoff | |
906 | |
907 SafePointNode* slow_map = NULL; | |
908 JVMState* slow_jvms; | |
909 if (slow_ctl != NULL) { | |
910 PreserveJVMState pjvms(&kit); | |
911 kit.set_control(slow_ctl); | |
912 if (!kit.stopped()) { | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
913 slow_jvms = _cg->generate(kit.sync_jvms(), parent_parser); |
6894 | 914 if (kit.failing()) |
915 return NULL; // might happen because of NodeCountInliningCutoff | |
916 assert(slow_jvms != NULL, "must be"); | |
917 kit.add_exception_states_from(slow_jvms); | |
918 kit.set_map(slow_jvms->map()); | |
919 if (!kit.stopped()) | |
920 slow_map = kit.stop(); | |
921 } | |
922 } | |
923 | |
924 if (kit.stopped()) { | |
925 // Predicate is always false. | |
926 kit.set_jvms(slow_jvms); | |
927 return kit.transfer_exceptions_into_jvms(); | |
928 } | |
929 | |
930 // Generate intrinsic code: | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
931 JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms(), parent_parser); |
6894 | 932 if (new_jvms == NULL) { |
933 // Intrinsic failed, so use slow code or make a direct call. | |
934 if (slow_map == NULL) { | |
935 CallGenerator* cg = CallGenerator::for_direct_call(method()); | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
936 new_jvms = cg->generate(kit.sync_jvms(), parent_parser); |
6894 | 937 } else { |
938 kit.set_jvms(slow_jvms); | |
939 return kit.transfer_exceptions_into_jvms(); | |
940 } | |
941 } | |
942 kit.add_exception_states_from(new_jvms); | |
943 kit.set_jvms(new_jvms); | |
944 | |
945 // Need to merge slow and fast? | |
946 if (slow_map == NULL) { | |
947 // The fast path is the only path remaining. | |
948 return kit.transfer_exceptions_into_jvms(); | |
949 } | |
950 | |
951 if (kit.stopped()) { | |
952 // Intrinsic method threw an exception, so it's just the slow path after all. | |
953 kit.set_jvms(slow_jvms); | |
954 return kit.transfer_exceptions_into_jvms(); | |
955 } | |
956 | |
957 // Finish the diamond. | |
958 kit.C->set_has_split_ifs(true); // Has chance for split-if optimization | |
959 RegionNode* region = new (kit.C) RegionNode(3); | |
960 region->init_req(1, kit.control()); | |
961 region->init_req(2, slow_map->control()); | |
962 kit.set_control(gvn.transform(region)); | |
963 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO); | |
964 iophi->set_req(2, slow_map->i_o()); | |
965 kit.set_i_o(gvn.transform(iophi)); | |
966 kit.merge_memory(slow_map->merged_memory(), region, 2); | |
967 uint tos = kit.jvms()->stkoff() + kit.sp(); | |
968 uint limit = slow_map->req(); | |
969 for (uint i = TypeFunc::Parms; i < limit; i++) { | |
970 // Skip unused stack slots; fast forward to monoff(); | |
971 if (i == tos) { | |
972 i = kit.jvms()->monoff(); | |
973 if( i >= limit ) break; | |
974 } | |
975 Node* m = kit.map()->in(i); | |
976 Node* n = slow_map->in(i); | |
977 if (m != n) { | |
17671
de95063c0e34
8027422: assert(_gvn.type(obj)->higher_equal(tjp)) failed: cast_up is no longer needed
roland
parents:
17467
diff
changeset
|
978 const Type* t = gvn.type(m)->meet_speculative(gvn.type(n)); |
6894 | 979 Node* phi = PhiNode::make(region, m, t); |
980 phi->set_req(2, n); | |
981 kit.map()->set_req(i, gvn.transform(phi)); | |
982 } | |
983 } | |
984 return kit.transfer_exceptions_into_jvms(); | |
985 } | |
986 | |
0 | 987 //-------------------------UncommonTrapCallGenerator----------------------------- |
988 // Internal class which handles all out-of-line calls checking receiver type. | |
989 class UncommonTrapCallGenerator : public CallGenerator { | |
990 Deoptimization::DeoptReason _reason; | |
991 Deoptimization::DeoptAction _action; | |
992 | |
993 public: | |
994 UncommonTrapCallGenerator(ciMethod* m, | |
995 Deoptimization::DeoptReason reason, | |
996 Deoptimization::DeoptAction action) | |
997 : CallGenerator(m) | |
998 { | |
999 _reason = reason; | |
1000 _action = action; | |
1001 } | |
1002 | |
1003 virtual bool is_virtual() const { ShouldNotReachHere(); return false; } | |
1004 virtual bool is_trap() const { return true; } | |
1005 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
1006 virtual JVMState* generate(JVMState* jvms, Parse* parent_parser); |
0 | 1007 }; |
1008 | |
1009 | |
1010 CallGenerator* | |
1011 CallGenerator::for_uncommon_trap(ciMethod* m, | |
1012 Deoptimization::DeoptReason reason, | |
1013 Deoptimization::DeoptAction action) { | |
1014 return new UncommonTrapCallGenerator(m, reason, action); | |
1015 } | |
1016 | |
1017 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
1018 JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms, Parse* parent_parser) { |
0 | 1019 GraphKit kit(jvms); |
1020 // Take the trap with arguments pushed on the stack. (Cf. null_check_receiver). | |
1021 int nargs = method()->arg_size(); | |
1022 kit.inc_sp(nargs); | |
1023 assert(nargs <= kit.sp() && kit.sp() <= jvms->stk_size(), "sane sp w/ args pushed"); | |
1024 if (_reason == Deoptimization::Reason_class_check && | |
1025 _action == Deoptimization::Action_maybe_recompile) { | |
1026 // Temp fix for 6529811 | |
1027 // Don't allow uncommon_trap to override our decision to recompile in the event | |
1028 // of a class cast failure for a monomorphic call as it will never let us convert | |
1029 // the call to either bi-morphic or megamorphic and can lead to unc-trap loops | |
1030 bool keep_exact_action = true; | |
1031 kit.uncommon_trap(_reason, _action, NULL, "monomorphic vcall checkcast", false, keep_exact_action); | |
1032 } else { | |
1033 kit.uncommon_trap(_reason, _action); | |
1034 } | |
1035 return kit.transfer_exceptions_into_jvms(); | |
1036 } | |
1037 | |
1038 // (Note: Moved hook_up_call to GraphKit::set_edges_for_java_call.) | |
1039 | |
1040 // (Node: Merged hook_up_exits into ParseGenerator::generate.) | |
1041 | |
1042 #define NODES_OVERHEAD_PER_METHOD (30.0) | |
1043 #define NODES_PER_BYTECODE (9.5) | |
1044 | |
1045 void WarmCallInfo::init(JVMState* call_site, ciMethod* call_method, ciCallProfile& profile, float prof_factor) { | |
1046 int call_count = profile.count(); | |
1047 int code_size = call_method->code_size(); | |
1048 | |
1049 // Expected execution count is based on the historical count: | |
1050 _count = call_count < 0 ? 1 : call_site->method()->scale_count(call_count, prof_factor); | |
1051 | |
1052 // Expected profit from inlining, in units of simple call-overheads. | |
1053 _profit = 1.0; | |
1054 | |
1055 // Expected work performed by the call in units of call-overheads. | |
1056 // %%% need an empirical curve fit for "work" (time in call) | |
1057 float bytecodes_per_call = 3; | |
1058 _work = 1.0 + code_size / bytecodes_per_call; | |
1059 | |
1060 // Expected size of compilation graph: | |
1061 // -XX:+PrintParseStatistics once reported: | |
1062 // Methods seen: 9184 Methods parsed: 9184 Nodes created: 1582391 | |
1063 // Histogram of 144298 parsed bytecodes: | |
1064 // %%% Need an better predictor for graph size. | |
1065 _size = NODES_OVERHEAD_PER_METHOD + (NODES_PER_BYTECODE * code_size); | |
1066 } | |
1067 | |
1068 // is_cold: Return true if the node should never be inlined. | |
1069 // This is true if any of the key metrics are extreme. | |
1070 bool WarmCallInfo::is_cold() const { | |
1071 if (count() < WarmCallMinCount) return true; | |
1072 if (profit() < WarmCallMinProfit) return true; | |
1073 if (work() > WarmCallMaxWork) return true; | |
1074 if (size() > WarmCallMaxSize) return true; | |
1075 return false; | |
1076 } | |
1077 | |
1078 // is_hot: Return true if the node should be inlined immediately. | |
1079 // This is true if any of the key metrics are extreme. | |
1080 bool WarmCallInfo::is_hot() const { | |
1081 assert(!is_cold(), "eliminate is_cold cases before testing is_hot"); | |
1082 if (count() >= HotCallCountThreshold) return true; | |
1083 if (profit() >= HotCallProfitThreshold) return true; | |
1084 if (work() <= HotCallTrivialWork) return true; | |
1085 if (size() <= HotCallTrivialSize) return true; | |
1086 return false; | |
1087 } | |
1088 | |
1089 // compute_heat: | |
1090 float WarmCallInfo::compute_heat() const { | |
1091 assert(!is_cold(), "compute heat only on warm nodes"); | |
1092 assert(!is_hot(), "compute heat only on warm nodes"); | |
1093 int min_size = MAX2(0, (int)HotCallTrivialSize); | |
1094 int max_size = MIN2(500, (int)WarmCallMaxSize); | |
1095 float method_size = (size() - min_size) / MAX2(1, max_size - min_size); | |
1096 float size_factor; | |
1097 if (method_size < 0.05) size_factor = 4; // 2 sigmas better than avg. | |
1098 else if (method_size < 0.15) size_factor = 2; // 1 sigma better than avg. | |
1099 else if (method_size < 0.5) size_factor = 1; // better than avg. | |
1100 else size_factor = 0.5; // worse than avg. | |
1101 return (count() * profit() * size_factor); | |
1102 } | |
1103 | |
1104 bool WarmCallInfo::warmer_than(WarmCallInfo* that) { | |
1105 assert(this != that, "compare only different WCIs"); | |
1106 assert(this->heat() != 0 && that->heat() != 0, "call compute_heat 1st"); | |
1107 if (this->heat() > that->heat()) return true; | |
1108 if (this->heat() < that->heat()) return false; | |
1109 assert(this->heat() == that->heat(), "no NaN heat allowed"); | |
1110 // Equal heat. Break the tie some other way. | |
1111 if (!this->call() || !that->call()) return (address)this > (address)that; | |
1112 return this->call()->_idx > that->call()->_idx; | |
1113 } | |
1114 | |
1115 //#define UNINIT_NEXT ((WarmCallInfo*)badAddress) | |
1116 #define UNINIT_NEXT ((WarmCallInfo*)NULL) | |
1117 | |
1118 WarmCallInfo* WarmCallInfo::insert_into(WarmCallInfo* head) { | |
1119 assert(next() == UNINIT_NEXT, "not yet on any list"); | |
1120 WarmCallInfo* prev_p = NULL; | |
1121 WarmCallInfo* next_p = head; | |
1122 while (next_p != NULL && next_p->warmer_than(this)) { | |
1123 prev_p = next_p; | |
1124 next_p = prev_p->next(); | |
1125 } | |
1126 // Install this between prev_p and next_p. | |
1127 this->set_next(next_p); | |
1128 if (prev_p == NULL) | |
1129 head = this; | |
1130 else | |
1131 prev_p->set_next(this); | |
1132 return head; | |
1133 } | |
1134 | |
1135 WarmCallInfo* WarmCallInfo::remove_from(WarmCallInfo* head) { | |
1136 WarmCallInfo* prev_p = NULL; | |
1137 WarmCallInfo* next_p = head; | |
1138 while (next_p != this) { | |
1139 assert(next_p != NULL, "this must be in the list somewhere"); | |
1140 prev_p = next_p; | |
1141 next_p = prev_p->next(); | |
1142 } | |
1143 next_p = this->next(); | |
1144 debug_only(this->set_next(UNINIT_NEXT)); | |
1145 // Remove this from between prev_p and next_p. | |
1146 if (prev_p == NULL) | |
1147 head = next_p; | |
1148 else | |
1149 prev_p->set_next(next_p); | |
1150 return head; | |
1151 } | |
1152 | |
2443
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1153 WarmCallInfo WarmCallInfo::_always_hot(WarmCallInfo::MAX_VALUE(), WarmCallInfo::MAX_VALUE(), |
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1154 WarmCallInfo::MIN_VALUE(), WarmCallInfo::MIN_VALUE()); |
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1155 WarmCallInfo WarmCallInfo::_always_cold(WarmCallInfo::MIN_VALUE(), WarmCallInfo::MIN_VALUE(), |
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1156 WarmCallInfo::MAX_VALUE(), WarmCallInfo::MAX_VALUE()); |
0 | 1157 |
1158 WarmCallInfo* WarmCallInfo::always_hot() { | |
2443
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1159 assert(_always_hot.is_hot(), "must always be hot"); |
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1160 return &_always_hot; |
0 | 1161 } |
1162 | |
1163 WarmCallInfo* WarmCallInfo::always_cold() { | |
2443
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1164 assert(_always_cold.is_cold(), "must always be cold"); |
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1165 return &_always_cold; |
0 | 1166 } |
1167 | |
1168 | |
1169 #ifndef PRODUCT | |
1170 | |
1171 void WarmCallInfo::print() const { | |
1172 tty->print("%s : C=%6.1f P=%6.1f W=%6.1f S=%6.1f H=%6.1f -> %p", | |
1173 is_cold() ? "cold" : is_hot() ? "hot " : "warm", | |
1174 count(), profit(), work(), size(), compute_heat(), next()); | |
1175 tty->cr(); | |
1176 if (call() != NULL) call()->dump(); | |
1177 } | |
1178 | |
1179 void print_wci(WarmCallInfo* ci) { | |
1180 ci->print(); | |
1181 } | |
1182 | |
1183 void WarmCallInfo::print_all() const { | |
1184 for (const WarmCallInfo* p = this; p != NULL; p = p->next()) | |
1185 p->print(); | |
1186 } | |
1187 | |
1188 int WarmCallInfo::count_all() const { | |
1189 int cnt = 0; | |
1190 for (const WarmCallInfo* p = this; p != NULL; p = p->next()) | |
1191 cnt++; | |
1192 return cnt; | |
1193 } | |
1194 | |
1195 #endif //PRODUCT |