Mercurial > hg > truffle
annotate src/share/vm/opto/parseHelper.cpp @ 9126:bc26f978b0ce
HotSpotResolvedObjectType: implement hasFinalizeSubclass() correctly
don't use the (wrong) cached value, but ask the runtime on each request.
Fixes regression on xml.* benchmarks @ specjvm2008. The problem was:
After the constructor of Object was deoptimized due to an assumption violation,
it was recompiled again after some time. However, on recompilation, the value
of hasFinalizeSubclass for the class was not updated and it was compiled again
with a, now wrong, assumption, which then triggers deoptimization again.
This was repeated until it hit the recompilation limit (defined by
PerMethodRecompilationCutoff), and therefore only executed by the interpreter
from now on, causing the performance regression.
author | Bernhard Urban <bernhard.urban@jku.at> |
---|---|
date | Mon, 15 Apr 2013 19:54:58 +0200 |
parents | beebba0acc11 |
children | aeaca88565e6 |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
2 * Copyright (c) 1998, 2012, 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 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
46 Node* thread = _gvn.transform( new (C) ThreadLocalNode() ); |
0 | 47 |
48 // Get method | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
49 const TypePtr* method_type = TypeMetadataPtr::make(method); |
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. | |
4823
9a28ddfc1f4a
7123910: Some CTW tests crash VM: is_loaded() && that->is_loaded()
roland
parents:
4771
diff
changeset
|
74 const TypeOopPtr *tp = _gvn.type(obj)->isa_oopptr(); |
9a28ddfc1f4a
7123910: Some CTW tests crash VM: is_loaded() && that->is_loaded()
roland
parents:
4771
diff
changeset
|
75 if (!will_link || (tp && tp->klass() && !tp->klass()->is_loaded())) { |
0 | 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 } | |
4823
9a28ddfc1f4a
7123910: Some CTW tests crash VM: is_loaded() && that->is_loaded()
roland
parents:
4771
diff
changeset
|
81 if (tp && tp->klass() && !tp->klass()->is_loaded()) { |
0 | 82 // %%% Cannot happen? |
83 C->log()->elem("assert_null reason='checkcast source' klass='%d'", | |
84 C->log()->identify(tp->klass())); | |
85 } | |
86 } | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6831
diff
changeset
|
87 null_assert(obj); |
0 | 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 } | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6831
diff
changeset
|
119 null_assert(peek()); |
0 | 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 | |
7194
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6831
diff
changeset
|
142 // Shorthand access to array store elements without popping them. |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6831
diff
changeset
|
143 Node *obj = peek(0); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6831
diff
changeset
|
144 Node *idx = peek(1); |
beebba0acc11
7172640: C2: instrinsic implementations in LibraryCallKit should use argument() instead of pop()
twisti
parents:
6831
diff
changeset
|
145 Node *ary = peek(2); |
0 | 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); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
178 Node* cmp = _gvn.transform(new (C) CmpPNode( array_klass, con )); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
179 Node* bol = _gvn.transform(new (C) BoolNode( cmp, BoolTest::eq )); |
0 | 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 | |
6831
d8ce2825b193
8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
coleenp
parents:
6804
diff
changeset
|
203 int element_klass_offset = in_bytes(ObjArrayKlass::element_klass_offset()); |
0 | 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 |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
218 Node* cur_thread = _gvn.transform( new (C) ThreadLocalNode() ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
219 Node* merge = new (C) RegionNode(3); |
1645
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 |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
223 Node* init_thread_offset = _gvn.MakeConX(in_bytes(InstanceKlass::init_thread_offset())); |
1645
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 |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
231 Node* init_state_offset = _gvn.MakeConX(in_bytes(InstanceKlass::init_state_offset())); |
1645
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); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
233 // Use T_BOOLEAN for InstanceKlass::_init_state so the compiler |
4739
52b5d32fbfaf
7117052: instanceKlass::_init_state can be u1 type
coleenp
parents:
1972
diff
changeset
|
234 // can generate code to load it as unsigned byte. |
52b5d32fbfaf
7117052: instanceKlass::_init_state can be u1 type
coleenp
parents:
1972
diff
changeset
|
235 Node* init_state = make_load(NULL, adr_node, TypeInt::UBYTE, T_BOOLEAN); |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
236 Node* being_init = _gvn.intcon(InstanceKlass::being_initialized); |
1645
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
237 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
|
238 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
|
239 set_control(IfTrue(iff)); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
240 merge->set_req(2, IfFalse(iff)); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
241 |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
242 PreserveJVMState pjvms(this); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
243 record_for_igvn(merge); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
244 set_control(merge); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
245 |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
246 uncommon_trap(Deoptimization::Reason_uninitialized, |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
247 Deoptimization::Action_reinterpret, |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
248 klass); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
249 } |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
250 |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
251 |
0 | 252 //------------------------------do_new----------------------------------------- |
253 void Parse::do_new() { | |
254 kill_dead_locals(); | |
255 | |
256 bool will_link; | |
257 ciInstanceKlass* klass = iter().get_klass(will_link)->as_instance_klass(); | |
258 assert(will_link, "_new: typeflow responsibility"); | |
259 | |
260 // 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
|
261 if (!klass->is_initialized() && !klass->is_being_initialized() || |
0 | 262 klass->is_abstract() || klass->is_interface() || |
263 klass->name() == ciSymbol::java_lang_Class() || | |
264 iter().is_unresolved_klass()) { | |
265 uncommon_trap(Deoptimization::Reason_uninitialized, | |
266 Deoptimization::Action_reinterpret, | |
267 klass); | |
268 return; | |
269 } | |
1645
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
270 if (klass->is_being_initialized()) { |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
271 emit_guard_for_new(klass); |
3941674cc7fa
6958668: repeated uncommon trapping for new of klass which is being initialized
never
parents:
1552
diff
changeset
|
272 } |
0 | 273 |
274 Node* kls = makecon(TypeKlassPtr::make(klass)); | |
275 Node* obj = new_instance(kls); | |
276 | |
277 // Push resultant oop onto stack | |
278 push(obj); | |
1080
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
279 |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
280 // Keep track of whether opportunities exist for StringBuilder |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
281 // optimizations. |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
282 if (OptimizeStringConcat && |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
283 (klass == C->env()->StringBuilder_klass() || |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
284 klass == C->env()->StringBuffer_klass())) { |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
285 C->set_has_stringbuilder(true); |
7c57aead6d3e
6892658: C2 should optimize some stringbuilder patterns
never
parents:
844
diff
changeset
|
286 } |
0 | 287 } |
288 | |
289 #ifndef PRODUCT | |
290 //------------------------------dump_map_adr_mem------------------------------- | |
291 // Debug dump of the mapping from address types to MergeMemNode indices. | |
292 void Parse::dump_map_adr_mem() const { | |
293 tty->print_cr("--- Mapping from address types to memory Nodes ---"); | |
294 MergeMemNode *mem = map() == NULL ? NULL : (map()->memory()->is_MergeMem() ? | |
295 map()->memory()->as_MergeMem() : NULL); | |
296 for (uint i = 0; i < (uint)C->num_alias_types(); i++) { | |
297 C->alias_type(i)->print_on(tty); | |
298 tty->print("\t"); | |
299 // Node mapping, if any | |
300 if (mem && i < mem->req() && mem->in(i) && mem->in(i) != mem->empty_memory()) { | |
301 mem->in(i)->dump(); | |
302 } else { | |
303 tty->cr(); | |
304 } | |
305 } | |
306 } | |
307 | |
308 #endif | |
309 | |
310 | |
311 //============================================================================= | |
312 // | |
313 // parser methods for profiling | |
314 | |
315 | |
316 //----------------------test_counter_against_threshold ------------------------ | |
317 void Parse::test_counter_against_threshold(Node* cnt, int limit) { | |
318 // Test the counter against the limit and uncommon trap if greater. | |
319 | |
320 // This code is largely copied from the range check code in | |
321 // array_addressing() | |
322 | |
323 // Test invocation count vs threshold | |
324 Node *threshold = makecon(TypeInt::make(limit)); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
325 Node *chk = _gvn.transform( new (C) CmpUNode( cnt, threshold) ); |
0 | 326 BoolTest::mask btest = BoolTest::lt; |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
327 Node *tst = _gvn.transform( new (C) BoolNode( chk, btest) ); |
0 | 328 // Branch to failure if threshold exceeded |
329 { BuildCutout unless(this, tst, PROB_ALWAYS); | |
330 uncommon_trap(Deoptimization::Reason_age, | |
331 Deoptimization::Action_maybe_recompile); | |
332 } | |
333 } | |
334 | |
335 //----------------------increment_and_test_invocation_counter------------------- | |
336 void Parse::increment_and_test_invocation_counter(int limit) { | |
337 if (!count_invocations()) return; | |
338 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
339 // Get the Method* node. |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
340 const TypePtr* adr_type = TypeMetadataPtr::make(method()); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
341 Node *method_node = makecon(adr_type); |
0 | 342 |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
343 // Load the interpreter_invocation_counter from the Method*. |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
344 int offset = Method::interpreter_invocation_counter_offset_in_bytes(); |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
345 Node* adr_node = basic_plus_adr(method_node, method_node, offset); |
0 | 346 Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type); |
347 | |
348 test_counter_against_threshold(cnt, limit); | |
349 | |
350 // Add one to the counter and store | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
351 Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(1))); |
0 | 352 store_to_memory( NULL, adr_node, incr, T_INT, adr_type ); |
353 } | |
354 | |
355 //----------------------------method_data_addressing--------------------------- | |
356 Node* Parse::method_data_addressing(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, Node* idx, uint stride) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
357 // Get offset within MethodData* of the data array |
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
358 ByteSize data_offset = MethodData::data_offset(); |
0 | 359 |
360 // Get cell offset of the ProfileData within data array | |
361 int cell_offset = md->dp_to_di(data->dp()); | |
362 | |
363 // Add in counter_offset, the # of bytes into the ProfileData of counter or flag | |
364 int offset = in_bytes(data_offset) + cell_offset + in_bytes(counter_offset); | |
365 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
4823
diff
changeset
|
366 const TypePtr* adr_type = TypeMetadataPtr::make(md); |
0 | 367 Node* mdo = makecon(adr_type); |
368 Node* ptr = basic_plus_adr(mdo, mdo, offset); | |
369 | |
370 if (stride != 0) { | |
371 Node* str = _gvn.MakeConX(stride); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
372 Node* scale = _gvn.transform( new (C) MulXNode( idx, str ) ); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
373 ptr = _gvn.transform( new (C) AddPNode( mdo, ptr, scale ) ); |
0 | 374 } |
375 | |
376 return ptr; | |
377 } | |
378 | |
379 //--------------------------increment_md_counter_at---------------------------- | |
380 void Parse::increment_md_counter_at(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, Node* idx, uint stride) { | |
381 Node* adr_node = method_data_addressing(md, data, counter_offset, idx, stride); | |
382 | |
383 const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); | |
384 Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
385 Node* incr = _gvn.transform(new (C) AddINode(cnt, _gvn.intcon(DataLayout::counter_increment))); |
0 | 386 store_to_memory(NULL, adr_node, incr, T_INT, adr_type ); |
387 } | |
388 | |
389 //--------------------------test_for_osr_md_counter_at------------------------- | |
390 void Parse::test_for_osr_md_counter_at(ciMethodData* md, ciProfileData* data, ByteSize counter_offset, int limit) { | |
391 Node* adr_node = method_data_addressing(md, data, counter_offset); | |
392 | |
393 const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); | |
394 Node* cnt = make_load(NULL, adr_node, TypeInt::INT, T_INT, adr_type); | |
395 | |
396 test_counter_against_threshold(cnt, limit); | |
397 } | |
398 | |
399 //-------------------------------set_md_flag_at-------------------------------- | |
400 void Parse::set_md_flag_at(ciMethodData* md, ciProfileData* data, int flag_constant) { | |
401 Node* adr_node = method_data_addressing(md, data, DataLayout::flags_offset()); | |
402 | |
403 const TypePtr* adr_type = _gvn.type(adr_node)->is_ptr(); | |
404 Node* flags = make_load(NULL, adr_node, TypeInt::BYTE, T_BYTE, adr_type); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6725
diff
changeset
|
405 Node* incr = _gvn.transform(new (C) OrINode(flags, _gvn.intcon(flag_constant))); |
0 | 406 store_to_memory(NULL, adr_node, incr, T_BYTE, adr_type); |
407 } | |
408 | |
409 //----------------------------profile_taken_branch----------------------------- | |
410 void Parse::profile_taken_branch(int target_bci, bool force_update) { | |
411 // This is a potential osr_site if we have a backedge. | |
412 int cur_bci = bci(); | |
413 bool osr_site = | |
414 (target_bci <= cur_bci) && count_invocations() && UseOnStackReplacement; | |
415 | |
416 // If we are going to OSR, restart at the target bytecode. | |
417 set_bci(target_bci); | |
418 | |
419 // To do: factor out the the limit calculations below. These duplicate | |
420 // the similar limit calculations in the interpreter. | |
421 | |
422 if (method_data_update() || force_update) { | |
423 ciMethodData* md = method()->method_data(); | |
424 assert(md != NULL, "expected valid ciMethodData"); | |
425 ciProfileData* data = md->bci_to_data(cur_bci); | |
426 assert(data->is_JumpData(), "need JumpData for taken branch"); | |
427 increment_md_counter_at(md, data, JumpData::taken_offset()); | |
428 } | |
429 | |
430 // In the new tiered system this is all we need to do. In the old | |
431 // (c2 based) tiered sytem we must do the code below. | |
432 #ifndef TIERED | |
433 if (method_data_update()) { | |
434 ciMethodData* md = method()->method_data(); | |
435 if (osr_site) { | |
436 ciProfileData* data = md->bci_to_data(cur_bci); | |
437 int limit = (CompileThreshold | |
438 * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100; | |
439 test_for_osr_md_counter_at(md, data, JumpData::taken_offset(), limit); | |
440 } | |
441 } else { | |
442 // With method data update off, use the invocation counter to trigger an | |
443 // OSR compilation, as done in the interpreter. | |
444 if (osr_site) { | |
445 int limit = (CompileThreshold * OnStackReplacePercentage) / 100; | |
446 increment_and_test_invocation_counter(limit); | |
447 } | |
448 } | |
449 #endif // TIERED | |
450 | |
451 // Restore the original bytecode. | |
452 set_bci(cur_bci); | |
453 } | |
454 | |
455 //--------------------------profile_not_taken_branch--------------------------- | |
456 void Parse::profile_not_taken_branch(bool force_update) { | |
457 | |
458 if (method_data_update() || force_update) { | |
459 ciMethodData* md = method()->method_data(); | |
460 assert(md != NULL, "expected valid ciMethodData"); | |
461 ciProfileData* data = md->bci_to_data(bci()); | |
462 assert(data->is_BranchData(), "need BranchData for not taken branch"); | |
463 increment_md_counter_at(md, data, BranchData::not_taken_offset()); | |
464 } | |
465 | |
466 } | |
467 | |
468 //---------------------------------profile_call-------------------------------- | |
469 void Parse::profile_call(Node* receiver) { | |
470 if (!method_data_update()) return; | |
471 | |
472 switch (bc()) { | |
473 case Bytecodes::_invokevirtual: | |
474 case Bytecodes::_invokeinterface: | |
475 profile_receiver_type(receiver); | |
476 break; | |
477 case Bytecodes::_invokestatic: | |
726
be93aad57795
6655646: dynamic languages need dynamically linked call sites
jrose
parents:
196
diff
changeset
|
478 case Bytecodes::_invokedynamic: |
0 | 479 case Bytecodes::_invokespecial: |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
480 profile_generic_call(); |
0 | 481 break; |
482 default: fatal("unexpected call bytecode"); | |
483 } | |
484 } | |
485 | |
486 //------------------------------profile_generic_call--------------------------- | |
487 void Parse::profile_generic_call() { | |
488 assert(method_data_update(), "must be generating profile code"); | |
489 | |
490 ciMethodData* md = method()->method_data(); | |
491 assert(md != NULL, "expected valid ciMethodData"); | |
492 ciProfileData* data = md->bci_to_data(bci()); | |
493 assert(data->is_CounterData(), "need CounterData for not taken branch"); | |
494 increment_md_counter_at(md, data, CounterData::count_offset()); | |
495 } | |
496 | |
497 //-----------------------------profile_receiver_type--------------------------- | |
498 void Parse::profile_receiver_type(Node* receiver) { | |
499 assert(method_data_update(), "must be generating profile code"); | |
500 | |
501 ciMethodData* md = method()->method_data(); | |
502 assert(md != NULL, "expected valid ciMethodData"); | |
503 ciProfileData* data = md->bci_to_data(bci()); | |
504 assert(data->is_ReceiverTypeData(), "need ReceiverTypeData here"); | |
1206
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
505 |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
506 // Skip if we aren't tracking receivers |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
507 if (TypeProfileWidth < 1) { |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
508 increment_md_counter_at(md, data, CounterData::count_offset()); |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
509 return; |
87684f1a88b5
6614597: Performance variability in jvm2008 xml.validation
kvn
parents:
1080
diff
changeset
|
510 } |
0 | 511 ciReceiverTypeData* rdata = (ciReceiverTypeData*)data->as_ReceiverTypeData(); |
512 | |
513 Node* method_data = method_data_addressing(md, rdata, in_ByteSize(0)); | |
514 | |
515 // Using an adr_type of TypePtr::BOTTOM to work around anti-dep problems. | |
516 // A better solution might be to use TypeRawPtr::BOTTOM with RC_NARROW_MEM. | |
517 make_runtime_call(RC_LEAF, OptoRuntime::profile_receiver_type_Type(), | |
518 CAST_FROM_FN_PTR(address, | |
519 OptoRuntime::profile_receiver_type_C), | |
520 "profile_receiver_type_C", | |
521 TypePtr::BOTTOM, | |
522 method_data, receiver); | |
523 } | |
524 | |
525 //---------------------------------profile_ret--------------------------------- | |
526 void Parse::profile_ret(int target_bci) { | |
527 if (!method_data_update()) return; | |
528 | |
529 // Skip if we aren't tracking ret targets | |
530 if (TypeProfileWidth < 1) return; | |
531 | |
532 ciMethodData* md = method()->method_data(); | |
533 assert(md != NULL, "expected valid ciMethodData"); | |
534 ciProfileData* data = md->bci_to_data(bci()); | |
535 assert(data->is_RetData(), "need RetData for ret"); | |
536 ciRetData* ret_data = (ciRetData*)data->as_RetData(); | |
537 | |
538 // Look for the target_bci is already in the table | |
539 uint row; | |
540 bool table_full = true; | |
541 for (row = 0; row < ret_data->row_limit(); row++) { | |
542 int key = ret_data->bci(row); | |
543 table_full &= (key != RetData::no_bci); | |
544 if (key == target_bci) break; | |
545 } | |
546 | |
547 if (row >= ret_data->row_limit()) { | |
548 // The target_bci was not found in the table. | |
549 if (!table_full) { | |
550 // XXX: Make slow call to update RetData | |
551 } | |
552 return; | |
553 } | |
554 | |
555 // the target_bci is already in the table | |
556 increment_md_counter_at(md, data, RetData::bci_count_offset(row)); | |
557 } | |
558 | |
559 //--------------------------profile_null_checkcast---------------------------- | |
560 void Parse::profile_null_checkcast() { | |
561 // Set the null-seen flag, done in conjunction with the usual null check. We | |
562 // never unset the flag, so this is a one-way switch. | |
563 if (!method_data_update()) return; | |
564 | |
565 ciMethodData* md = method()->method_data(); | |
566 assert(md != NULL, "expected valid ciMethodData"); | |
567 ciProfileData* data = md->bci_to_data(bci()); | |
568 assert(data->is_BitData(), "need BitData for checkcast"); | |
569 set_md_flag_at(md, data, BitData::null_seen_byte_constant()); | |
570 } | |
571 | |
572 //-----------------------------profile_switch_case----------------------------- | |
573 void Parse::profile_switch_case(int table_index) { | |
574 if (!method_data_update()) return; | |
575 | |
576 ciMethodData* md = method()->method_data(); | |
577 assert(md != NULL, "expected valid ciMethodData"); | |
578 | |
579 ciProfileData* data = md->bci_to_data(bci()); | |
580 assert(data->is_MultiBranchData(), "need MultiBranchData for switch case"); | |
581 if (table_index >= 0) { | |
582 increment_md_counter_at(md, data, MultiBranchData::case_count_offset(table_index)); | |
583 } else { | |
584 increment_md_counter_at(md, data, MultiBranchData::default_count_offset()); | |
585 } | |
586 } |