Mercurial > hg > graal-compiler
annotate src/share/vm/opto/callGenerator.cpp @ 3992:d1bdeef3e3e2
7098282: G1: assert(interval >= 0) failed: Sanity check, referencePolicy.cpp: 76
Summary: There is a race between one thread successfully forwarding and copying the klass mirror for the SoftReference class (including the static master clock) and another thread attempting to use the master clock while attempting to discover a soft reference object. Maintain a shadow copy of the soft reference master clock and use the shadow during reference discovery and reference processing.
Reviewed-by: tonyp, brutisso, ysr
author | johnc |
---|---|
date | Wed, 12 Oct 2011 10:25:51 -0700 |
parents | c26de9aef2ed |
children | 83d0b5cd1438 |
rev | line source |
---|---|
0 | 1 /* |
2357
8033953d67ff
7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents:
1972
diff
changeset
|
2 * Copyright (c) 2000, 2011, 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" |
1972 | 28 #include "ci/ciCPCache.hpp" |
29 #include "ci/ciMethodHandle.hpp" | |
30 #include "classfile/javaClasses.hpp" | |
31 #include "compiler/compileLog.hpp" | |
32 #include "opto/addnode.hpp" | |
33 #include "opto/callGenerator.hpp" | |
34 #include "opto/callnode.hpp" | |
35 #include "opto/cfgnode.hpp" | |
36 #include "opto/connode.hpp" | |
37 #include "opto/parse.hpp" | |
38 #include "opto/rootnode.hpp" | |
39 #include "opto/runtime.hpp" | |
40 #include "opto/subnode.hpp" | |
0 | 41 |
42 CallGenerator::CallGenerator(ciMethod* method) { | |
43 _method = method; | |
44 } | |
45 | |
46 // Utility function. | |
47 const TypeFunc* CallGenerator::tf() const { | |
48 return TypeFunc::make(method()); | |
49 } | |
50 | |
51 //-----------------------------ParseGenerator--------------------------------- | |
52 // Internal class which handles all direct bytecode traversal. | |
53 class ParseGenerator : public InlineCallGenerator { | |
54 private: | |
55 bool _is_osr; | |
56 float _expected_uses; | |
57 | |
58 public: | |
59 ParseGenerator(ciMethod* method, float expected_uses, bool is_osr = false) | |
60 : InlineCallGenerator(method) | |
61 { | |
62 _is_osr = is_osr; | |
63 _expected_uses = expected_uses; | |
3900
a32de5085326
7079673: JSR 292: C1 should inline bytecoded method handle adapters
twisti
parents:
3894
diff
changeset
|
64 assert(InlineTree::check_can_parse(method) == NULL, "parse must be possible"); |
0 | 65 } |
66 | |
67 virtual bool is_parse() const { return true; } | |
68 virtual JVMState* generate(JVMState* jvms); | |
69 int is_osr() { return _is_osr; } | |
70 | |
71 }; | |
72 | |
73 JVMState* ParseGenerator::generate(JVMState* jvms) { | |
74 Compile* C = Compile::current(); | |
75 | |
76 if (is_osr()) { | |
77 // The JVMS for a OSR has a single argument (see its TypeFunc). | |
78 assert(jvms->depth() == 1, "no inline OSR"); | |
79 } | |
80 | |
81 if (C->failing()) { | |
82 return NULL; // bailing out of the compile; do not try to parse | |
83 } | |
84 | |
85 Parse parser(jvms, method(), _expected_uses); | |
86 // Grab signature for matching/allocation | |
87 #ifdef ASSERT | |
88 if (parser.tf() != (parser.depth() == 1 ? C->tf() : tf())) { | |
89 MutexLockerEx ml(Compile_lock, Mutex::_no_safepoint_check_flag); | |
90 assert(C->env()->system_dictionary_modification_counter_changed(), | |
91 "Must invalidate if TypeFuncs differ"); | |
92 } | |
93 #endif | |
94 | |
95 GraphKit& exits = parser.exits(); | |
96 | |
97 if (C->failing()) { | |
98 while (exits.pop_exception_state() != NULL) ; | |
99 return NULL; | |
100 } | |
101 | |
102 assert(exits.jvms()->same_calls_as(jvms), "sanity"); | |
103 | |
104 // Simply return the exit state of the parser, | |
105 // augmented by any exceptional states. | |
106 return exits.transfer_exceptions_into_jvms(); | |
107 } | |
108 | |
109 //---------------------------DirectCallGenerator------------------------------ | |
110 // Internal class which handles all out-of-line calls w/o receiver type checks. | |
111 class DirectCallGenerator : public CallGenerator { | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
112 private: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
113 CallStaticJavaNode* _call_node; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
114 // Force separate memory and I/O projections for the exceptional |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
115 // paths to facilitate late inlinig. |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
116 bool _separate_io_proj; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
117 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
118 public: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
119 DirectCallGenerator(ciMethod* method, bool separate_io_proj) |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
120 : CallGenerator(method), |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
121 _separate_io_proj(separate_io_proj) |
0 | 122 { |
123 } | |
124 virtual JVMState* generate(JVMState* jvms); | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
125 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
126 CallStaticJavaNode* call_node() const { return _call_node; } |
0 | 127 }; |
128 | |
129 JVMState* DirectCallGenerator::generate(JVMState* jvms) { | |
130 GraphKit kit(jvms); | |
131 bool is_static = method()->is_static(); | |
132 address target = is_static ? SharedRuntime::get_resolve_static_call_stub() | |
133 : SharedRuntime::get_resolve_opt_virtual_call_stub(); | |
134 | |
135 if (kit.C->log() != NULL) { | |
136 kit.C->log()->elem("direct_call bci='%d'", jvms->bci()); | |
137 } | |
138 | |
139 CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), target, method(), kit.bci()); | |
140 if (!is_static) { | |
141 // Make an explicit receiver null_check as part of this call. | |
142 // Since we share a map with the caller, his JVMS gets adjusted. | |
143 kit.null_check_receiver(method()); | |
144 if (kit.stopped()) { | |
145 // And dump it back to the caller, decorated with any exceptions: | |
146 return kit.transfer_exceptions_into_jvms(); | |
147 } | |
148 // Mark the call node as virtual, sort of: | |
149 call->set_optimized_virtual(true); | |
1265 | 150 if (method()->is_method_handle_invoke()) { |
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); |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
158 _call_node = call; // Save the call node in case we need it later |
0 | 159 return kit.transfer_exceptions_into_jvms(); |
160 } | |
161 | |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
162 //---------------------------DynamicCallGenerator----------------------------- |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
163 // Internal class which handles all out-of-line invokedynamic calls. |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
164 class DynamicCallGenerator : public CallGenerator { |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
165 public: |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
166 DynamicCallGenerator(ciMethod* method) |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
167 : CallGenerator(method) |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
168 { |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
169 } |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
170 virtual JVMState* generate(JVMState* jvms); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
171 }; |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
172 |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
173 JVMState* DynamicCallGenerator::generate(JVMState* jvms) { |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
174 GraphKit kit(jvms); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
175 |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
176 if (kit.C->log() != NULL) { |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
177 kit.C->log()->elem("dynamic_call bci='%d'", jvms->bci()); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
178 } |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
179 |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
180 // Get the constant pool cache from the caller class. |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
181 ciMethod* caller_method = jvms->method(); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
182 ciBytecodeStream str(caller_method); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
183 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
184 assert(str.cur_bc() == Bytecodes::_invokedynamic, "wrong place to issue a dynamic call!"); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
185 ciCPCache* cpcache = str.get_cpcache(); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
186 |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
187 // Get the offset of the CallSite from the constant pool cache |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
188 // pointer. |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
189 int index = str.get_method_index(); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
190 size_t call_site_offset = cpcache->get_f1_offset(index); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
191 |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
192 // Load the CallSite object from the constant pool cache. |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
193 const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
194 Node* cpcache_adr = kit.makecon(cpcache_ptr); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
195 Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
196 Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
197 |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
198 // Load the target MethodHandle from the CallSite object. |
2357
8033953d67ff
7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents:
1972
diff
changeset
|
199 Node* target_mh_adr = kit.basic_plus_adr(call_site, call_site, java_lang_invoke_CallSite::target_offset_in_bytes()); |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
200 Node* target_mh = kit.make_load(kit.control(), target_mh_adr, TypeInstPtr::BOTTOM, T_OBJECT); |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
201 |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
202 address resolve_stub = SharedRuntime::get_resolve_opt_virtual_call_stub(); |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
203 |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
204 CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), resolve_stub, method(), kit.bci()); |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
205 // invokedynamic is treated as an optimized invokevirtual. |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
206 call->set_optimized_virtual(true); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
207 // Take extra care (in the presence of argument motion) not to trash the SP: |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
208 call->set_method_handle_invoke(true); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
209 |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
210 // Pass the target MethodHandle as first argument and shift the |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
211 // other arguments. |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
212 call->init_req(0 + TypeFunc::Parms, target_mh); |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
213 uint nargs = call->method()->arg_size(); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
214 for (uint i = 1; i < nargs; i++) { |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
215 Node* arg = kit.argument(i - 1); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
216 call->init_req(i + TypeFunc::Parms, arg); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
217 } |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
218 |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
219 kit.set_edges_for_java_call(call); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
220 Node* ret = kit.set_results_for_java_call(call); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
221 kit.push_node(method()->return_type()->basic_type(), ret); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
222 return kit.transfer_exceptions_into_jvms(); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
223 } |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
224 |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
225 //--------------------------VirtualCallGenerator------------------------------ |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
226 // Internal class which handles all out-of-line calls checking receiver type. |
0 | 227 class VirtualCallGenerator : public CallGenerator { |
228 private: | |
229 int _vtable_index; | |
230 public: | |
231 VirtualCallGenerator(ciMethod* method, int vtable_index) | |
232 : CallGenerator(method), _vtable_index(vtable_index) | |
233 { | |
234 assert(vtable_index == methodOopDesc::invalid_vtable_index || | |
235 vtable_index >= 0, "either invalid or usable"); | |
236 } | |
237 virtual bool is_virtual() const { return true; } | |
238 virtual JVMState* generate(JVMState* jvms); | |
239 }; | |
240 | |
241 JVMState* VirtualCallGenerator::generate(JVMState* jvms) { | |
242 GraphKit kit(jvms); | |
243 Node* receiver = kit.argument(0); | |
244 | |
245 if (kit.C->log() != NULL) { | |
246 kit.C->log()->elem("virtual_call bci='%d'", jvms->bci()); | |
247 } | |
248 | |
249 // If the receiver is a constant null, do not torture the system | |
250 // by attempting to call through it. The compile will proceed | |
251 // correctly, but may bail out in final_graph_reshaping, because | |
252 // the call instruction will have a seemingly deficient out-count. | |
253 // (The bailout says something misleading about an "infinite loop".) | |
254 if (kit.gvn().type(receiver)->higher_equal(TypePtr::NULL_PTR)) { | |
255 kit.inc_sp(method()->arg_size()); // restore arguments | |
256 kit.uncommon_trap(Deoptimization::Reason_null_check, | |
257 Deoptimization::Action_none, | |
258 NULL, "null receiver"); | |
259 return kit.transfer_exceptions_into_jvms(); | |
260 } | |
261 | |
262 // Ideally we would unconditionally do a null check here and let it | |
263 // be converted to an implicit check based on profile information. | |
264 // However currently the conversion to implicit null checks in | |
265 // Block::implicit_null_check() only looks for loads and stores, not calls. | |
266 ciMethod *caller = kit.method(); | |
267 ciMethodData *caller_md = (caller == NULL) ? NULL : caller->method_data(); | |
268 if (!UseInlineCaches || !ImplicitNullChecks || | |
269 ((ImplicitNullCheckThreshold > 0) && caller_md && | |
270 (caller_md->trap_count(Deoptimization::Reason_null_check) | |
271 >= (uint)ImplicitNullCheckThreshold))) { | |
272 // Make an explicit receiver null_check as part of this call. | |
273 // Since we share a map with the caller, his JVMS gets adjusted. | |
274 receiver = kit.null_check_receiver(method()); | |
275 if (kit.stopped()) { | |
276 // And dump it back to the caller, decorated with any exceptions: | |
277 return kit.transfer_exceptions_into_jvms(); | |
278 } | |
279 } | |
280 | |
281 assert(!method()->is_static(), "virtual call must not be to static"); | |
282 assert(!method()->is_final(), "virtual call should not be to final"); | |
283 assert(!method()->is_private(), "virtual call should not be to private"); | |
284 assert(_vtable_index == methodOopDesc::invalid_vtable_index || !UseInlineCaches, | |
285 "no vtable calls if +UseInlineCaches "); | |
286 address target = SharedRuntime::get_resolve_virtual_call_stub(); | |
287 // Normal inline cache used for call | |
288 CallDynamicJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallDynamicJavaNode(tf(), target, method(), _vtable_index, kit.bci()); | |
289 kit.set_arguments_for_java_call(call); | |
290 kit.set_edges_for_java_call(call); | |
291 Node* ret = kit.set_results_for_java_call(call); | |
292 kit.push_node(method()->return_type()->basic_type(), ret); | |
293 | |
294 // Represent the effect of an implicit receiver null_check | |
295 // as part of this call. Since we share a map with the caller, | |
296 // his JVMS gets adjusted. | |
297 kit.cast_not_null(receiver); | |
298 return kit.transfer_exceptions_into_jvms(); | |
299 } | |
300 | |
301 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
|
302 if (InlineTree::check_can_parse(m) != NULL) return NULL; |
0 | 303 return new ParseGenerator(m, expected_uses); |
304 } | |
305 | |
306 // As a special case, the JVMS passed to this CallGenerator is | |
307 // for the method execution already in progress, not just the JVMS | |
308 // of the caller. Thus, this CallGenerator cannot be mixed with others! | |
309 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
|
310 if (InlineTree::check_can_parse(m) != NULL) return NULL; |
0 | 311 float past_uses = m->interpreter_invocation_count(); |
312 float expected_uses = past_uses; | |
313 return new ParseGenerator(m, expected_uses, true); | |
314 } | |
315 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
316 CallGenerator* CallGenerator::for_direct_call(ciMethod* m, bool separate_io_proj) { |
0 | 317 assert(!m->is_abstract(), "for_direct_call mismatch"); |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
318 return new DirectCallGenerator(m, separate_io_proj); |
0 | 319 } |
320 | |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
321 CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) { |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
322 assert(m->is_method_handle_invoke() || m->is_method_handle_adapter(), "for_dynamic_call mismatch"); |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
323 return new DynamicCallGenerator(m); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
324 } |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
325 |
0 | 326 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) { |
327 assert(!m->is_static(), "for_virtual_call mismatch"); | |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
328 assert(!m->is_method_handle_invoke(), "should be a direct call"); |
0 | 329 return new VirtualCallGenerator(m, vtable_index); |
330 } | |
331 | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
332 // Allow inlining decisions to be delayed |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
333 class LateInlineCallGenerator : public DirectCallGenerator { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
334 CallGenerator* _inline_cg; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
335 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
336 public: |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
337 LateInlineCallGenerator(ciMethod* method, CallGenerator* inline_cg) : |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
338 DirectCallGenerator(method, true), _inline_cg(inline_cg) {} |
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 virtual bool is_late_inline() const { return true; } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
341 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
342 // Convert the CallStaticJava into an inline |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
343 virtual void do_late_inline(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
344 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
345 JVMState* generate(JVMState* jvms) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
346 // Record that this call site should be revisited once the main |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
347 // parse is finished. |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
348 Compile::current()->add_late_inline(this); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
349 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
350 // Emit the CallStaticJava and request separate projections so |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
351 // that the late inlining logic can distinguish between fall |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
352 // through and exceptional uses of the memory and io projections |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
353 // as is done for allocations and macro expansion. |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
354 return DirectCallGenerator::generate(jvms); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
355 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
356 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
357 }; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
358 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
359 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
360 void LateInlineCallGenerator::do_late_inline() { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
361 // Can't inline it |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
362 if (call_node() == NULL || call_node()->outcnt() == 0 || |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
363 call_node()->in(0) == NULL || call_node()->in(0)->is_top()) |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
364 return; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
365 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
366 CallStaticJavaNode* call = call_node(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
367 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
368 // Make a clone of the JVMState that appropriate to use for driving a parse |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
369 Compile* C = Compile::current(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
370 JVMState* jvms = call->jvms()->clone_shallow(C); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
371 uint size = call->req(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
372 SafePointNode* map = new (C, size) SafePointNode(size, jvms); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
373 for (uint i1 = 0; i1 < size; i1++) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
374 map->init_req(i1, call->in(i1)); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
375 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
376 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
377 // Make sure the state is a MergeMem for parsing. |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
378 if (!map->in(TypeFunc::Memory)->is_MergeMem()) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
379 map->set_req(TypeFunc::Memory, MergeMemNode::make(C, map->in(TypeFunc::Memory))); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
380 } |
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 // Make enough space for the expression stack and transfer the incoming arguments |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
383 int nargs = method()->arg_size(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
384 jvms->set_map(map); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
385 map->ensure_stack(jvms, jvms->method()->max_stack()); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
386 if (nargs > 0) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
387 for (int i1 = 0; i1 < nargs; i1++) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
388 map->set_req(i1 + jvms->argoff(), call->in(TypeFunc::Parms + i1)); |
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 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
392 CompileLog* log = C->log(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
393 if (log != NULL) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
394 log->head("late_inline method='%d'", log->identify(method())); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
395 JVMState* p = jvms; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
396 while (p != NULL) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
397 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
|
398 p = p->caller(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
399 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
400 log->tail("late_inline"); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
401 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
402 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
403 // Setup default node notes to be picked up by the inlining |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
404 Node_Notes* old_nn = C->default_node_notes(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
405 if (old_nn != NULL) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
406 Node_Notes* entry_nn = old_nn->clone(C); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
407 entry_nn->set_jvms(jvms); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
408 C->set_default_node_notes(entry_nn); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
409 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
410 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
411 // Now perform the inling using the synthesized JVMState |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
412 JVMState* new_jvms = _inline_cg->generate(jvms); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
413 if (new_jvms == NULL) return; // no change |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
414 if (C->failing()) return; |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
415 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
416 // Capture any exceptional control flow |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
417 GraphKit kit(new_jvms); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
418 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
419 // Find the result object |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
420 Node* result = C->top(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
421 int result_size = method()->return_type()->size(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
422 if (result_size != 0 && !kit.stopped()) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
423 result = (result_size == 1) ? kit.pop() : kit.pop_pair(); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
424 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
425 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
426 kit.replace_call(call, result); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
427 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
428 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
429 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
430 CallGenerator* CallGenerator::for_late_inline(ciMethod* method, CallGenerator* inline_cg) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
431 return new LateInlineCallGenerator(method, inline_cg); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
432 } |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
433 |
0 | 434 |
435 //---------------------------WarmCallGenerator-------------------------------- | |
436 // Internal class which handles initial deferral of inlining decisions. | |
437 class WarmCallGenerator : public CallGenerator { | |
438 WarmCallInfo* _call_info; | |
439 CallGenerator* _if_cold; | |
440 CallGenerator* _if_hot; | |
441 bool _is_virtual; // caches virtuality of if_cold | |
442 bool _is_inline; // caches inline-ness of if_hot | |
443 | |
444 public: | |
445 WarmCallGenerator(WarmCallInfo* ci, | |
446 CallGenerator* if_cold, | |
447 CallGenerator* if_hot) | |
448 : CallGenerator(if_cold->method()) | |
449 { | |
450 assert(method() == if_hot->method(), "consistent choices"); | |
451 _call_info = ci; | |
452 _if_cold = if_cold; | |
453 _if_hot = if_hot; | |
454 _is_virtual = if_cold->is_virtual(); | |
455 _is_inline = if_hot->is_inline(); | |
456 } | |
457 | |
458 virtual bool is_inline() const { return _is_inline; } | |
459 virtual bool is_virtual() const { return _is_virtual; } | |
460 virtual bool is_deferred() const { return true; } | |
461 | |
462 virtual JVMState* generate(JVMState* jvms); | |
463 }; | |
464 | |
465 | |
466 CallGenerator* CallGenerator::for_warm_call(WarmCallInfo* ci, | |
467 CallGenerator* if_cold, | |
468 CallGenerator* if_hot) { | |
469 return new WarmCallGenerator(ci, if_cold, if_hot); | |
470 } | |
471 | |
472 JVMState* WarmCallGenerator::generate(JVMState* jvms) { | |
473 Compile* C = Compile::current(); | |
474 if (C->log() != NULL) { | |
475 C->log()->elem("warm_call bci='%d'", jvms->bci()); | |
476 } | |
477 jvms = _if_cold->generate(jvms); | |
478 if (jvms != NULL) { | |
479 Node* m = jvms->map()->control(); | |
480 if (m->is_CatchProj()) m = m->in(0); else m = C->top(); | |
481 if (m->is_Catch()) m = m->in(0); else m = C->top(); | |
482 if (m->is_Proj()) m = m->in(0); else m = C->top(); | |
483 if (m->is_CallJava()) { | |
484 _call_info->set_call(m->as_Call()); | |
485 _call_info->set_hot_cg(_if_hot); | |
486 #ifndef PRODUCT | |
487 if (PrintOpto || PrintOptoInlining) { | |
488 tty->print_cr("Queueing for warm inlining at bci %d:", jvms->bci()); | |
489 tty->print("WCI: "); | |
490 _call_info->print(); | |
491 } | |
492 #endif | |
493 _call_info->set_heat(_call_info->compute_heat()); | |
494 C->set_warm_calls(_call_info->insert_into(C->warm_calls())); | |
495 } | |
496 } | |
497 return jvms; | |
498 } | |
499 | |
500 void WarmCallInfo::make_hot() { | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
337
diff
changeset
|
501 Unimplemented(); |
0 | 502 } |
503 | |
504 void WarmCallInfo::make_cold() { | |
505 // No action: Just dequeue. | |
506 } | |
507 | |
508 | |
509 //------------------------PredictedCallGenerator------------------------------ | |
510 // Internal class which handles all out-of-line calls checking receiver type. | |
511 class PredictedCallGenerator : public CallGenerator { | |
512 ciKlass* _predicted_receiver; | |
513 CallGenerator* _if_missed; | |
514 CallGenerator* _if_hit; | |
515 float _hit_prob; | |
516 | |
517 public: | |
518 PredictedCallGenerator(ciKlass* predicted_receiver, | |
519 CallGenerator* if_missed, | |
520 CallGenerator* if_hit, float hit_prob) | |
521 : CallGenerator(if_missed->method()) | |
522 { | |
523 // The call profile data may predict the hit_prob as extreme as 0 or 1. | |
524 // Remove the extremes values from the range. | |
525 if (hit_prob > PROB_MAX) hit_prob = PROB_MAX; | |
526 if (hit_prob < PROB_MIN) hit_prob = PROB_MIN; | |
527 | |
528 _predicted_receiver = predicted_receiver; | |
529 _if_missed = if_missed; | |
530 _if_hit = if_hit; | |
531 _hit_prob = hit_prob; | |
532 } | |
533 | |
534 virtual bool is_virtual() const { return true; } | |
535 virtual bool is_inline() const { return _if_hit->is_inline(); } | |
536 virtual bool is_deferred() const { return _if_hit->is_deferred(); } | |
537 | |
538 virtual JVMState* generate(JVMState* jvms); | |
539 }; | |
540 | |
541 | |
542 CallGenerator* CallGenerator::for_predicted_call(ciKlass* predicted_receiver, | |
543 CallGenerator* if_missed, | |
544 CallGenerator* if_hit, | |
545 float hit_prob) { | |
546 return new PredictedCallGenerator(predicted_receiver, if_missed, if_hit, hit_prob); | |
547 } | |
548 | |
549 | |
550 JVMState* PredictedCallGenerator::generate(JVMState* jvms) { | |
551 GraphKit kit(jvms); | |
552 PhaseGVN& gvn = kit.gvn(); | |
553 // We need an explicit receiver null_check before checking its type. | |
554 // We share a map with the caller, so his JVMS gets adjusted. | |
555 Node* receiver = kit.argument(0); | |
556 | |
557 CompileLog* log = kit.C->log(); | |
558 if (log != NULL) { | |
559 log->elem("predicted_call bci='%d' klass='%d'", | |
560 jvms->bci(), log->identify(_predicted_receiver)); | |
561 } | |
562 | |
563 receiver = kit.null_check_receiver(method()); | |
564 if (kit.stopped()) { | |
565 return kit.transfer_exceptions_into_jvms(); | |
566 } | |
567 | |
568 Node* exact_receiver = receiver; // will get updated in place... | |
569 Node* slow_ctl = kit.type_check_receiver(receiver, | |
570 _predicted_receiver, _hit_prob, | |
571 &exact_receiver); | |
572 | |
573 SafePointNode* slow_map = NULL; | |
574 JVMState* slow_jvms; | |
575 { PreserveJVMState pjvms(&kit); | |
576 kit.set_control(slow_ctl); | |
577 if (!kit.stopped()) { | |
578 slow_jvms = _if_missed->generate(kit.sync_jvms()); | |
579 assert(slow_jvms != NULL, "miss path must not fail to generate"); | |
580 kit.add_exception_states_from(slow_jvms); | |
581 kit.set_map(slow_jvms->map()); | |
582 if (!kit.stopped()) | |
583 slow_map = kit.stop(); | |
584 } | |
585 } | |
586 | |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
0
diff
changeset
|
587 if (kit.stopped()) { |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
0
diff
changeset
|
588 // 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
|
589 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
|
590 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
|
591 } |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
0
diff
changeset
|
592 |
0 | 593 // fall through if the instance exactly matches the desired type |
594 kit.replace_in_map(receiver, exact_receiver); | |
595 | |
596 // Make the hot call: | |
597 JVMState* new_jvms = _if_hit->generate(kit.sync_jvms()); | |
598 if (new_jvms == NULL) { | |
599 // Inline failed, so make a direct call. | |
600 assert(_if_hit->is_inline(), "must have been a failed inline"); | |
601 CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method()); | |
602 new_jvms = cg->generate(kit.sync_jvms()); | |
603 } | |
604 kit.add_exception_states_from(new_jvms); | |
605 kit.set_jvms(new_jvms); | |
606 | |
607 // Need to merge slow and fast? | |
608 if (slow_map == NULL) { | |
609 // The fast path is the only path remaining. | |
610 return kit.transfer_exceptions_into_jvms(); | |
611 } | |
612 | |
613 if (kit.stopped()) { | |
614 // Inlined method threw an exception, so it's just the slow path after all. | |
615 kit.set_jvms(slow_jvms); | |
616 return kit.transfer_exceptions_into_jvms(); | |
617 } | |
618 | |
619 // Finish the diamond. | |
620 kit.C->set_has_split_ifs(true); // Has chance for split-if optimization | |
621 RegionNode* region = new (kit.C, 3) RegionNode(3); | |
622 region->init_req(1, kit.control()); | |
623 region->init_req(2, slow_map->control()); | |
624 kit.set_control(gvn.transform(region)); | |
625 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO); | |
626 iophi->set_req(2, slow_map->i_o()); | |
627 kit.set_i_o(gvn.transform(iophi)); | |
628 kit.merge_memory(slow_map->merged_memory(), region, 2); | |
629 uint tos = kit.jvms()->stkoff() + kit.sp(); | |
630 uint limit = slow_map->req(); | |
631 for (uint i = TypeFunc::Parms; i < limit; i++) { | |
632 // Skip unused stack slots; fast forward to monoff(); | |
633 if (i == tos) { | |
634 i = kit.jvms()->monoff(); | |
635 if( i >= limit ) break; | |
636 } | |
637 Node* m = kit.map()->in(i); | |
638 Node* n = slow_map->in(i); | |
639 if (m != n) { | |
640 const Type* t = gvn.type(m)->meet(gvn.type(n)); | |
641 Node* phi = PhiNode::make(region, m, t); | |
642 phi->set_req(2, n); | |
643 kit.map()->set_req(i, gvn.transform(phi)); | |
644 } | |
645 } | |
646 return kit.transfer_exceptions_into_jvms(); | |
647 } | |
648 | |
649 | |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
650 //------------------------PredictedDynamicCallGenerator----------------------- |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
651 // Internal class which handles all out-of-line calls checking receiver type. |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
652 class PredictedDynamicCallGenerator : public CallGenerator { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
653 ciMethodHandle* _predicted_method_handle; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
654 CallGenerator* _if_missed; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
655 CallGenerator* _if_hit; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
656 float _hit_prob; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
657 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
658 public: |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
659 PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle, |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
660 CallGenerator* if_missed, |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
661 CallGenerator* if_hit, |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
662 float hit_prob) |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
663 : CallGenerator(if_missed->method()), |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
664 _predicted_method_handle(predicted_method_handle), |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
665 _if_missed(if_missed), |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
666 _if_hit(if_hit), |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
667 _hit_prob(hit_prob) |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
668 {} |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
669 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
670 virtual bool is_inline() const { return _if_hit->is_inline(); } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
671 virtual bool is_deferred() const { return _if_hit->is_deferred(); } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
672 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
673 virtual JVMState* generate(JVMState* jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
674 }; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
675 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
676 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
677 CallGenerator* CallGenerator::for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle, |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
678 CallGenerator* if_missed, |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
679 CallGenerator* if_hit, |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
680 float hit_prob) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
681 return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
682 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
683 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
684 |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
685 CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMState* jvms, |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
686 ciMethod* caller, ciMethod* callee, ciCallProfile profile) { |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
687 if (method_handle->Opcode() == Op_ConP) { |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
688 const TypeOopPtr* oop_ptr = method_handle->bottom_type()->is_oopptr(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
689 ciObject* const_oop = oop_ptr->const_oop(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
690 ciMethodHandle* method_handle = const_oop->as_method_handle(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
691 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
692 // Set the callee to have access to the class and signature in |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
693 // the MethodHandleCompiler. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
694 method_handle->set_callee(callee); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
695 method_handle->set_caller(caller); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
696 method_handle->set_call_profile(profile); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
697 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
698 // Get an adapter for the MethodHandle. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
699 ciMethod* target_method = method_handle->get_method_handle_adapter(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
700 if (target_method != NULL) { |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
701 CallGenerator* cg = Compile::current()->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS); |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
702 if (cg != NULL && cg->is_inline()) |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
703 return cg; |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
704 } |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
705 } else if (method_handle->Opcode() == Op_Phi && method_handle->req() == 3 && |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
706 method_handle->in(1)->Opcode() == Op_ConP && method_handle->in(2)->Opcode() == Op_ConP) { |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
707 float prob = PROB_FAIR; |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
708 Node* meth_region = method_handle->in(0); |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
709 if (meth_region->is_Region() && |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
710 meth_region->in(1)->is_Proj() && meth_region->in(2)->is_Proj() && |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
711 meth_region->in(1)->in(0) == meth_region->in(2)->in(0) && |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
712 meth_region->in(1)->in(0)->is_If()) { |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
713 // If diamond, so grab the probability of the test to drive the inlining below |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
714 prob = meth_region->in(1)->in(0)->as_If()->_prob; |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
715 if (meth_region->in(1)->is_IfTrue()) { |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
716 prob = 1 - prob; |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
717 } |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
718 } |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
719 |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
720 // selectAlternative idiom merging two constant MethodHandles. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
721 // Generate a guard so that each can be inlined. We might want to |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
722 // do more inputs at later point but this gets the most common |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
723 // case. |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
724 CallGenerator* cg1 = for_method_handle_inline(method_handle->in(1), jvms, caller, callee, profile.rescale(1.0 - prob)); |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
725 CallGenerator* cg2 = for_method_handle_inline(method_handle->in(2), jvms, caller, callee, profile.rescale(prob)); |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
726 if (cg1 != NULL && cg2 != NULL) { |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
727 const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr(); |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
728 ciObject* const_oop = oop_ptr->const_oop(); |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
729 ciMethodHandle* mh = const_oop->as_method_handle(); |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
730 return new PredictedDynamicCallGenerator(mh, cg2, cg1, prob); |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
731 } |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
732 } |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
733 return NULL; |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
734 } |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
735 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
736 |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
737 CallGenerator* CallGenerator::for_invokedynamic_inline(ciCallSite* call_site, JVMState* jvms, |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
738 ciMethod* caller, ciMethod* callee, ciCallProfile profile) { |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
739 ciMethodHandle* method_handle = call_site->get_target(); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
740 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
741 // Set the callee to have access to the class and signature in the |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
742 // MethodHandleCompiler. |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
743 method_handle->set_callee(callee); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
744 method_handle->set_caller(caller); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
745 method_handle->set_call_profile(profile); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
746 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
747 // Get an adapter for the MethodHandle. |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
748 ciMethod* target_method = method_handle->get_invokedynamic_adapter(); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
749 if (target_method != NULL) { |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
750 Compile *C = Compile::current(); |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
751 CallGenerator* cg = C->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS); |
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
752 if (cg != NULL && cg->is_inline()) { |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
753 // Add a dependence for invalidation of the optimization. |
3901
aa67216400d3
7085404: JSR 292: VolatileCallSites should have push notification too
twisti
parents:
3900
diff
changeset
|
754 if (!call_site->is_constant_call_site()) { |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
755 C->dependencies()->assert_call_site_target_value(call_site, method_handle); |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
756 } |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
757 return cg; |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
758 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
759 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
760 return NULL; |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
761 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
762 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
763 |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
764 JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
765 GraphKit kit(jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
766 PhaseGVN& gvn = kit.gvn(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
767 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
768 CompileLog* log = kit.C->log(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
769 if (log != NULL) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
770 log->elem("predicted_dynamic_call bci='%d'", jvms->bci()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
771 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
772 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
773 const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle, true); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
774 Node* predicted_mh = kit.makecon(predicted_mh_ptr); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
775 |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
776 Node* bol = NULL; |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
777 int bc = jvms->method()->java_code_at_bci(jvms->bci()); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
778 if (bc == Bytecodes::_invokespecial) { |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
779 // This is the selectAlternative idiom for guardWithTest |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
780 Node* receiver = kit.argument(0); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
781 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
782 // Check if the MethodHandle is the expected one |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
783 Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(receiver, predicted_mh)); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
784 bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) ); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
785 } else { |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
786 assert(bc == Bytecodes::_invokedynamic, "must be"); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
787 // Get the constant pool cache from the caller class. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
788 ciMethod* caller_method = jvms->method(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
789 ciBytecodeStream str(caller_method); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
790 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
791 ciCPCache* cpcache = str.get_cpcache(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
792 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
793 // Get the offset of the CallSite from the constant pool cache |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
794 // pointer. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
795 int index = str.get_method_index(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
796 size_t call_site_offset = cpcache->get_f1_offset(index); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
797 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
798 // Load the CallSite object from the constant pool cache. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
799 const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
800 Node* cpcache_adr = kit.makecon(cpcache_ptr); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
801 Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
802 Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
803 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
804 // Load the target MethodHandle from the CallSite object. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
805 Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_lang_invoke_CallSite::target_offset_in_bytes()); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
806 Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
807 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
808 // Check if the MethodHandle is still the same. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
809 Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh)); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
810 bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) ); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
811 } |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
812 IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
813 kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff))); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
814 Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff)); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
815 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
816 SafePointNode* slow_map = NULL; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
817 JVMState* slow_jvms; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
818 { PreserveJVMState pjvms(&kit); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
819 kit.set_control(slow_ctl); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
820 if (!kit.stopped()) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
821 slow_jvms = _if_missed->generate(kit.sync_jvms()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
822 assert(slow_jvms != NULL, "miss path must not fail to generate"); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
823 kit.add_exception_states_from(slow_jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
824 kit.set_map(slow_jvms->map()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
825 if (!kit.stopped()) |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
826 slow_map = kit.stop(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
827 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
828 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
829 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
830 if (kit.stopped()) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
831 // Instance exactly does not matches the desired type. |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
832 kit.set_jvms(slow_jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
833 return kit.transfer_exceptions_into_jvms(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
834 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
835 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
836 // Make the hot call: |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
837 JVMState* new_jvms = _if_hit->generate(kit.sync_jvms()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
838 if (new_jvms == NULL) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
839 // Inline failed, so make a direct call. |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
840 assert(_if_hit->is_inline(), "must have been a failed inline"); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
841 CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
842 new_jvms = cg->generate(kit.sync_jvms()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
843 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
844 kit.add_exception_states_from(new_jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
845 kit.set_jvms(new_jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
846 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
847 // Need to merge slow and fast? |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
848 if (slow_map == NULL) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
849 // The fast path is the only path remaining. |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
850 return kit.transfer_exceptions_into_jvms(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
851 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
852 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
853 if (kit.stopped()) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
854 // Inlined method threw an exception, so it's just the slow path after all. |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
855 kit.set_jvms(slow_jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
856 return kit.transfer_exceptions_into_jvms(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
857 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
858 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
859 // Finish the diamond. |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
860 kit.C->set_has_split_ifs(true); // Has chance for split-if optimization |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
861 RegionNode* region = new (kit.C, 3) RegionNode(3); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
862 region->init_req(1, kit.control()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
863 region->init_req(2, slow_map->control()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
864 kit.set_control(gvn.transform(region)); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
865 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
866 iophi->set_req(2, slow_map->i_o()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
867 kit.set_i_o(gvn.transform(iophi)); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
868 kit.merge_memory(slow_map->merged_memory(), region, 2); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
869 uint tos = kit.jvms()->stkoff() + kit.sp(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
870 uint limit = slow_map->req(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
871 for (uint i = TypeFunc::Parms; i < limit; i++) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
872 // Skip unused stack slots; fast forward to monoff(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
873 if (i == tos) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
874 i = kit.jvms()->monoff(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
875 if( i >= limit ) break; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
876 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
877 Node* m = kit.map()->in(i); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
878 Node* n = slow_map->in(i); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
879 if (m != n) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
880 const Type* t = gvn.type(m)->meet(gvn.type(n)); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
881 Node* phi = PhiNode::make(region, m, t); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
882 phi->set_req(2, n); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
883 kit.map()->set_req(i, gvn.transform(phi)); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
884 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
885 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
886 return kit.transfer_exceptions_into_jvms(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
887 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
888 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
889 |
0 | 890 //-------------------------UncommonTrapCallGenerator----------------------------- |
891 // Internal class which handles all out-of-line calls checking receiver type. | |
892 class UncommonTrapCallGenerator : public CallGenerator { | |
893 Deoptimization::DeoptReason _reason; | |
894 Deoptimization::DeoptAction _action; | |
895 | |
896 public: | |
897 UncommonTrapCallGenerator(ciMethod* m, | |
898 Deoptimization::DeoptReason reason, | |
899 Deoptimization::DeoptAction action) | |
900 : CallGenerator(m) | |
901 { | |
902 _reason = reason; | |
903 _action = action; | |
904 } | |
905 | |
906 virtual bool is_virtual() const { ShouldNotReachHere(); return false; } | |
907 virtual bool is_trap() const { return true; } | |
908 | |
909 virtual JVMState* generate(JVMState* jvms); | |
910 }; | |
911 | |
912 | |
913 CallGenerator* | |
914 CallGenerator::for_uncommon_trap(ciMethod* m, | |
915 Deoptimization::DeoptReason reason, | |
916 Deoptimization::DeoptAction action) { | |
917 return new UncommonTrapCallGenerator(m, reason, action); | |
918 } | |
919 | |
920 | |
921 JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms) { | |
922 GraphKit kit(jvms); | |
923 // Take the trap with arguments pushed on the stack. (Cf. null_check_receiver). | |
924 int nargs = method()->arg_size(); | |
925 kit.inc_sp(nargs); | |
926 assert(nargs <= kit.sp() && kit.sp() <= jvms->stk_size(), "sane sp w/ args pushed"); | |
927 if (_reason == Deoptimization::Reason_class_check && | |
928 _action == Deoptimization::Action_maybe_recompile) { | |
929 // Temp fix for 6529811 | |
930 // Don't allow uncommon_trap to override our decision to recompile in the event | |
931 // of a class cast failure for a monomorphic call as it will never let us convert | |
932 // the call to either bi-morphic or megamorphic and can lead to unc-trap loops | |
933 bool keep_exact_action = true; | |
934 kit.uncommon_trap(_reason, _action, NULL, "monomorphic vcall checkcast", false, keep_exact_action); | |
935 } else { | |
936 kit.uncommon_trap(_reason, _action); | |
937 } | |
938 return kit.transfer_exceptions_into_jvms(); | |
939 } | |
940 | |
941 // (Note: Moved hook_up_call to GraphKit::set_edges_for_java_call.) | |
942 | |
943 // (Node: Merged hook_up_exits into ParseGenerator::generate.) | |
944 | |
945 #define NODES_OVERHEAD_PER_METHOD (30.0) | |
946 #define NODES_PER_BYTECODE (9.5) | |
947 | |
948 void WarmCallInfo::init(JVMState* call_site, ciMethod* call_method, ciCallProfile& profile, float prof_factor) { | |
949 int call_count = profile.count(); | |
950 int code_size = call_method->code_size(); | |
951 | |
952 // Expected execution count is based on the historical count: | |
953 _count = call_count < 0 ? 1 : call_site->method()->scale_count(call_count, prof_factor); | |
954 | |
955 // Expected profit from inlining, in units of simple call-overheads. | |
956 _profit = 1.0; | |
957 | |
958 // Expected work performed by the call in units of call-overheads. | |
959 // %%% need an empirical curve fit for "work" (time in call) | |
960 float bytecodes_per_call = 3; | |
961 _work = 1.0 + code_size / bytecodes_per_call; | |
962 | |
963 // Expected size of compilation graph: | |
964 // -XX:+PrintParseStatistics once reported: | |
965 // Methods seen: 9184 Methods parsed: 9184 Nodes created: 1582391 | |
966 // Histogram of 144298 parsed bytecodes: | |
967 // %%% Need an better predictor for graph size. | |
968 _size = NODES_OVERHEAD_PER_METHOD + (NODES_PER_BYTECODE * code_size); | |
969 } | |
970 | |
971 // is_cold: Return true if the node should never be inlined. | |
972 // This is true if any of the key metrics are extreme. | |
973 bool WarmCallInfo::is_cold() const { | |
974 if (count() < WarmCallMinCount) return true; | |
975 if (profit() < WarmCallMinProfit) return true; | |
976 if (work() > WarmCallMaxWork) return true; | |
977 if (size() > WarmCallMaxSize) return true; | |
978 return false; | |
979 } | |
980 | |
981 // is_hot: Return true if the node should be inlined immediately. | |
982 // This is true if any of the key metrics are extreme. | |
983 bool WarmCallInfo::is_hot() const { | |
984 assert(!is_cold(), "eliminate is_cold cases before testing is_hot"); | |
985 if (count() >= HotCallCountThreshold) return true; | |
986 if (profit() >= HotCallProfitThreshold) return true; | |
987 if (work() <= HotCallTrivialWork) return true; | |
988 if (size() <= HotCallTrivialSize) return true; | |
989 return false; | |
990 } | |
991 | |
992 // compute_heat: | |
993 float WarmCallInfo::compute_heat() const { | |
994 assert(!is_cold(), "compute heat only on warm nodes"); | |
995 assert(!is_hot(), "compute heat only on warm nodes"); | |
996 int min_size = MAX2(0, (int)HotCallTrivialSize); | |
997 int max_size = MIN2(500, (int)WarmCallMaxSize); | |
998 float method_size = (size() - min_size) / MAX2(1, max_size - min_size); | |
999 float size_factor; | |
1000 if (method_size < 0.05) size_factor = 4; // 2 sigmas better than avg. | |
1001 else if (method_size < 0.15) size_factor = 2; // 1 sigma better than avg. | |
1002 else if (method_size < 0.5) size_factor = 1; // better than avg. | |
1003 else size_factor = 0.5; // worse than avg. | |
1004 return (count() * profit() * size_factor); | |
1005 } | |
1006 | |
1007 bool WarmCallInfo::warmer_than(WarmCallInfo* that) { | |
1008 assert(this != that, "compare only different WCIs"); | |
1009 assert(this->heat() != 0 && that->heat() != 0, "call compute_heat 1st"); | |
1010 if (this->heat() > that->heat()) return true; | |
1011 if (this->heat() < that->heat()) return false; | |
1012 assert(this->heat() == that->heat(), "no NaN heat allowed"); | |
1013 // Equal heat. Break the tie some other way. | |
1014 if (!this->call() || !that->call()) return (address)this > (address)that; | |
1015 return this->call()->_idx > that->call()->_idx; | |
1016 } | |
1017 | |
1018 //#define UNINIT_NEXT ((WarmCallInfo*)badAddress) | |
1019 #define UNINIT_NEXT ((WarmCallInfo*)NULL) | |
1020 | |
1021 WarmCallInfo* WarmCallInfo::insert_into(WarmCallInfo* head) { | |
1022 assert(next() == UNINIT_NEXT, "not yet on any list"); | |
1023 WarmCallInfo* prev_p = NULL; | |
1024 WarmCallInfo* next_p = head; | |
1025 while (next_p != NULL && next_p->warmer_than(this)) { | |
1026 prev_p = next_p; | |
1027 next_p = prev_p->next(); | |
1028 } | |
1029 // Install this between prev_p and next_p. | |
1030 this->set_next(next_p); | |
1031 if (prev_p == NULL) | |
1032 head = this; | |
1033 else | |
1034 prev_p->set_next(this); | |
1035 return head; | |
1036 } | |
1037 | |
1038 WarmCallInfo* WarmCallInfo::remove_from(WarmCallInfo* head) { | |
1039 WarmCallInfo* prev_p = NULL; | |
1040 WarmCallInfo* next_p = head; | |
1041 while (next_p != this) { | |
1042 assert(next_p != NULL, "this must be in the list somewhere"); | |
1043 prev_p = next_p; | |
1044 next_p = prev_p->next(); | |
1045 } | |
1046 next_p = this->next(); | |
1047 debug_only(this->set_next(UNINIT_NEXT)); | |
1048 // Remove this from between prev_p and next_p. | |
1049 if (prev_p == NULL) | |
1050 head = next_p; | |
1051 else | |
1052 prev_p->set_next(next_p); | |
1053 return head; | |
1054 } | |
1055 | |
2443
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1056 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
|
1057 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
|
1058 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
|
1059 WarmCallInfo::MAX_VALUE(), WarmCallInfo::MAX_VALUE()); |
0 | 1060 |
1061 WarmCallInfo* WarmCallInfo::always_hot() { | |
2443
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1062 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
|
1063 return &_always_hot; |
0 | 1064 } |
1065 | |
1066 WarmCallInfo* WarmCallInfo::always_cold() { | |
2443
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1067 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
|
1068 return &_always_cold; |
0 | 1069 } |
1070 | |
1071 | |
1072 #ifndef PRODUCT | |
1073 | |
1074 void WarmCallInfo::print() const { | |
1075 tty->print("%s : C=%6.1f P=%6.1f W=%6.1f S=%6.1f H=%6.1f -> %p", | |
1076 is_cold() ? "cold" : is_hot() ? "hot " : "warm", | |
1077 count(), profit(), work(), size(), compute_heat(), next()); | |
1078 tty->cr(); | |
1079 if (call() != NULL) call()->dump(); | |
1080 } | |
1081 | |
1082 void print_wci(WarmCallInfo* ci) { | |
1083 ci->print(); | |
1084 } | |
1085 | |
1086 void WarmCallInfo::print_all() const { | |
1087 for (const WarmCallInfo* p = this; p != NULL; p = p->next()) | |
1088 p->print(); | |
1089 } | |
1090 | |
1091 int WarmCallInfo::count_all() const { | |
1092 int cnt = 0; | |
1093 for (const WarmCallInfo* p = this; p != NULL; p = p->next()) | |
1094 cnt++; | |
1095 return cnt; | |
1096 } | |
1097 | |
1098 #endif //PRODUCT |