Mercurial > hg > truffle
annotate src/share/vm/opto/callGenerator.cpp @ 4710:41406797186b
7113012: G1: rename not-fully-young GCs as "mixed"
Summary: Renamed partially-young GCs as mixed and fully-young GCs as young. Change all external output that includes those terms (GC log and GC ergo log) as well as any comments, fields, methods, etc. The changeset also includes very minor code tidying up (added some curly brackets).
Reviewed-by: johnc, brutisso
author | tonyp |
---|---|
date | Fri, 16 Dec 2011 02:14:27 -0500 |
parents | a04a201f0f5a |
children | 847da049d62f |
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 | |
321 CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) { | |
322 assert(!m->is_static(), "for_virtual_call mismatch"); | |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1080
diff
changeset
|
323 assert(!m->is_method_handle_invoke(), "should be a direct call"); |
0 | 324 return new VirtualCallGenerator(m, vtable_index); |
325 } | |
326 | |
4117
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
327 CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) { |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
328 assert(m->is_method_handle_invoke() || m->is_method_handle_adapter(), "for_dynamic_call mismatch"); |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
329 return new DynamicCallGenerator(m); |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
330 } |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
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()); | |
4117
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
579 if (kit.failing()) |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
580 return NULL; // might happen because of NodeCountInliningCutoff |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
581 assert(slow_jvms != NULL, "must be"); |
0 | 582 kit.add_exception_states_from(slow_jvms); |
583 kit.set_map(slow_jvms->map()); | |
584 if (!kit.stopped()) | |
585 slow_map = kit.stop(); | |
586 } | |
587 } | |
588 | |
293
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
0
diff
changeset
|
589 if (kit.stopped()) { |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
0
diff
changeset
|
590 // 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
|
591 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
|
592 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
|
593 } |
c3e045194476
6731641: assert(m->adr_type() == mach->adr_type(),"matcher should not change adr type")
kvn
parents:
0
diff
changeset
|
594 |
0 | 595 // fall through if the instance exactly matches the desired type |
596 kit.replace_in_map(receiver, exact_receiver); | |
597 | |
598 // Make the hot call: | |
599 JVMState* new_jvms = _if_hit->generate(kit.sync_jvms()); | |
600 if (new_jvms == NULL) { | |
601 // Inline failed, so make a direct call. | |
602 assert(_if_hit->is_inline(), "must have been a failed inline"); | |
603 CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method()); | |
604 new_jvms = cg->generate(kit.sync_jvms()); | |
605 } | |
606 kit.add_exception_states_from(new_jvms); | |
607 kit.set_jvms(new_jvms); | |
608 | |
609 // Need to merge slow and fast? | |
610 if (slow_map == NULL) { | |
611 // The fast path is the only path remaining. | |
612 return kit.transfer_exceptions_into_jvms(); | |
613 } | |
614 | |
615 if (kit.stopped()) { | |
616 // Inlined method threw an exception, so it's just the slow path after all. | |
617 kit.set_jvms(slow_jvms); | |
618 return kit.transfer_exceptions_into_jvms(); | |
619 } | |
620 | |
621 // Finish the diamond. | |
622 kit.C->set_has_split_ifs(true); // Has chance for split-if optimization | |
623 RegionNode* region = new (kit.C, 3) RegionNode(3); | |
624 region->init_req(1, kit.control()); | |
625 region->init_req(2, slow_map->control()); | |
626 kit.set_control(gvn.transform(region)); | |
627 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO); | |
628 iophi->set_req(2, slow_map->i_o()); | |
629 kit.set_i_o(gvn.transform(iophi)); | |
630 kit.merge_memory(slow_map->merged_memory(), region, 2); | |
631 uint tos = kit.jvms()->stkoff() + kit.sp(); | |
632 uint limit = slow_map->req(); | |
633 for (uint i = TypeFunc::Parms; i < limit; i++) { | |
634 // Skip unused stack slots; fast forward to monoff(); | |
635 if (i == tos) { | |
636 i = kit.jvms()->monoff(); | |
637 if( i >= limit ) break; | |
638 } | |
639 Node* m = kit.map()->in(i); | |
640 Node* n = slow_map->in(i); | |
641 if (m != n) { | |
642 const Type* t = gvn.type(m)->meet(gvn.type(n)); | |
643 Node* phi = PhiNode::make(region, m, t); | |
644 phi->set_req(2, n); | |
645 kit.map()->set_req(i, gvn.transform(phi)); | |
646 } | |
647 } | |
648 return kit.transfer_exceptions_into_jvms(); | |
649 } | |
650 | |
651 | |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
652 //------------------------PredictedDynamicCallGenerator----------------------- |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
653 // 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
|
654 class PredictedDynamicCallGenerator : public CallGenerator { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
655 ciMethodHandle* _predicted_method_handle; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
656 CallGenerator* _if_missed; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
657 CallGenerator* _if_hit; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
658 float _hit_prob; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
659 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
660 public: |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
661 PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle, |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
662 CallGenerator* if_missed, |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
663 CallGenerator* if_hit, |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
664 float hit_prob) |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
665 : CallGenerator(if_missed->method()), |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
666 _predicted_method_handle(predicted_method_handle), |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
667 _if_missed(if_missed), |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
668 _if_hit(if_hit), |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
669 _hit_prob(hit_prob) |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
670 {} |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
671 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
672 virtual bool is_inline() const { return _if_hit->is_inline(); } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
673 virtual bool is_deferred() const { return _if_hit->is_deferred(); } |
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 virtual JVMState* generate(JVMState* jvms); |
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 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
678 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
679 CallGenerator* CallGenerator::for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle, |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
680 CallGenerator* if_missed, |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
681 CallGenerator* if_hit, |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
682 float hit_prob) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
683 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
|
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 |
4117
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
687 CallGenerator* CallGenerator::for_method_handle_call(Node* method_handle, JVMState* jvms, |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
688 ciMethod* caller, ciMethod* callee, ciCallProfile profile) { |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
689 assert(callee->is_method_handle_invoke() || callee->is_method_handle_adapter(), "for_method_handle_call mismatch"); |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
690 CallGenerator* cg = CallGenerator::for_method_handle_inline(method_handle, jvms, caller, callee, profile); |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
691 if (cg != NULL) |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
692 return cg; |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
693 return CallGenerator::for_direct_call(callee); |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
694 } |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
695 |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
696 CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMState* jvms, |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
697 ciMethod* caller, ciMethod* callee, ciCallProfile profile) { |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
698 if (method_handle->Opcode() == Op_ConP) { |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
699 const TypeOopPtr* oop_ptr = method_handle->bottom_type()->is_oopptr(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
700 ciObject* const_oop = oop_ptr->const_oop(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
701 ciMethodHandle* method_handle = const_oop->as_method_handle(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
702 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
703 // 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
|
704 // the MethodHandleCompiler. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
705 method_handle->set_callee(callee); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
706 method_handle->set_caller(caller); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
707 method_handle->set_call_profile(profile); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
708 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
709 // Get an adapter for the MethodHandle. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
710 ciMethod* target_method = method_handle->get_method_handle_adapter(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
711 if (target_method != NULL) { |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
712 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
|
713 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
|
714 return cg; |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
715 } |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
716 } else if (method_handle->Opcode() == Op_Phi && method_handle->req() == 3 && |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
717 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
|
718 float prob = PROB_FAIR; |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
719 Node* meth_region = method_handle->in(0); |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
720 if (meth_region->is_Region() && |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
721 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
|
722 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
|
723 meth_region->in(1)->in(0)->is_If()) { |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
724 // 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
|
725 prob = meth_region->in(1)->in(0)->as_If()->_prob; |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
726 if (meth_region->in(1)->is_IfTrue()) { |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
727 prob = 1 - prob; |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
728 } |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
729 } |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
730 |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
731 // selectAlternative idiom merging two constant MethodHandles. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
732 // 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
|
733 // 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
|
734 // case. |
4117
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
735 CallGenerator* cg1 = for_method_handle_call(method_handle->in(1), jvms, caller, callee, profile.rescale(1.0 - prob)); |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
736 CallGenerator* cg2 = for_method_handle_call(method_handle->in(2), jvms, caller, callee, profile.rescale(prob)); |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
737 if (cg1 != NULL && cg2 != NULL) { |
3905
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
738 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
|
739 ciObject* const_oop = oop_ptr->const_oop(); |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
740 ciMethodHandle* mh = const_oop->as_method_handle(); |
c26de9aef2ed
7071307: MethodHandle bimorphic inlining should consider the frequency
never
parents:
3901
diff
changeset
|
741 return new PredictedDynamicCallGenerator(mh, cg2, cg1, prob); |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
742 } |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
743 } |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
744 return NULL; |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
745 } |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
746 |
4117
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
747 CallGenerator* CallGenerator::for_invokedynamic_call(JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile) { |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
748 assert(callee->is_method_handle_invoke() || callee->is_method_handle_adapter(), "for_invokedynamic_call mismatch"); |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
749 // Get the CallSite object. |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
750 ciBytecodeStream str(caller); |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
751 str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci. |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
752 ciCallSite* call_site = str.get_call_site(); |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
753 CallGenerator* cg = CallGenerator::for_invokedynamic_inline(call_site, jvms, caller, callee, profile); |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
754 if (cg != NULL) |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
755 return cg; |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
756 return CallGenerator::for_dynamic_call(callee); |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
757 } |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
758 |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
759 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
|
760 ciMethod* caller, ciMethod* callee, ciCallProfile profile) { |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
761 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
|
762 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
763 // 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
|
764 // MethodHandleCompiler. |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
765 method_handle->set_callee(callee); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
766 method_handle->set_caller(caller); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
767 method_handle->set_call_profile(profile); |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
768 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
769 // Get an adapter for the MethodHandle. |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
770 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
|
771 if (target_method != NULL) { |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
772 Compile *C = Compile::current(); |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
773 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
|
774 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
|
775 // Add a dependence for invalidation of the optimization. |
3901
aa67216400d3
7085404: JSR 292: VolatileCallSites should have push notification too
twisti
parents:
3900
diff
changeset
|
776 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
|
777 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
|
778 } |
3894
b27c72d69fd1
7083184: JSR 292: don't store context class argument with call site dependencies
twisti
parents:
3852
diff
changeset
|
779 return cg; |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
780 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
781 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
782 return NULL; |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
783 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
784 |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3752
diff
changeset
|
785 |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
786 JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
787 GraphKit kit(jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
788 PhaseGVN& gvn = kit.gvn(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
789 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
790 CompileLog* log = kit.C->log(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
791 if (log != NULL) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
792 log->elem("predicted_dynamic_call bci='%d'", jvms->bci()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
793 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
794 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
795 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
|
796 Node* predicted_mh = kit.makecon(predicted_mh_ptr); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
797 |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
798 Node* bol = NULL; |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
799 int bc = jvms->method()->java_code_at_bci(jvms->bci()); |
4062
83d0b5cd1438
7087727: JSR 292: C2 crash if ScavengeRootsInCode=2 when "static final" MethodHandle constants are in use
twisti
parents:
3905
diff
changeset
|
800 if (bc != Bytecodes::_invokedynamic) { |
83d0b5cd1438
7087727: JSR 292: C2 crash if ScavengeRootsInCode=2 when "static final" MethodHandle constants are in use
twisti
parents:
3905
diff
changeset
|
801 // This is the selectAlternative idiom for guardWithTest or |
83d0b5cd1438
7087727: JSR 292: C2 crash if ScavengeRootsInCode=2 when "static final" MethodHandle constants are in use
twisti
parents:
3905
diff
changeset
|
802 // similar idioms. |
3752
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
803 Node* receiver = kit.argument(0); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
804 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
805 // Check if the MethodHandle is the expected one |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
806 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
|
807 bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) ); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
808 } else { |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
809 // Get the constant pool cache from the caller class. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
810 ciMethod* caller_method = jvms->method(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
811 ciBytecodeStream str(caller_method); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
812 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
|
813 ciCPCache* cpcache = str.get_cpcache(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
814 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
815 // Get the offset of the CallSite from the constant pool cache |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
816 // pointer. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
817 int index = str.get_method_index(); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
818 size_t call_site_offset = cpcache->get_f1_offset(index); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
819 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
820 // Load the CallSite object from the constant pool cache. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
821 const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
822 Node* cpcache_adr = kit.makecon(cpcache_ptr); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
823 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
|
824 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
|
825 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
826 // Load the target MethodHandle from the CallSite object. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
827 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
|
828 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
|
829 |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
830 // Check if the MethodHandle is still the same. |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
831 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
|
832 bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) ); |
f918d6096e23
7050554: JSR 292 - need optimization for selectAlternative
never
parents:
2443
diff
changeset
|
833 } |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
834 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
|
835 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
|
836 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
|
837 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
838 SafePointNode* slow_map = NULL; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
839 JVMState* slow_jvms; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
840 { PreserveJVMState pjvms(&kit); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
841 kit.set_control(slow_ctl); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
842 if (!kit.stopped()) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
843 slow_jvms = _if_missed->generate(kit.sync_jvms()); |
4117
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
844 if (kit.failing()) |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
845 return NULL; // might happen because of NodeCountInliningCutoff |
a04a201f0f5a
7108383: JSR 292: JRuby bench_define_method_methods.rb: assert(slow_jvms != NULL) failed: miss path must not
twisti
parents:
4062
diff
changeset
|
846 assert(slow_jvms != NULL, "must be"); |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
847 kit.add_exception_states_from(slow_jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
848 kit.set_map(slow_jvms->map()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
849 if (!kit.stopped()) |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
850 slow_map = kit.stop(); |
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 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
854 if (kit.stopped()) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
855 // Instance exactly does not matches the desired type. |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
856 kit.set_jvms(slow_jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
857 return kit.transfer_exceptions_into_jvms(); |
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 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
860 // Make the hot call: |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
861 JVMState* new_jvms = _if_hit->generate(kit.sync_jvms()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
862 if (new_jvms == NULL) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
863 // Inline failed, so make a direct call. |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
864 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
|
865 CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
866 new_jvms = cg->generate(kit.sync_jvms()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
867 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
868 kit.add_exception_states_from(new_jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
869 kit.set_jvms(new_jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
870 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
871 // Need to merge slow and fast? |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
872 if (slow_map == NULL) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
873 // The fast path is the only path remaining. |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
874 return kit.transfer_exceptions_into_jvms(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
875 } |
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 if (kit.stopped()) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
878 // 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
|
879 kit.set_jvms(slow_jvms); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
880 return kit.transfer_exceptions_into_jvms(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
881 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
882 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
883 // Finish the diamond. |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
884 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
|
885 RegionNode* region = new (kit.C, 3) RegionNode(3); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
886 region->init_req(1, kit.control()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
887 region->init_req(2, slow_map->control()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
888 kit.set_control(gvn.transform(region)); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
889 Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
890 iophi->set_req(2, slow_map->i_o()); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
891 kit.set_i_o(gvn.transform(iophi)); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
892 kit.merge_memory(slow_map->merged_memory(), region, 2); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
893 uint tos = kit.jvms()->stkoff() + kit.sp(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
894 uint limit = slow_map->req(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
895 for (uint i = TypeFunc::Parms; i < limit; i++) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
896 // Skip unused stack slots; fast forward to monoff(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
897 if (i == tos) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
898 i = kit.jvms()->monoff(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
899 if( i >= limit ) break; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
900 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
901 Node* m = kit.map()->in(i); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
902 Node* n = slow_map->in(i); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
903 if (m != n) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
904 const Type* t = gvn.type(m)->meet(gvn.type(n)); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
905 Node* phi = PhiNode::make(region, m, t); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
906 phi->set_req(2, n); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
907 kit.map()->set_req(i, gvn.transform(phi)); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
908 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
909 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
910 return kit.transfer_exceptions_into_jvms(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
911 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
912 |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1137
diff
changeset
|
913 |
0 | 914 //-------------------------UncommonTrapCallGenerator----------------------------- |
915 // Internal class which handles all out-of-line calls checking receiver type. | |
916 class UncommonTrapCallGenerator : public CallGenerator { | |
917 Deoptimization::DeoptReason _reason; | |
918 Deoptimization::DeoptAction _action; | |
919 | |
920 public: | |
921 UncommonTrapCallGenerator(ciMethod* m, | |
922 Deoptimization::DeoptReason reason, | |
923 Deoptimization::DeoptAction action) | |
924 : CallGenerator(m) | |
925 { | |
926 _reason = reason; | |
927 _action = action; | |
928 } | |
929 | |
930 virtual bool is_virtual() const { ShouldNotReachHere(); return false; } | |
931 virtual bool is_trap() const { return true; } | |
932 | |
933 virtual JVMState* generate(JVMState* jvms); | |
934 }; | |
935 | |
936 | |
937 CallGenerator* | |
938 CallGenerator::for_uncommon_trap(ciMethod* m, | |
939 Deoptimization::DeoptReason reason, | |
940 Deoptimization::DeoptAction action) { | |
941 return new UncommonTrapCallGenerator(m, reason, action); | |
942 } | |
943 | |
944 | |
945 JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms) { | |
946 GraphKit kit(jvms); | |
947 // Take the trap with arguments pushed on the stack. (Cf. null_check_receiver). | |
948 int nargs = method()->arg_size(); | |
949 kit.inc_sp(nargs); | |
950 assert(nargs <= kit.sp() && kit.sp() <= jvms->stk_size(), "sane sp w/ args pushed"); | |
951 if (_reason == Deoptimization::Reason_class_check && | |
952 _action == Deoptimization::Action_maybe_recompile) { | |
953 // Temp fix for 6529811 | |
954 // Don't allow uncommon_trap to override our decision to recompile in the event | |
955 // of a class cast failure for a monomorphic call as it will never let us convert | |
956 // the call to either bi-morphic or megamorphic and can lead to unc-trap loops | |
957 bool keep_exact_action = true; | |
958 kit.uncommon_trap(_reason, _action, NULL, "monomorphic vcall checkcast", false, keep_exact_action); | |
959 } else { | |
960 kit.uncommon_trap(_reason, _action); | |
961 } | |
962 return kit.transfer_exceptions_into_jvms(); | |
963 } | |
964 | |
965 // (Note: Moved hook_up_call to GraphKit::set_edges_for_java_call.) | |
966 | |
967 // (Node: Merged hook_up_exits into ParseGenerator::generate.) | |
968 | |
969 #define NODES_OVERHEAD_PER_METHOD (30.0) | |
970 #define NODES_PER_BYTECODE (9.5) | |
971 | |
972 void WarmCallInfo::init(JVMState* call_site, ciMethod* call_method, ciCallProfile& profile, float prof_factor) { | |
973 int call_count = profile.count(); | |
974 int code_size = call_method->code_size(); | |
975 | |
976 // Expected execution count is based on the historical count: | |
977 _count = call_count < 0 ? 1 : call_site->method()->scale_count(call_count, prof_factor); | |
978 | |
979 // Expected profit from inlining, in units of simple call-overheads. | |
980 _profit = 1.0; | |
981 | |
982 // Expected work performed by the call in units of call-overheads. | |
983 // %%% need an empirical curve fit for "work" (time in call) | |
984 float bytecodes_per_call = 3; | |
985 _work = 1.0 + code_size / bytecodes_per_call; | |
986 | |
987 // Expected size of compilation graph: | |
988 // -XX:+PrintParseStatistics once reported: | |
989 // Methods seen: 9184 Methods parsed: 9184 Nodes created: 1582391 | |
990 // Histogram of 144298 parsed bytecodes: | |
991 // %%% Need an better predictor for graph size. | |
992 _size = NODES_OVERHEAD_PER_METHOD + (NODES_PER_BYTECODE * code_size); | |
993 } | |
994 | |
995 // is_cold: Return true if the node should never be inlined. | |
996 // This is true if any of the key metrics are extreme. | |
997 bool WarmCallInfo::is_cold() const { | |
998 if (count() < WarmCallMinCount) return true; | |
999 if (profit() < WarmCallMinProfit) return true; | |
1000 if (work() > WarmCallMaxWork) return true; | |
1001 if (size() > WarmCallMaxSize) return true; | |
1002 return false; | |
1003 } | |
1004 | |
1005 // is_hot: Return true if the node should be inlined immediately. | |
1006 // This is true if any of the key metrics are extreme. | |
1007 bool WarmCallInfo::is_hot() const { | |
1008 assert(!is_cold(), "eliminate is_cold cases before testing is_hot"); | |
1009 if (count() >= HotCallCountThreshold) return true; | |
1010 if (profit() >= HotCallProfitThreshold) return true; | |
1011 if (work() <= HotCallTrivialWork) return true; | |
1012 if (size() <= HotCallTrivialSize) return true; | |
1013 return false; | |
1014 } | |
1015 | |
1016 // compute_heat: | |
1017 float WarmCallInfo::compute_heat() const { | |
1018 assert(!is_cold(), "compute heat only on warm nodes"); | |
1019 assert(!is_hot(), "compute heat only on warm nodes"); | |
1020 int min_size = MAX2(0, (int)HotCallTrivialSize); | |
1021 int max_size = MIN2(500, (int)WarmCallMaxSize); | |
1022 float method_size = (size() - min_size) / MAX2(1, max_size - min_size); | |
1023 float size_factor; | |
1024 if (method_size < 0.05) size_factor = 4; // 2 sigmas better than avg. | |
1025 else if (method_size < 0.15) size_factor = 2; // 1 sigma better than avg. | |
1026 else if (method_size < 0.5) size_factor = 1; // better than avg. | |
1027 else size_factor = 0.5; // worse than avg. | |
1028 return (count() * profit() * size_factor); | |
1029 } | |
1030 | |
1031 bool WarmCallInfo::warmer_than(WarmCallInfo* that) { | |
1032 assert(this != that, "compare only different WCIs"); | |
1033 assert(this->heat() != 0 && that->heat() != 0, "call compute_heat 1st"); | |
1034 if (this->heat() > that->heat()) return true; | |
1035 if (this->heat() < that->heat()) return false; | |
1036 assert(this->heat() == that->heat(), "no NaN heat allowed"); | |
1037 // Equal heat. Break the tie some other way. | |
1038 if (!this->call() || !that->call()) return (address)this > (address)that; | |
1039 return this->call()->_idx > that->call()->_idx; | |
1040 } | |
1041 | |
1042 //#define UNINIT_NEXT ((WarmCallInfo*)badAddress) | |
1043 #define UNINIT_NEXT ((WarmCallInfo*)NULL) | |
1044 | |
1045 WarmCallInfo* WarmCallInfo::insert_into(WarmCallInfo* head) { | |
1046 assert(next() == UNINIT_NEXT, "not yet on any list"); | |
1047 WarmCallInfo* prev_p = NULL; | |
1048 WarmCallInfo* next_p = head; | |
1049 while (next_p != NULL && next_p->warmer_than(this)) { | |
1050 prev_p = next_p; | |
1051 next_p = prev_p->next(); | |
1052 } | |
1053 // Install this between prev_p and next_p. | |
1054 this->set_next(next_p); | |
1055 if (prev_p == NULL) | |
1056 head = this; | |
1057 else | |
1058 prev_p->set_next(this); | |
1059 return head; | |
1060 } | |
1061 | |
1062 WarmCallInfo* WarmCallInfo::remove_from(WarmCallInfo* head) { | |
1063 WarmCallInfo* prev_p = NULL; | |
1064 WarmCallInfo* next_p = head; | |
1065 while (next_p != this) { | |
1066 assert(next_p != NULL, "this must be in the list somewhere"); | |
1067 prev_p = next_p; | |
1068 next_p = prev_p->next(); | |
1069 } | |
1070 next_p = this->next(); | |
1071 debug_only(this->set_next(UNINIT_NEXT)); | |
1072 // Remove this from between prev_p and next_p. | |
1073 if (prev_p == NULL) | |
1074 head = next_p; | |
1075 else | |
1076 prev_p->set_next(next_p); | |
1077 return head; | |
1078 } | |
1079 | |
2443
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1080 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
|
1081 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
|
1082 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
|
1083 WarmCallInfo::MAX_VALUE(), WarmCallInfo::MAX_VALUE()); |
0 | 1084 |
1085 WarmCallInfo* WarmCallInfo::always_hot() { | |
2443
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1086 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
|
1087 return &_always_hot; |
0 | 1088 } |
1089 | |
1090 WarmCallInfo* WarmCallInfo::always_cold() { | |
2443
f8b038506985
6909440: C2 fails with assertion (_always_cold->is_cold(),"must always be cold")
never
parents:
2357
diff
changeset
|
1091 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
|
1092 return &_always_cold; |
0 | 1093 } |
1094 | |
1095 | |
1096 #ifndef PRODUCT | |
1097 | |
1098 void WarmCallInfo::print() const { | |
1099 tty->print("%s : C=%6.1f P=%6.1f W=%6.1f S=%6.1f H=%6.1f -> %p", | |
1100 is_cold() ? "cold" : is_hot() ? "hot " : "warm", | |
1101 count(), profit(), work(), size(), compute_heat(), next()); | |
1102 tty->cr(); | |
1103 if (call() != NULL) call()->dump(); | |
1104 } | |
1105 | |
1106 void print_wci(WarmCallInfo* ci) { | |
1107 ci->print(); | |
1108 } | |
1109 | |
1110 void WarmCallInfo::print_all() const { | |
1111 for (const WarmCallInfo* p = this; p != NULL; p = p->next()) | |
1112 p->print(); | |
1113 } | |
1114 | |
1115 int WarmCallInfo::count_all() const { | |
1116 int cnt = 0; | |
1117 for (const WarmCallInfo* p = this; p != NULL; p = p->next()) | |
1118 cnt++; | |
1119 return cnt; | |
1120 } | |
1121 | |
1122 #endif //PRODUCT |