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