Mercurial > hg > truffle
annotate src/share/vm/opto/parseHelper.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 | f95d63e2154a |
children | 52b5d32fbfaf 069ab3f976d3 |
rev | line source |
---|---|
0 | 1 /* |
1645
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
2 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1206
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1206
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:
1206
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/systemDictionary.hpp" | |
27 #include "compiler/compileLog.hpp" | |
28 #include "oops/objArrayKlass.hpp" | |
29 #include "opto/addnode.hpp" | |
30 #include "opto/memnode.hpp" | |
31 #include "opto/mulnode.hpp" | |
32 #include "opto/parse.hpp" | |
33 #include "opto/rootnode.hpp" | |
34 #include "opto/runtime.hpp" | |
35 #include "runtime/sharedRuntime.hpp" | |
0 | 36 |
37 //------------------------------make_dtrace_method_entry_exit ---------------- | |
38 // Dtrace -- record entry or exit of a method if compiled with dtrace support | |
39 void GraphKit::make_dtrace_method_entry_exit(ciMethod* method, bool is_entry) { | |
40 const TypeFunc *call_type = OptoRuntime::dtrace_method_entry_exit_Type(); | |
41 address call_address = is_entry ? CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_entry) : | |
42 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit); | |
43 const char *call_name = is_entry ? "dtrace_method_entry" : "dtrace_method_exit"; | |
44 | |
45 // Get base of thread-local storage area | |
46 Node* thread = _gvn.transform( new (C, 1) ThreadLocalNode() ); | |
47 | |
48 // Get method | |
49 const TypeInstPtr* method_type = TypeInstPtr::make(TypePtr::Constant, method->klass(), true, method, 0); | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
0
diff
changeset
|
50 Node *method_node = _gvn.transform( ConNode::make(C, method_type) ); |
0 | 51 |
52 kill_dead_locals(); | |
53 | |
54 // For some reason, this call reads only raw memory. | |
55 const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM; | |
56 make_runtime_call(RC_LEAF | RC_NARROW_MEM, | |
57 call_type, call_address, | |
58 call_name, raw_adr_type, | |
59 thread, method_node); | |
60 } | |
61 | |
62 | |
63 //============================================================================= | |
64 //------------------------------do_checkcast----------------------------------- | |
65 void Parse::do_checkcast() { | |
66 bool will_link; | |
67 ciKlass* klass = iter().get_klass(will_link); | |
68 | |
69 Node *obj = peek(); | |
70 | |
71 // Throw uncommon trap if class is not loaded or the value we are casting | |
72 // _from_ is not loaded, and value is not null. If the value _is_ NULL, | |
73 // then the checkcast does nothing. | |
74 const TypeInstPtr *tp = _gvn.type(obj)->isa_instptr(); | |
75 if (!will_link || (tp && !tp->is_loaded())) { | |
76 if (C->log() != NULL) { | |
77 if (!will_link) { | |
78 C->log()->elem("assert_null reason='checkcast' klass='%d'", | |
79 C->log()->identify(klass)); | |
80 } | |
81 if (tp && !tp->is_loaded()) { | |
82 // %%% Cannot happen? | |
83 C->log()->elem("assert_null reason='checkcast source' klass='%d'", | |
84 C->log()->identify(tp->klass())); | |
85 } | |
86 } | |
87 do_null_assert(obj, T_OBJECT); | |
88 assert( stopped() || _gvn.type(peek())->higher_equal(TypePtr::NULL_PTR), "what's left behind is null" ); | |
89 if (!stopped()) { | |
90 profile_null_checkcast(); | |
91 } | |
92 return; | |
93 } | |
94 | |
95 Node *res = gen_checkcast(obj, makecon(TypeKlassPtr::make(klass)) ); | |
96 | |
97 // Pop from stack AFTER gen_checkcast because it can uncommon trap and | |
98 // the debug info has to be correct. | |
99 pop(); | |
100 push(res); | |
101 } | |
102 | |
103 | |
104 //------------------------------do_instanceof---------------------------------- | |
105 void Parse::do_instanceof() { | |
106 if (stopped()) return; | |
107 // We would like to return false if class is not loaded, emitting a | |
108 // dependency, but Java requires instanceof to load its operand. | |
109 | |
110 // Throw uncommon trap if class is not loaded | |
111 bool will_link; | |
112 ciKlass* klass = iter().get_klass(will_link); | |
113 | |
114 if (!will_link) { | |
115 if (C->log() != NULL) { | |
116 C->log()->elem("assert_null reason='instanceof' klass='%d'", | |
117 C->log()->identify(klass)); | |
118 } | |
119 do_null_assert(peek(), T_OBJECT); | |
120 assert( stopped() || _gvn.type(peek())->higher_equal(TypePtr::NULL_PTR), "what's left behind is null" ); | |
121 if (!stopped()) { | |
122 // The object is now known to be null. | |
123 // Shortcut the effect of gen_instanceof and return "false" directly. | |
124 pop(); // pop the null | |
125 push(_gvn.intcon(0)); // push false answer | |
126 } | |
127 return; | |
128 } | |
129 | |
130 // Push the bool result back on stack | |
1746
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1645
diff
changeset
|
131 Node* res = gen_instanceof(peek(), makecon(TypeKlassPtr::make(klass))); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1645
diff
changeset
|
132 |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1645
diff
changeset
|
133 // Pop from stack AFTER gen_instanceof because it can uncommon trap. |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1645
diff
changeset
|
134 pop(); |
4b29a725c43c
6912064: type profiles need to be exploited more for dynamic language support
jrose
parents:
1645
diff
changeset
|
135 push(res); |
0 | 136 } |
137 | |
138 //------------------------------array_store_check------------------------------ | |
139 // pull array from stack and check that the store is valid | |
140 void Parse::array_store_check() { | |
141 | |
142 // Shorthand access to array store elements | |
143 Node *obj = stack(_sp-1); | |
144 Node *idx = stack(_sp-2); | |
145 Node *ary = stack(_sp-3); | |
146 | |
147 if (_gvn.type(obj) == TypePtr::NULL_PTR) { | |
148 // There's never a type check on null values. | |
149 // This cutout lets us avoid the uncommon_trap(Reason_array_check) | |
150 // below, which turns into a performance liability if the | |
151 // gen_checkcast folds up completely. | |
152 return; | |
153 } | |
154 | |
155 // Extract the array klass type | |
156 int klass_offset = oopDesc::klass_offset_in_bytes(); | |
157 Node* p = basic_plus_adr( ary, ary, klass_offset ); | |
158 // p's type is array-of-OOPS plus klass_offset | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
0
diff
changeset
|
159 Node* array_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS) ); |
0 | 160 // Get the array klass |
161 const TypeKlassPtr *tak = _gvn.type(array_klass)->is_klassptr(); | |
162 | |
163 // array_klass's type is generally INexact array-of-oop. Heroically | |
164 // cast the array klass to EXACT array and uncommon-trap if the cast | |
165 // fails. | |
166 bool always_see_exact_class = false; | |
167 if (MonomorphicArrayCheck | |
168 && !too_many_traps(Deoptimization::Reason_array_check)) { | |
169 always_see_exact_class = true; | |
170 // (If no MDO at all, hope for the best, until a trap actually occurs.) | |
171 } | |
172 | |
173 // Is the array klass is exactly its defined type? | |
174 if (always_see_exact_class && !tak->klass_is_exact()) { | |
175 // Make a constant out of the inexact array klass | |
176 const TypeKlassPtr *extak = tak->cast_to_exactness(true)->is_klassptr(); | |
177 Node* con = makecon(extak); | |
178 Node* cmp = _gvn.transform(new (C, 3) CmpPNode( array_klass, con )); | |
179 Node* bol = _gvn.transform(new (C, 2) BoolNode( cmp, BoolTest::eq )); | |
180 Node* ctrl= control(); | |
181 { BuildCutout unless(this, bol, PROB_MAX); | |
182 uncommon_trap(Deoptimization::Reason_array_check, | |
183 Deoptimization::Action_maybe_recompile, | |
184 tak->klass()); | |
185 } | |
186 if (stopped()) { // MUST uncommon-trap? | |
187 set_control(ctrl); // Then Don't Do It, just fall into the normal checking | |
188 } else { // Cast array klass to exactness: | |
189 // Use the exact constant value we know it is. | |
190 replace_in_map(array_klass,con); | |
191 CompileLog* log = C->log(); | |
192 if (log != NULL) { | |
193 log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'", | |
194 log->identify(tak->klass())); | |
195 } | |
196 array_klass = con; // Use cast value moving forward | |
197 } | |
198 } | |
199 | |
200 // Come here for polymorphic array klasses | |
201 | |
202 // Extract the array element class | |
203 int element_klass_offset = objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc); | |
204 Node *p2 = basic_plus_adr(array_klass, array_klass, element_klass_offset); | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
0
diff
changeset
|
205 Node *a_e_klass = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p2, tak) ); |
0 | 206 |
207 // Check (the hard way) and throw if not a subklass. | |
208 // Result is ignored, we just need the CFG effects. | |
209 gen_checkcast( obj, a_e_klass ); | |
210 } | |
211 | |
212 | |
1645
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
213 void Parse::emit_guard_for_new(ciInstanceKlass* klass) { |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
214 // Emit guarded new |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
215 // if (klass->_init_thread != current_thread || |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
216 // klass->_init_state != being_initialized) |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
217 // uncommon_trap |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
218 Node* cur_thread = _gvn.transform( new (C, 1) ThreadLocalNode() ); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
219 Node* merge = new (C, 3) RegionNode(3); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
220 _gvn.set_type(merge, Type::CONTROL); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
221 Node* kls = makecon(TypeKlassPtr::make(klass)); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
222 |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
223 Node* init_thread_offset = _gvn.MakeConX(instanceKlass::init_thread_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
224 Node* adr_node = basic_plus_adr(kls, kls, init_thread_offset); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
225 Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
226 Node *tst = Bool( CmpP( init_thread, cur_thread), BoolTest::eq); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
227 IfNode* iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
228 set_control(IfTrue(iff)); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
229 merge->set_req(1, IfFalse(iff)); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
230 |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
231 Node* init_state_offset = _gvn.MakeConX(instanceKlass::init_state_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
232 adr_node = basic_plus_adr(kls, kls, init_state_offset); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
233 Node* init_state = make_load(NULL, adr_node, TypeInt::INT, T_INT); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
234 Node* being_init = _gvn.intcon(instanceKlass::being_initialized); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
235 tst = Bool( CmpI( init_state, being_init), BoolTest::eq); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
236 iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
237 set_control(IfTrue(iff)); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
238 merge->set_req(2, IfFalse(iff)); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
239 |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
240 PreserveJVMState pjvms(this); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
241 record_for_igvn(merge); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
242 set_control(merge); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
243 |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
244 uncommon_trap(Deoptimization::Reason_uninitialized, |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
245 Deoptimization::Action_reinterpret, |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
246 klass); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
247 } |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
248 |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
249 |
0 | 250 //------------------------------do_new----------------------------------------- |
251 void Parse::do_new() { | |
252 kill_dead_locals(); | |
253 | |
254 bool will_link; | |
255 ciInstanceKlass* klass = iter().get_klass(will_link)->as_instance_klass(); | |
256 assert(will_link, "_new: typeflow responsibility"); | |
257 | |
258 // Should initialize, or throw an InstantiationError? | |
1645
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
259 if (!klass->is_initialized() && !klass->is_being_initialized() || |
0 | 260 klass->is_abstract() || klass->is_interface() || |
261 klass->name() == ciSymbol::java_lang_Class() || | |
262 iter().is_unresolved_klass()) { | |
263 uncommon_trap(Deoptimization::Reason_uninitialized, | |
264 Deoptimization::Action_reinterpret, | |
265 klass); | |
266 return; | |
267 } | |
1645
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
268 if (klass->is_being_initialized()) { |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
269 emit_guard_for_new(klass); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
270 } |
0 | 271 |
272 Node* kls = makecon(TypeKlassPtr::make(klass)); | |
273 Node* obj = new_instance(kls); | |
274 | |
275 // Push resultant oop onto stack | |
276 push(obj); | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
277 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
278 // Keep track of whether opportunities exist for StringBuilder |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
279 // optimizations. |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
280 if (OptimizeStringConcat && |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
281 (klass == C->env()->StringBuilder_klass() || |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
282 klass == C->env()->StringBuffer_klass())) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
283 C->set_has_stringbuilder(true); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
284 } |
0 | 285 } |
286 | |
287 #ifndef PRODUCT | |
288 //------------------------------dump_map_adr_mem------------------------------- | |
289 // Debug dump of the mapping from address types to MergeMemNode indices. | |
290 void Parse::dump_map_adr_mem() const { | |
291 tty->print_cr("--- Mapping from address types to memory Nodes ---"); | |
292 MergeMemNode *mem = map() == NULL ? NULL : (map()->memory()->is_MergeMem() ? | |
293 map()->memory()->as_MergeMem() : NULL); | |
294 for (uint i = 0; i < (uint)C->num_alias_types(); i++) { | |
295 C->alias_type(i)->print_on(tty); | |
296 tty->print("\t"); | |
297 // Node mapping, if any | |
298 if (mem && i < mem->req() && mem->in(i) && mem->in(i) != mem->empty_memory()) { | |
299 mem->in(i)->dump(); | |
300 } else { | |
301 tty->cr(); | |
302 } | |
303 } | |
304 } | |
305 | |
306 #endif | |
307 | |
308 | |
309 //============================================================================= | |
310 // | |
311 // parser methods for profiling | |
312 | |
313 | |
314 //----------------------test_counter_against_threshold ------------------------ | |
315 void Parse::test_counter_against_threshold(Node* cnt, int limit) { | |
316 // Test the counter against the limit and uncommon trap if greater. | |
317 | |
318 // This code is largely copied from the range check code in | |
319 // array_addressing() | |
320 | |
321 // Test invocation count vs threshold | |
322 Node *threshold = makecon(TypeInt::make(limit)); | |
323 Node *chk = _gvn.transform( new (C, 3) CmpUNode( cnt, threshold) ); | |
324 BoolTest::mask btest = BoolTest::lt; | |
325 Node *tst = _gvn.transform( new (C, 2) BoolNode( chk, btest) ); | |
326 // Branch to failure if threshold exceeded | |
327 { BuildCutout unless(this, tst, PROB_ALWAYS); | |
328 uncommon_trap(Deoptimization::Reason_age, | |
329 Deoptimization::Action_maybe_recompile); | |
330 } | |
331 } | |
332 | |
333 //----------------------increment_and_test_invocation_counter------------------- | |
334 void Parse::increment_and_test_invocation_counter(int limit) { | |
335 if (!count_invocations()) return; | |
336 | |
337 // Get the methodOop node. | |
338 const TypePtr* adr_type = TypeOopPtr::make_from_constant(method()); | |
339 Node *methodOop_node = makecon(adr_type); | |
340 | |
341 // Load the interpreter_invocation_counter from the methodOop. | |
342 int offset = methodOopDesc::interpreter_invocation_counter_offset_in_bytes(); | |
343 Node* adr_node = basic_plus_adr(methodOop_node, methodOop_node, offset); | |
344 Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type); | |
345 | |
346 test_counter_against_threshold(cnt, limit); | |
347 | |
348 // Add one to the counter and store | |
349 Node* incr = _gvn.transform(new (C, 3) AddINode(cnt, _gvn.intcon(1))); | |
350 store_to_memory( NULL, adr_node, incr, T_INT, adr_type ); | |
351 } | |
352 | |
353 //----------------------------method_data_addressing--------------------------- | |
354 Node* Parse::method_data_addressing(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, Node* idx, uint stride) { | |
355 // Get offset within methodDataOop of the data array | |
356 ByteSize data_offset = methodDataOopDesc::data_offset(); | |
357 | |
358 // Get cell offset of the ProfileData within data array | |
359 int cell_offset = md->dp_to_di(data->dp()); | |
360 | |
361 // Add in counter_offset, the # of bytes into the ProfileData of counter or flag | |
362 int offset = in_bytes(data_offset) + cell_offset + in_bytes(counter_offset); | |
363 | |
364 const TypePtr* adr_type = TypeOopPtr::make_from_constant(md); | |
365 Node* mdo = makecon(adr_type); | |
366 Node* ptr = basic_plus_adr(mdo, mdo, offset); | |
367 | |
368 if (stride != 0) { | |
369 Node* str = _gvn.MakeConX(stride); | |
370 Node* scale = _gvn.transform( new (C, 3) MulXNode( idx, str ) ); | |
371 ptr = _gvn.transform( new (C, 4) AddPNode( mdo, ptr, scale ) ); | |
372 } | |
373 | |
374 return ptr; | |
375 } | |
376 | |
377 //--------------------------increment_md_counter_at---------------------------- | |
378 void Parse::increment_md_counter_at(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, Node* idx, uint stride) { | |
379 Node* adr_node = method_data_addressing(md, data, counter_offset, idx, stride); | |
380 | |
381 const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); | |
382 Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type); | |
383 Node* incr = _gvn.transform(new (C, 3) AddINode(cnt, _gvn.intcon(DataLayout::counter_increment))); | |
384 store_to_memory(NULL, adr_node, incr, T_INT, adr_type ); | |
385 } | |
386 | |
387 //--------------------------test_for_osr_md_counter_at------------------------- | |
388 void Parse::test_for_osr_md_counter_at(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, int limit) { | |
389 Node* adr_node = method_data_addressing(md, data, counter_offset); | |
390 | |
391 const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); | |
392 Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type); | |
393 | |
394 test_counter_against_threshold(cnt, limit); | |
395 } | |
396 | |
397 //-------------------------------set_md_flag_at-------------------------------- | |
398 void Parse::set_md_flag_at(ciMethodData* md, ciProfileData* data, int flag_constant) { | |
399 Node* adr_node = method_data_addressing(md, data, DataLayout::flags_offset()); | |
400 | |
401 const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); | |
402 Node* flags = make_load(NULL, adr_node, TypeInt::BYTE, T_BYTE, adr_type); | |
403 Node* incr = _gvn.transform(new (C, 3) OrINode(flags, _gvn.intcon(flag_constant))); | |
404 store_to_memory(NULL, adr_node, incr, T_BYTE, adr_type); | |
405 } | |
406 | |
407 //----------------------------profile_taken_branch----------------------------- | |
408 void Parse::profile_taken_branch(int target_bci, bool force_update) { | |
409 // This is a potential osr_site if we have a backedge. | |
410 int cur_bci = bci(); | |
411 bool osr_site = | |
412 (target_bci <= cur_bci) && count_invocations() && UseOnStackReplacement; | |
413 | |
414 // If we are going to OSR, restart at the target bytecode. | |
415 set_bci(target_bci); | |
416 | |
417 // To do: factor out the the limit calculations below. These duplicate | |
418 // the similar limit calculations in the interpreter. | |
419 | |
420 if (method_data_update() || force_update) { | |
421 ciMethodData* md = method()->method_data(); | |
422 assert(md != NULL, "expected valid ciMethodData"); | |
423 ciProfileData* data = md->bci_to_data(cur_bci); | |
424 assert(data->is_JumpData(), "need JumpData for taken branch"); | |
425 increment_md_counter_at(md, data, JumpData::taken_offset()); | |
426 } | |
427 | |
428 // In the new tiered system this is all we need to do. In the old | |
429 // (c2 based) tiered sytem we must do the code below. | |
430 #ifndef TIERED | |
431 if (method_data_update()) { | |
432 ciMethodData* md = method()->method_data(); | |
433 if (osr_site) { | |
434 ciProfileData* data = md->bci_to_data(cur_bci); | |
435 int limit = (CompileThreshold | |
436 * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100; | |
437 test_for_osr_md_counter_at(md, data, JumpData::taken_offset(), limit); | |
438 } | |
439 } else { | |
440 // With method data update off, use the invocation counter to trigger an | |
441 // OSR compilation, as done in the interpreter. | |
442 if (osr_site) { | |
443 int limit = (CompileThreshold * OnStackReplacePercentage) / 100; | |
444 increment_and_test_invocation_counter(limit); | |
445 } | |
446 } | |
447 #endif // TIERED | |
448 | |
449 // Restore the original bytecode. | |
450 set_bci(cur_bci); | |
451 } | |
452 | |
453 //--------------------------profile_not_taken_branch--------------------------- | |
454 void Parse::profile_not_taken_branch(bool force_update) { | |
455 | |
456 if (method_data_update() || force_update) { | |
457 ciMethodData* md = method()->method_data(); | |
458 assert(md != NULL, "expected valid ciMethodData"); | |
459 ciProfileData* data = md->bci_to_data(bci()); | |
460 assert(data->is_BranchData(), "need BranchData for not taken branch"); | |
461 increment_md_counter_at(md, data, BranchData::not_taken_offset()); | |
462 } | |
463 | |
464 } | |
465 | |
466 //---------------------------------profile_call-------------------------------- | |
467 void Parse::profile_call(Node* receiver) { | |
468 if (!method_data_update()) return; | |
469 | |
470 switch (bc()) { | |
471 case Bytecodes::_invokevirtual: | |
472 case Bytecodes::_invokeinterface: | |
473 profile_receiver_type(receiver); | |
474 break; | |
475 case Bytecodes::_invokestatic: | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
196
diff
changeset
|
476 case Bytecodes::_invokedynamic: |
0 | 477 case Bytecodes::_invokespecial: |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
478 profile_generic_call(); |
0 | 479 break; |
480 default: fatal("unexpected call bytecode"); | |
481 } | |
482 } | |
483 | |
484 //------------------------------profile_generic_call--------------------------- | |
485 void Parse::profile_generic_call() { | |
486 assert(method_data_update(), "must be generating profile code"); | |
487 | |
488 ciMethodData* md = method()->method_data(); | |
489 assert(md != NULL, "expected valid ciMethodData"); | |
490 ciProfileData* data = md->bci_to_data(bci()); | |
491 assert(data->is_CounterData(), "need CounterData for not taken branch"); | |
492 increment_md_counter_at(md, data, CounterData::count_offset()); | |
493 } | |
494 | |
495 //-----------------------------profile_receiver_type--------------------------- | |
496 void Parse::profile_receiver_type(Node* receiver) { | |
497 assert(method_data_update(), "must be generating profile code"); | |
498 | |
499 ciMethodData* md = method()->method_data(); | |
500 assert(md != NULL, "expected valid ciMethodData"); | |
501 ciProfileData* data = md->bci_to_data(bci()); | |
502 assert(data->is_ReceiverTypeData(), "need ReceiverTypeData here"); | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
503 |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
504 // Skip if we aren't tracking receivers |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
505 if (TypeProfileWidth < 1) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
506 increment_md_counter_at(md, data, CounterData::count_offset()); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
507 return; |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
508 } |
0 | 509 ciReceiverTypeData* rdata = (ciReceiverTypeData*)data->as_ReceiverTypeData(); |
510 | |
511 Node* method_data = method_data_addressing(md, rdata, in_ByteSize(0)); | |
512 | |
513 // Using an adr_type of TypePtr::BOTTOM to work around anti-dep problems. | |
514 // A better solution might be to use TypeRawPtr::BOTTOM with RC_NARROW_MEM. | |
515 make_runtime_call(RC_LEAF, OptoRuntime::profile_receiver_type_Type(), | |
516 CAST_FROM_FN_PTR(address, | |
517 OptoRuntime::profile_receiver_type_C), | |
518 "profile_receiver_type_C", | |
519 TypePtr::BOTTOM, | |
520 method_data, receiver); | |
521 } | |
522 | |
523 //---------------------------------profile_ret--------------------------------- | |
524 void Parse::profile_ret(int target_bci) { | |
525 if (!method_data_update()) return; | |
526 | |
527 // Skip if we aren't tracking ret targets | |
528 if (TypeProfileWidth < 1) return; | |
529 | |
530 ciMethodData* md = method()->method_data(); | |
531 assert(md != NULL, "expected valid ciMethodData"); | |
532 ciProfileData* data = md->bci_to_data(bci()); | |
533 assert(data->is_RetData(), "need RetData for ret"); | |
534 ciRetData* ret_data = (ciRetData*)data->as_RetData(); | |
535 | |
536 // Look for the target_bci is already in the table | |
537 uint row; | |
538 bool table_full = true; | |
539 for (row = 0; row < ret_data->row_limit(); row++) { | |
540 int key = ret_data->bci(row); | |
541 table_full &= (key != RetData::no_bci); | |
542 if (key == target_bci) break; | |
543 } | |
544 | |
545 if (row >= ret_data->row_limit()) { | |
546 // The target_bci was not found in the table. | |
547 if (!table_full) { | |
548 // XXX: Make slow call to update RetData | |
549 } | |
550 return; | |
551 } | |
552 | |
553 // the target_bci is already in the table | |
554 increment_md_counter_at(md, data, RetData::bci_count_offset(row)); | |
555 } | |
556 | |
557 //--------------------------profile_null_checkcast---------------------------- | |
558 void Parse::profile_null_checkcast() { | |
559 // Set the null-seen flag, done in conjunction with the usual null check. We | |
560 // never unset the flag, so this is a one-way switch. | |
561 if (!method_data_update()) return; | |
562 | |
563 ciMethodData* md = method()->method_data(); | |
564 assert(md != NULL, "expected valid ciMethodData"); | |
565 ciProfileData* data = md->bci_to_data(bci()); | |
566 assert(data->is_BitData(), "need BitData for checkcast"); | |
567 set_md_flag_at(md, data, BitData::null_seen_byte_constant()); | |
568 } | |
569 | |
570 //-----------------------------profile_switch_case----------------------------- | |
571 void Parse::profile_switch_case(int table_index) { | |
572 if (!method_data_update()) return; | |
573 | |
574 ciMethodData* md = method()->method_data(); | |
575 assert(md != NULL, "expected valid ciMethodData"); | |
576 | |
577 ciProfileData* data = md->bci_to_data(bci()); | |
578 assert(data->is_MultiBranchData(), "need MultiBranchData for switch case"); | |
579 if (table_index >= 0) { | |
580 increment_md_counter_at(md, data, MultiBranchData::case_count_offset(table_index)); | |
581 } else { | |
582 increment_md_counter_at(md, data, MultiBranchData::default_count_offset()); | |
583 } | |
584 } |