Mercurial > hg > graal-compiler
annotate src/share/vm/opto/parse3.cpp @ 3992:d1bdeef3e3e2
7098282: G1: assert(interval >= 0) failed: Sanity check, referencePolicy.cpp: 76
Summary: There is a race between one thread successfully forwarding and copying the klass mirror for the SoftReference class (including the static master clock) and another thread attempting to use the master clock while attempting to discover a soft reference object. Maintain a shadow copy of the soft reference master clock and use the shadow during reference discovery and reference processing.
Reviewed-by: tonyp, brutisso, ysr
author | johnc |
---|---|
date | Wed, 12 Oct 2011 10:25:51 -0700 |
parents | 11a4af030e4b |
children | e626685e9f6c |
rev | line source |
---|---|
0 | 1 /* |
2357
8033953d67ff
7012648: move JSR 292 to package java.lang.invoke and adjust names
jrose
parents:
1972
diff
changeset
|
2 * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1252
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1252
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:
1252
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "compiler/compileLog.hpp" | |
27 #include "interpreter/linkResolver.hpp" | |
28 #include "memory/universe.inline.hpp" | |
29 #include "oops/objArrayKlass.hpp" | |
30 #include "opto/addnode.hpp" | |
31 #include "opto/memnode.hpp" | |
32 #include "opto/parse.hpp" | |
33 #include "opto/rootnode.hpp" | |
34 #include "opto/runtime.hpp" | |
35 #include "opto/subnode.hpp" | |
36 #include "runtime/deoptimization.hpp" | |
37 #include "runtime/handles.inline.hpp" | |
0 | 38 |
39 //============================================================================= | |
40 // Helper methods for _get* and _put* bytecodes | |
41 //============================================================================= | |
42 bool Parse::static_field_ok_in_clinit(ciField *field, ciMethod *method) { | |
43 // Could be the field_holder's <clinit> method, or <clinit> for a subklass. | |
44 // Better to check now than to Deoptimize as soon as we execute | |
45 assert( field->is_static(), "Only check if field is static"); | |
46 // is_being_initialized() is too generous. It allows access to statics | |
47 // by threads that are not running the <clinit> before the <clinit> finishes. | |
48 // return field->holder()->is_being_initialized(); | |
49 | |
50 // The following restriction is correct but conservative. | |
51 // It is also desirable to allow compilation of methods called from <clinit> | |
52 // but this generated code will need to be made safe for execution by | |
53 // other threads, or the transition from interpreted to compiled code would | |
54 // need to be guarded. | |
55 ciInstanceKlass *field_holder = field->holder(); | |
56 | |
57 bool access_OK = false; | |
58 if (method->holder()->is_subclass_of(field_holder)) { | |
59 if (method->is_static()) { | |
60 if (method->name() == ciSymbol::class_initializer_name()) { | |
61 // OK to access static fields inside initializer | |
62 access_OK = true; | |
63 } | |
64 } else { | |
65 if (method->name() == ciSymbol::object_initializer_name()) { | |
66 // It's also OK to access static fields inside a constructor, | |
67 // because any thread calling the constructor must first have | |
68 // synchronized on the class by executing a '_new' bytecode. | |
69 access_OK = true; | |
70 } | |
71 } | |
72 } | |
73 | |
74 return access_OK; | |
75 | |
76 } | |
77 | |
78 | |
79 void Parse::do_field_access(bool is_get, bool is_field) { | |
80 bool will_link; | |
81 ciField* field = iter().get_field(will_link); | |
82 assert(will_link, "getfield: typeflow responsibility"); | |
83 | |
84 ciInstanceKlass* field_holder = field->holder(); | |
85 | |
86 if (is_field == field->is_static()) { | |
87 // Interpreter will throw java_lang_IncompatibleClassChangeError | |
88 // Check this before allowing <clinit> methods to access static fields | |
89 uncommon_trap(Deoptimization::Reason_unhandled, | |
90 Deoptimization::Action_none); | |
91 return; | |
92 } | |
93 | |
94 if (!is_field && !field_holder->is_initialized()) { | |
95 if (!static_field_ok_in_clinit(field, method())) { | |
96 uncommon_trap(Deoptimization::Reason_uninitialized, | |
97 Deoptimization::Action_reinterpret, | |
98 NULL, "!static_field_ok_in_clinit"); | |
99 return; | |
100 } | |
101 } | |
102 | |
3901
aa67216400d3
7085404: JSR 292: VolatileCallSites should have push notification too
twisti
parents:
3852
diff
changeset
|
103 // Deoptimize on putfield writes to call site target field. |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3805
diff
changeset
|
104 if (!is_get && field->is_call_site_target()) { |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3805
diff
changeset
|
105 uncommon_trap(Deoptimization::Reason_unhandled, |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3805
diff
changeset
|
106 Deoptimization::Action_reinterpret, |
3901
aa67216400d3
7085404: JSR 292: VolatileCallSites should have push notification too
twisti
parents:
3852
diff
changeset
|
107 NULL, "put to call site target field"); |
3852
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3805
diff
changeset
|
108 return; |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3805
diff
changeset
|
109 } |
fdb992d83a87
7071653: JSR 292: call site change notification should be pushed not pulled
twisti
parents:
3805
diff
changeset
|
110 |
0 | 111 assert(field->will_link(method()->holder(), bc()), "getfield: typeflow responsibility"); |
112 | |
113 // Note: We do not check for an unloaded field type here any more. | |
114 | |
115 // Generate code for the object pointer. | |
116 Node* obj; | |
117 if (is_field) { | |
118 int obj_depth = is_get ? 0 : field->type()->size(); | |
119 obj = do_null_check(peek(obj_depth), T_OBJECT); | |
120 // Compile-time detect of null-exception? | |
121 if (stopped()) return; | |
122 | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2357
diff
changeset
|
123 #ifdef ASSERT |
0 | 124 const TypeInstPtr *tjp = TypeInstPtr::make(TypePtr::NotNull, iter().get_declared_field_holder()); |
125 assert(_gvn.type(obj)->higher_equal(tjp), "cast_up is no longer needed"); | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2357
diff
changeset
|
126 #endif |
0 | 127 |
128 if (is_get) { | |
129 --_sp; // pop receiver before getting | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2357
diff
changeset
|
130 do_get_xxx(obj, field, is_field); |
0 | 131 } else { |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2357
diff
changeset
|
132 do_put_xxx(obj, field, is_field); |
0 | 133 --_sp; // pop receiver after putting |
134 } | |
135 } else { | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2357
diff
changeset
|
136 const TypeInstPtr* tip = TypeInstPtr::make(field_holder->java_mirror()); |
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2357
diff
changeset
|
137 obj = _gvn.makecon(tip); |
0 | 138 if (is_get) { |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2357
diff
changeset
|
139 do_get_xxx(obj, field, is_field); |
0 | 140 } else { |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2357
diff
changeset
|
141 do_put_xxx(obj, field, is_field); |
0 | 142 } |
143 } | |
144 } | |
145 | |
146 | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2357
diff
changeset
|
147 void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { |
0 | 148 // Does this field have a constant value? If so, just push the value. |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
149 if (field->is_constant()) { |
3902
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3901
diff
changeset
|
150 // final field |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
151 if (field->is_static()) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
152 // final static field |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
153 if (push_constant(field->constant_value())) |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
154 return; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
155 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
156 else { |
3902
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3901
diff
changeset
|
157 // final non-static field |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3901
diff
changeset
|
158 // Treat final non-static fields of trusted classes (classes in |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3901
diff
changeset
|
159 // java.lang.invoke and sun.invoke packages and subpackages) as |
11a4af030e4b
7071709: JSR 292: switchpoint invalidation should be pushed not pulled
twisti
parents:
3901
diff
changeset
|
160 // compile time constants. |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
161 if (obj->is_Con()) { |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
162 const TypeOopPtr* oop_ptr = obj->bottom_type()->isa_oopptr(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
163 ciObject* constant_oop = oop_ptr->const_oop(); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
164 ciConstant constant = field->constant_value_of(constant_oop); |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
165 if (push_constant(constant, true)) |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
166 return; |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
167 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
168 } |
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
169 } |
0 | 170 |
171 ciType* field_klass = field->type(); | |
172 bool is_vol = field->is_volatile(); | |
173 | |
174 // Compute address and memory type. | |
175 int offset = field->offset_in_bytes(); | |
176 const TypePtr* adr_type = C->alias_type(field)->adr_type(); | |
177 Node *adr = basic_plus_adr(obj, obj, offset); | |
178 BasicType bt = field->layout_type(); | |
179 | |
180 // Build the resultant type of the load | |
181 const Type *type; | |
182 | |
183 bool must_assert_null = false; | |
184 | |
185 if( bt == T_OBJECT ) { | |
186 if (!field->type()->is_loaded()) { | |
187 type = TypeInstPtr::BOTTOM; | |
188 must_assert_null = true; | |
1138
dd57230ba8fe
6893268: additional dynamic language related optimizations in C2
twisti
parents:
1100
diff
changeset
|
189 } else if (field->is_constant() && field->is_static()) { |
0 | 190 // This can happen if the constant oop is non-perm. |
191 ciObject* con = field->constant_value().as_object(); | |
192 // Do not "join" in the previous type; it doesn't add value, | |
193 // and may yield a vacuous result if the field is of interface type. | |
194 type = TypeOopPtr::make_from_constant(con)->isa_oopptr(); | |
195 assert(type != NULL, "field singleton type must be consistent"); | |
196 } else { | |
197 type = TypeOopPtr::make_from_klass(field_klass->as_klass()); | |
198 } | |
199 } else { | |
200 type = Type::get_const_basic_type(bt); | |
201 } | |
202 // Build the load. | |
203 Node* ld = make_load(NULL, adr, type, bt, adr_type, is_vol); | |
204 | |
205 // Adjust Java stack | |
206 if (type2size[bt] == 1) | |
207 push(ld); | |
208 else | |
209 push_pair(ld); | |
210 | |
211 if (must_assert_null) { | |
212 // Do not take a trap here. It's possible that the program | |
213 // will never load the field's class, and will happily see | |
214 // null values in this field forever. Don't stumble into a | |
215 // trap for such a program, or we might get a long series | |
216 // of useless recompilations. (Or, we might load a class | |
217 // which should not be loaded.) If we ever see a non-null | |
218 // value, we will then trap and recompile. (The trap will | |
219 // not need to mention the class index, since the class will | |
220 // already have been loaded if we ever see a non-null value.) | |
221 // uncommon_trap(iter().get_field_signature_index()); | |
222 #ifndef PRODUCT | |
223 if (PrintOpto && (Verbose || WizardMode)) { | |
224 method()->print_name(); tty->print_cr(" asserting nullness of field at bci: %d", bci()); | |
225 } | |
226 #endif | |
227 if (C->log() != NULL) { | |
228 C->log()->elem("assert_null reason='field' klass='%d'", | |
229 C->log()->identify(field->type())); | |
230 } | |
231 // If there is going to be a trap, put it at the next bytecode: | |
232 set_bci(iter().next_bci()); | |
233 do_null_assert(peek(), T_OBJECT); | |
234 set_bci(iter().cur_bci()); // put it back | |
235 } | |
236 | |
237 // If reference is volatile, prevent following memory ops from | |
238 // floating up past the volatile read. Also prevents commoning | |
239 // another volatile read. | |
240 if (field->is_volatile()) { | |
241 // Memory barrier includes bogus read of value to force load BEFORE membar | |
242 insert_mem_bar(Op_MemBarAcquire, ld); | |
243 } | |
244 } | |
245 | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2357
diff
changeset
|
246 void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) { |
0 | 247 bool is_vol = field->is_volatile(); |
248 // If reference is volatile, prevent following memory ops from | |
249 // floating down past the volatile write. Also prevents commoning | |
250 // another volatile read. | |
251 if (is_vol) insert_mem_bar(Op_MemBarRelease); | |
252 | |
253 // Compute address and memory type. | |
254 int offset = field->offset_in_bytes(); | |
255 const TypePtr* adr_type = C->alias_type(field)->adr_type(); | |
256 Node* adr = basic_plus_adr(obj, obj, offset); | |
257 BasicType bt = field->layout_type(); | |
258 // Value to be stored | |
259 Node* val = type2size[bt] == 1 ? pop() : pop_pair(); | |
260 // Round doubles before storing | |
261 if (bt == T_DOUBLE) val = dstore_rounding(val); | |
262 | |
263 // Store the value. | |
264 Node* store; | |
265 if (bt == T_OBJECT) { | |
825 | 266 const TypeOopPtr* field_type; |
0 | 267 if (!field->type()->is_loaded()) { |
268 field_type = TypeInstPtr::BOTTOM; | |
269 } else { | |
270 field_type = TypeOopPtr::make_from_klass(field->type()->as_klass()); | |
271 } | |
272 store = store_oop_to_object( control(), obj, adr, adr_type, val, field_type, bt); | |
273 } else { | |
274 store = store_to_memory( control(), adr, val, bt, adr_type, is_vol ); | |
275 } | |
276 | |
277 // If reference is volatile, prevent following volatiles ops from | |
278 // floating up before the volatile write. | |
279 if (is_vol) { | |
280 // First place the specific membar for THIS volatile index. This first | |
281 // membar is dependent on the store, keeping any other membars generated | |
282 // below from floating up past the store. | |
283 int adr_idx = C->get_alias_index(adr_type); | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
989
diff
changeset
|
284 insert_mem_bar_volatile(Op_MemBarVolatile, adr_idx, store); |
0 | 285 |
286 // Now place a membar for AliasIdxBot for the unknown yet-to-be-parsed | |
287 // volatile alias indices. Skip this if the membar is redundant. | |
288 if (adr_idx != Compile::AliasIdxBot) { | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
989
diff
changeset
|
289 insert_mem_bar_volatile(Op_MemBarVolatile, Compile::AliasIdxBot, store); |
0 | 290 } |
291 | |
292 // Finally, place alias-index-specific membars for each volatile index | |
293 // that isn't the adr_idx membar. Typically there's only 1 or 2. | |
294 for( int i = Compile::AliasIdxRaw; i < C->num_alias_types(); i++ ) { | |
295 if (i != adr_idx && C->alias_type(i)->is_volatile()) { | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
989
diff
changeset
|
296 insert_mem_bar_volatile(Op_MemBarVolatile, i, store); |
0 | 297 } |
298 } | |
299 } | |
300 | |
301 // If the field is final, the rules of Java say we are in <init> or <clinit>. | |
302 // Note the presence of writes to final non-static fields, so that we | |
303 // can insert a memory barrier later on to keep the writes from floating | |
304 // out of the constructor. | |
305 if (is_field && field->is_final()) { | |
306 set_wrote_final(true); | |
307 } | |
308 } | |
309 | |
310 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
311 bool Parse::push_constant(ciConstant constant, bool require_constant) { |
0 | 312 switch (constant.basic_type()) { |
313 case T_BOOLEAN: push( intcon(constant.as_boolean()) ); break; | |
314 case T_INT: push( intcon(constant.as_int()) ); break; | |
315 case T_CHAR: push( intcon(constant.as_char()) ); break; | |
316 case T_BYTE: push( intcon(constant.as_byte()) ); break; | |
317 case T_SHORT: push( intcon(constant.as_short()) ); break; | |
318 case T_FLOAT: push( makecon(TypeF::make(constant.as_float())) ); break; | |
319 case T_DOUBLE: push_pair( makecon(TypeD::make(constant.as_double())) ); break; | |
320 case T_LONG: push_pair( longcon(constant.as_long()) ); break; | |
321 case T_ARRAY: | |
322 case T_OBJECT: { | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
323 // cases: |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
324 // can_be_constant = (oop not scavengable || ScavengeRootsInCode != 0) |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
325 // should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2) |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
326 // An oop is not scavengable if it is in the perm gen. |
0 | 327 ciObject* oop_constant = constant.as_object(); |
328 if (oop_constant->is_null_object()) { | |
329 push( zerocon(T_OBJECT) ); | |
330 break; | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
331 } else if (require_constant || oop_constant->should_be_constant()) { |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
332 push( makecon(TypeOopPtr::make_from_constant(oop_constant, require_constant)) ); |
0 | 333 break; |
334 } else { | |
335 // we cannot inline the oop, but we can use it later to narrow a type | |
336 return false; | |
337 } | |
338 } | |
339 case T_ILLEGAL: { | |
340 // Invalid ciConstant returned due to OutOfMemoryError in the CI | |
341 assert(C->env()->failing(), "otherwise should not see this"); | |
342 // These always occur because of object types; we are going to | |
343 // bail out anyway, so make the stack depths match up | |
344 push( zerocon(T_OBJECT) ); | |
345 return false; | |
346 } | |
347 default: | |
348 ShouldNotReachHere(); | |
349 return false; | |
350 } | |
351 | |
352 // success | |
353 return true; | |
354 } | |
355 | |
356 | |
357 | |
358 //============================================================================= | |
359 void Parse::do_anewarray() { | |
360 bool will_link; | |
361 ciKlass* klass = iter().get_klass(will_link); | |
362 | |
363 // Uncommon Trap when class that array contains is not loaded | |
364 // we need the loaded class for the rest of graph; do not | |
365 // initialize the container class (see Java spec)!!! | |
366 assert(will_link, "anewarray: typeflow responsibility"); | |
367 | |
368 ciObjArrayKlass* array_klass = ciObjArrayKlass::make(klass); | |
369 // Check that array_klass object is loaded | |
370 if (!array_klass->is_loaded()) { | |
371 // Generate uncommon_trap for unloaded array_class | |
372 uncommon_trap(Deoptimization::Reason_unloaded, | |
373 Deoptimization::Action_reinterpret, | |
374 array_klass); | |
375 return; | |
376 } | |
377 | |
378 kill_dead_locals(); | |
379 | |
380 const TypeKlassPtr* array_klass_type = TypeKlassPtr::make(array_klass); | |
381 Node* count_val = pop(); | |
730
9c6be3edf0dc
6589834: deoptimization problem with -XX:+DeoptimizeALot
cfang
parents:
196
diff
changeset
|
382 Node* obj = new_array(makecon(array_klass_type), count_val, 1); |
0 | 383 push(obj); |
384 } | |
385 | |
386 | |
387 void Parse::do_newarray(BasicType elem_type) { | |
388 kill_dead_locals(); | |
389 | |
390 Node* count_val = pop(); | |
391 const TypeKlassPtr* array_klass = TypeKlassPtr::make(ciTypeArrayKlass::make(elem_type)); | |
730
9c6be3edf0dc
6589834: deoptimization problem with -XX:+DeoptimizeALot
cfang
parents:
196
diff
changeset
|
392 Node* obj = new_array(makecon(array_klass), count_val, 1); |
0 | 393 // Push resultant oop onto stack |
394 push(obj); | |
395 } | |
396 | |
397 // Expand simple expressions like new int[3][5] and new Object[2][nonConLen]. | |
398 // Also handle the degenerate 1-dimensional case of anewarray. | |
730
9c6be3edf0dc
6589834: deoptimization problem with -XX:+DeoptimizeALot
cfang
parents:
196
diff
changeset
|
399 Node* Parse::expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, int ndimensions, int nargs) { |
0 | 400 Node* length = lengths[0]; |
401 assert(length != NULL, ""); | |
730
9c6be3edf0dc
6589834: deoptimization problem with -XX:+DeoptimizeALot
cfang
parents:
196
diff
changeset
|
402 Node* array = new_array(makecon(TypeKlassPtr::make(array_klass)), length, nargs); |
0 | 403 if (ndimensions > 1) { |
404 jint length_con = find_int_con(length, -1); | |
405 guarantee(length_con >= 0, "non-constant multianewarray"); | |
406 ciArrayKlass* array_klass_1 = array_klass->as_obj_array_klass()->element_klass()->as_array_klass(); | |
407 const TypePtr* adr_type = TypeAryPtr::OOPS; | |
827
bf3489cc0aa0
6856025: assert(_base >= OopPtr && _base <= KlassPtr,"Not a Java pointer")
never
parents:
825
diff
changeset
|
408 const TypeOopPtr* elemtype = _gvn.type(array)->is_aryptr()->elem()->make_oopptr(); |
0 | 409 const intptr_t header = arrayOopDesc::base_offset_in_bytes(T_OBJECT); |
410 for (jint i = 0; i < length_con; i++) { | |
730
9c6be3edf0dc
6589834: deoptimization problem with -XX:+DeoptimizeALot
cfang
parents:
196
diff
changeset
|
411 Node* elem = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1, nargs); |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
106
diff
changeset
|
412 intptr_t offset = header + ((intptr_t)i << LogBytesPerHeapOop); |
0 | 413 Node* eaddr = basic_plus_adr(array, offset); |
414 store_oop_to_array(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT); | |
415 } | |
416 } | |
417 return array; | |
418 } | |
419 | |
420 void Parse::do_multianewarray() { | |
421 int ndimensions = iter().get_dimensions(); | |
422 | |
423 // the m-dimensional array | |
424 bool will_link; | |
425 ciArrayKlass* array_klass = iter().get_klass(will_link)->as_array_klass(); | |
426 assert(will_link, "multianewarray: typeflow responsibility"); | |
427 | |
428 // Note: Array classes are always initialized; no is_initialized check. | |
429 | |
430 kill_dead_locals(); | |
431 | |
432 // get the lengths from the stack (first dimension is on top) | |
3805
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
433 Node** length = NEW_RESOURCE_ARRAY(Node*, ndimensions + 1); |
0 | 434 length[ndimensions] = NULL; // terminating null for make_runtime_call |
435 int j; | |
436 for (j = ndimensions-1; j >= 0 ; j--) length[j] = pop(); | |
437 | |
438 // The original expression was of this form: new T[length0][length1]... | |
439 // It is often the case that the lengths are small (except the last). | |
440 // If that happens, use the fast 1-d creator a constant number of times. | |
441 const jint expand_limit = MIN2((juint)MultiArrayExpandLimit, (juint)100); | |
442 jint expand_count = 1; // count of allocations in the expansion | |
443 jint expand_fanout = 1; // running total fanout | |
444 for (j = 0; j < ndimensions-1; j++) { | |
445 jint dim_con = find_int_con(length[j], -1); | |
446 expand_fanout *= dim_con; | |
447 expand_count += expand_fanout; // count the level-J sub-arrays | |
106 | 448 if (dim_con <= 0 |
0 | 449 || dim_con > expand_limit |
450 || expand_count > expand_limit) { | |
451 expand_count = 0; | |
452 break; | |
453 } | |
454 } | |
455 | |
456 // Can use multianewarray instead of [a]newarray if only one dimension, | |
457 // or if all non-final dimensions are small constants. | |
1252
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1138
diff
changeset
|
458 if (ndimensions == 1 || (1 <= expand_count && expand_count <= expand_limit)) { |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1138
diff
changeset
|
459 Node* obj = NULL; |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1138
diff
changeset
|
460 // Set the original stack and the reexecute bit for the interpreter |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1138
diff
changeset
|
461 // to reexecute the multianewarray bytecode if deoptimization happens. |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1138
diff
changeset
|
462 // Do it unconditionally even for one dimension multianewarray. |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1138
diff
changeset
|
463 // Note: the reexecute bit will be set in GraphKit::add_safepoint_edges() |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1138
diff
changeset
|
464 // when AllocateArray node for newarray is created. |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1138
diff
changeset
|
465 { PreserveReexecuteState preexecs(this); |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1138
diff
changeset
|
466 _sp += ndimensions; |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1138
diff
changeset
|
467 // Pass 0 as nargs since uncommon trap code does not need to restore stack. |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1138
diff
changeset
|
468 obj = expand_multianewarray(array_klass, &length[0], ndimensions, 0); |
f516d5d7a019
6910605: C2: NullPointerException/ClassCaseException is thrown when C2 with DeoptimizeALot is used
kvn
parents:
1138
diff
changeset
|
469 } //original reexecute and sp are set back here |
0 | 470 push(obj); |
471 return; | |
472 } | |
473 | |
474 address fun = NULL; | |
475 switch (ndimensions) { | |
3805
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
476 case 1: ShouldNotReachHere(); break; |
0 | 477 case 2: fun = OptoRuntime::multianewarray2_Java(); break; |
478 case 3: fun = OptoRuntime::multianewarray3_Java(); break; | |
479 case 4: fun = OptoRuntime::multianewarray4_Java(); break; | |
480 case 5: fun = OptoRuntime::multianewarray5_Java(); break; | |
481 }; | |
3805
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
482 Node* c = NULL; |
0 | 483 |
3805
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
484 if (fun != NULL) { |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
485 c = make_runtime_call(RC_NO_LEAF | RC_NO_IO, |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
486 OptoRuntime::multianewarray_Type(ndimensions), |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
487 fun, NULL, TypeRawPtr::BOTTOM, |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
488 makecon(TypeKlassPtr::make(array_klass)), |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
489 length[0], length[1], length[2], |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
490 length[3], length[4]); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
491 } else { |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
492 // Create a java array for dimension sizes |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
493 Node* dims = NULL; |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
494 { PreserveReexecuteState preexecs(this); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
495 _sp += ndimensions; |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
496 Node* dims_array_klass = makecon(TypeKlassPtr::make(ciArrayKlass::make(ciType::make(T_INT)))); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
497 dims = new_array(dims_array_klass, intcon(ndimensions), 0); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
498 |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
499 // Fill-in it with values |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
500 for (j = 0; j < ndimensions; j++) { |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
501 Node *dims_elem = array_element_address(dims, intcon(j), T_INT); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
502 store_to_memory(control(), dims_elem, length[j], T_INT, TypeAryPtr::INTS); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
503 } |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
504 } |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
505 |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
506 c = make_runtime_call(RC_NO_LEAF | RC_NO_IO, |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
507 OptoRuntime::multianewarrayN_Type(), |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
508 OptoRuntime::multianewarrayN_Java(), NULL, TypeRawPtr::BOTTOM, |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
509 makecon(TypeKlassPtr::make(array_klass)), |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
510 dims); |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
511 } |
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
512 |
0 | 513 Node* res = _gvn.transform(new (C, 1) ProjNode(c, TypeFunc::Parms)); |
514 | |
515 const Type* type = TypeOopPtr::make_from_klass_raw(array_klass); | |
516 | |
517 // Improve the type: We know it's not null, exact, and of a given length. | |
518 type = type->is_ptr()->cast_to_ptr_type(TypePtr::NotNull); | |
519 type = type->is_aryptr()->cast_to_exactness(true); | |
520 | |
521 const TypeInt* ltype = _gvn.find_int_type(length[0]); | |
522 if (ltype != NULL) | |
523 type = type->is_aryptr()->cast_to_size(ltype); | |
524 | |
3805
263247c478c5
7058510: multinewarray with 6 dimensions uncommon traps in server compiler
iveresov
parents:
2376
diff
changeset
|
525 // We cannot sharpen the nested sub-arrays, since the top level is mutable. |
0 | 526 |
527 Node* cast = _gvn.transform( new (C, 2) CheckCastPPNode(control(), res, type) ); | |
528 push(cast); | |
529 | |
530 // Possible improvements: | |
531 // - Make a fast path for small multi-arrays. (W/ implicit init. loops.) | |
532 // - Issue CastII against length[*] values, to TypeInt::POS. | |
533 } |