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