File: | jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp |
Warning: | line 728, column 32 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. | |||
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 | * | |||
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |||
20 | * or visit www.oracle.com if you need additional information or have any | |||
21 | * questions. | |||
22 | * | |||
23 | */ | |||
24 | ||||
25 | #include "precompiled.hpp" | |||
26 | #include "c1/c1_Canonicalizer.hpp" | |||
27 | #include "c1/c1_InstructionPrinter.hpp" | |||
28 | #include "c1/c1_ValueStack.hpp" | |||
29 | #include "ci/ciArray.hpp" | |||
30 | #include "runtime/sharedRuntime.hpp" | |||
31 | ||||
32 | ||||
33 | class PrintValueVisitor: public ValueVisitor { | |||
34 | void visit(Value* vp) { | |||
35 | (*vp)->print_line(); | |||
36 | } | |||
37 | }; | |||
38 | ||||
39 | void Canonicalizer::set_canonical(Value x) { | |||
40 | assert(x != NULL, "value must exist")do { if (!(x != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 40, "assert(" "x != __null" ") failed", "value must exist") ; ::breakpoint(); } } while (0); | |||
41 | // Note: we can not currently substitute root nodes which show up in | |||
42 | // the instruction stream (because the instruction list is embedded | |||
43 | // in the instructions). | |||
44 | if (canonical() != x) { | |||
45 | #ifndef PRODUCT | |||
46 | if (!x->has_printable_bci()) { | |||
47 | x->set_printable_bci(bci()); | |||
48 | } | |||
49 | #endif | |||
50 | if (PrintCanonicalization) { | |||
51 | PrintValueVisitor do_print_value; | |||
52 | canonical()->input_values_do(&do_print_value); | |||
53 | canonical()->print_line(); | |||
54 | tty->print_cr("canonicalized to:"); | |||
55 | x->input_values_do(&do_print_value); | |||
56 | x->print_line(); | |||
57 | tty->cr(); | |||
58 | } | |||
59 | assert(_canonical->type()->tag() == x->type()->tag(), "types must match")do { if (!(_canonical->type()->tag() == x->type()-> tag())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 59, "assert(" "_canonical->type()->tag() == x->type()->tag()" ") failed", "types must match"); ::breakpoint(); } } while ( 0); | |||
60 | _canonical = x; | |||
61 | } | |||
62 | } | |||
63 | ||||
64 | ||||
65 | void Canonicalizer::move_const_to_right(Op2* x) { | |||
66 | if (x->x()->type()->is_constant() && x->is_commutative()) x->swap_operands(); | |||
67 | } | |||
68 | ||||
69 | ||||
70 | void Canonicalizer::do_Op2(Op2* x) { | |||
71 | if (x->x() == x->y()) { | |||
72 | switch (x->op()) { | |||
73 | case Bytecodes::_isub: set_constant(0); return; | |||
74 | case Bytecodes::_lsub: set_constant(jlong_cast(0)); return; | |||
75 | case Bytecodes::_iand: // fall through | |||
76 | case Bytecodes::_land: // fall through | |||
77 | case Bytecodes::_ior : // fall through | |||
78 | case Bytecodes::_lor : set_canonical(x->x()); return; | |||
79 | case Bytecodes::_ixor: set_constant(0); return; | |||
80 | case Bytecodes::_lxor: set_constant(jlong_cast(0)); return; | |||
81 | default : break; | |||
82 | } | |||
83 | } | |||
84 | ||||
85 | if (x->x()->type()->is_constant() && x->y()->type()->is_constant()) { | |||
86 | // do constant folding for selected operations | |||
87 | switch (x->type()->tag()) { | |||
88 | case intTag: | |||
89 | { jint a = x->x()->type()->as_IntConstant()->value(); | |||
90 | jint b = x->y()->type()->as_IntConstant()->value(); | |||
91 | switch (x->op()) { | |||
92 | case Bytecodes::_iadd: set_constant(a + b); return; | |||
93 | case Bytecodes::_isub: set_constant(a - b); return; | |||
94 | case Bytecodes::_imul: set_constant(a * b); return; | |||
95 | case Bytecodes::_idiv: | |||
96 | if (b != 0) { | |||
97 | if (a == min_jint && b == -1) { | |||
98 | set_constant(min_jint); | |||
99 | } else { | |||
100 | set_constant(a / b); | |||
101 | } | |||
102 | return; | |||
103 | } | |||
104 | break; | |||
105 | case Bytecodes::_irem: | |||
106 | if (b != 0) { | |||
107 | if (a == min_jint && b == -1) { | |||
108 | set_constant(0); | |||
109 | } else { | |||
110 | set_constant(a % b); | |||
111 | } | |||
112 | return; | |||
113 | } | |||
114 | break; | |||
115 | case Bytecodes::_iand: set_constant(a & b); return; | |||
116 | case Bytecodes::_ior : set_constant(a | b); return; | |||
117 | case Bytecodes::_ixor: set_constant(a ^ b); return; | |||
118 | default : break; | |||
119 | } | |||
120 | } | |||
121 | break; | |||
122 | case longTag: | |||
123 | { jlong a = x->x()->type()->as_LongConstant()->value(); | |||
124 | jlong b = x->y()->type()->as_LongConstant()->value(); | |||
125 | switch (x->op()) { | |||
126 | case Bytecodes::_ladd: set_constant(a + b); return; | |||
127 | case Bytecodes::_lsub: set_constant(a - b); return; | |||
128 | case Bytecodes::_lmul: set_constant(a * b); return; | |||
129 | case Bytecodes::_ldiv: | |||
130 | if (b != 0) { | |||
131 | set_constant(SharedRuntime::ldiv(b, a)); | |||
132 | return; | |||
133 | } | |||
134 | break; | |||
135 | case Bytecodes::_lrem: | |||
136 | if (b != 0) { | |||
137 | set_constant(SharedRuntime::lrem(b, a)); | |||
138 | return; | |||
139 | } | |||
140 | break; | |||
141 | case Bytecodes::_land: set_constant(a & b); return; | |||
142 | case Bytecodes::_lor : set_constant(a | b); return; | |||
143 | case Bytecodes::_lxor: set_constant(a ^ b); return; | |||
144 | default : break; | |||
145 | } | |||
146 | } | |||
147 | break; | |||
148 | default: | |||
149 | // other cases not implemented (must be extremely careful with floats & doubles!) | |||
150 | break; | |||
151 | } | |||
152 | } | |||
153 | // make sure constant is on the right side, if any | |||
154 | move_const_to_right(x); | |||
155 | ||||
156 | if (x->y()->type()->is_constant()) { | |||
157 | // do constant folding for selected operations | |||
158 | switch (x->type()->tag()) { | |||
159 | case intTag: | |||
160 | if (x->y()->type()->as_IntConstant()->value() == 0) { | |||
161 | switch (x->op()) { | |||
162 | case Bytecodes::_iadd: set_canonical(x->x()); return; | |||
163 | case Bytecodes::_isub: set_canonical(x->x()); return; | |||
164 | case Bytecodes::_imul: set_constant(0); return; | |||
165 | // Note: for div and rem, make sure that C semantics | |||
166 | // corresponds to Java semantics! | |||
167 | case Bytecodes::_iand: set_constant(0); return; | |||
168 | case Bytecodes::_ior : set_canonical(x->x()); return; | |||
169 | default : break; | |||
170 | } | |||
171 | } | |||
172 | break; | |||
173 | case longTag: | |||
174 | if (x->y()->type()->as_LongConstant()->value() == (jlong)0) { | |||
175 | switch (x->op()) { | |||
176 | case Bytecodes::_ladd: set_canonical(x->x()); return; | |||
177 | case Bytecodes::_lsub: set_canonical(x->x()); return; | |||
178 | case Bytecodes::_lmul: set_constant((jlong)0); return; | |||
179 | // Note: for div and rem, make sure that C semantics | |||
180 | // corresponds to Java semantics! | |||
181 | case Bytecodes::_land: set_constant((jlong)0); return; | |||
182 | case Bytecodes::_lor : set_canonical(x->x()); return; | |||
183 | default : break; | |||
184 | } | |||
185 | } | |||
186 | break; | |||
187 | default: | |||
188 | break; | |||
189 | } | |||
190 | } | |||
191 | } | |||
192 | ||||
193 | ||||
194 | void Canonicalizer::do_Phi (Phi* x) {} | |||
195 | void Canonicalizer::do_Constant (Constant* x) {} | |||
196 | void Canonicalizer::do_Local (Local* x) {} | |||
197 | void Canonicalizer::do_LoadField (LoadField* x) {} | |||
198 | ||||
199 | // checks if v is in the block that is currently processed by | |||
200 | // GraphBuilder. This is the only block that has not BlockEnd yet. | |||
201 | static bool in_current_block(Value v) { | |||
202 | int max_distance = 4; | |||
203 | while (max_distance > 0 && v != NULL__null && v->as_BlockEnd() == NULL__null) { | |||
204 | v = v->next(); | |||
205 | max_distance--; | |||
206 | } | |||
207 | return v == NULL__null; | |||
208 | } | |||
209 | ||||
210 | void Canonicalizer::do_StoreField (StoreField* x) { | |||
211 | // If a value is going to be stored into a field or array some of | |||
212 | // the conversions emitted by javac are unneeded because the fields | |||
213 | // are packed to their natural size. | |||
214 | Convert* conv = x->value()->as_Convert(); | |||
215 | if (conv) { | |||
216 | Value value = NULL__null; | |||
217 | BasicType type = x->field()->type()->basic_type(); | |||
218 | switch (conv->op()) { | |||
219 | case Bytecodes::_i2b: if (type == T_BYTE) value = conv->value(); break; | |||
220 | case Bytecodes::_i2s: if (type == T_SHORT || type == T_BYTE) value = conv->value(); break; | |||
221 | case Bytecodes::_i2c: if (type == T_CHAR || type == T_BYTE) value = conv->value(); break; | |||
222 | default : break; | |||
223 | } | |||
224 | // limit this optimization to current block | |||
225 | if (value != NULL__null && in_current_block(conv)) { | |||
226 | set_canonical(new StoreField(x->obj(), x->offset(), x->field(), value, x->is_static(), | |||
227 | x->state_before(), x->needs_patching())); | |||
228 | return; | |||
229 | } | |||
230 | } | |||
231 | ||||
232 | } | |||
233 | ||||
234 | void Canonicalizer::do_ArrayLength (ArrayLength* x) { | |||
235 | NewArray* na; | |||
236 | Constant* ct; | |||
237 | LoadField* lf; | |||
238 | ||||
239 | if ((na = x->array()->as_NewArray()) != NULL__null) { | |||
240 | // New arrays might have the known length. | |||
241 | // Do not use the Constant itself, but create a new Constant | |||
242 | // with same value Otherwise a Constant is live over multiple | |||
243 | // blocks without being registered in a state array. | |||
244 | Constant* length; | |||
245 | NewMultiArray* nma; | |||
246 | if (na->length() != NULL__null && | |||
247 | (length = na->length()->as_Constant()) != NULL__null) { | |||
248 | assert(length->type()->as_IntConstant() != NULL, "array length must be integer")do { if (!(length->type()->as_IntConstant() != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 248, "assert(" "length->type()->as_IntConstant() != __null" ") failed", "array length must be integer"); ::breakpoint(); } } while (0); | |||
249 | set_constant(length->type()->as_IntConstant()->value()); | |||
250 | } else if ((nma = x->array()->as_NewMultiArray()) != NULL__null && | |||
251 | (length = nma->dims()->at(0)->as_Constant()) != NULL__null) { | |||
252 | assert(length->type()->as_IntConstant() != NULL, "array length must be integer")do { if (!(length->type()->as_IntConstant() != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 252, "assert(" "length->type()->as_IntConstant() != __null" ") failed", "array length must be integer"); ::breakpoint(); } } while (0); | |||
253 | set_constant(length->type()->as_IntConstant()->value()); | |||
254 | } | |||
255 | ||||
256 | } else if ((ct = x->array()->as_Constant()) != NULL__null) { | |||
257 | // Constant arrays have constant lengths. | |||
258 | ArrayConstant* cnst = ct->type()->as_ArrayConstant(); | |||
259 | if (cnst != NULL__null) { | |||
260 | set_constant(cnst->value()->length()); | |||
261 | } | |||
262 | ||||
263 | } else if ((lf = x->array()->as_LoadField()) != NULL__null) { | |||
264 | ciField* field = lf->field(); | |||
265 | if (field->is_static_constant()) { | |||
266 | // Constant field loads are usually folded during parsing. | |||
267 | // But it doesn't happen with PatchALot, ScavengeRootsInCode < 2, or when | |||
268 | // holder class is being initialized during parsing (for static fields). | |||
269 | ciObject* c = field->constant_value().as_object(); | |||
270 | if (!c->is_null_object()) { | |||
271 | set_constant(c->as_array()->length()); | |||
272 | } | |||
273 | } | |||
274 | } | |||
275 | } | |||
276 | ||||
277 | void Canonicalizer::do_LoadIndexed (LoadIndexed* x) { | |||
278 | StableArrayConstant* array = x->array()->type()->as_StableArrayConstant(); | |||
279 | IntConstant* index = x->index()->type()->as_IntConstant(); | |||
280 | ||||
281 | assert(array == NULL || FoldStableValues, "not enabled")do { if (!(array == __null || FoldStableValues)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 281, "assert(" "array == __null || FoldStableValues" ") failed" , "not enabled"); ::breakpoint(); } } while (0); | |||
282 | ||||
283 | // Constant fold loads from stable arrays. | |||
284 | if (!x->mismatched() && array != NULL__null && index != NULL__null) { | |||
285 | jint idx = index->value(); | |||
286 | if (idx < 0 || idx >= array->value()->length()) { | |||
287 | // Leave the load as is. The range check will handle it. | |||
288 | return; | |||
289 | } | |||
290 | ||||
291 | ciConstant field_val = array->value()->element_value(idx); | |||
292 | if (!field_val.is_null_or_zero()) { | |||
293 | jint dimension = array->dimension(); | |||
294 | assert(dimension <= array->value()->array_type()->dimension(), "inconsistent info")do { if (!(dimension <= array->value()->array_type() ->dimension())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 294, "assert(" "dimension <= array->value()->array_type()->dimension()" ") failed", "inconsistent info"); ::breakpoint(); } } while ( 0); | |||
295 | ValueType* value = NULL__null; | |||
296 | if (dimension > 1) { | |||
297 | // Preserve information about the dimension for the element. | |||
298 | assert(field_val.as_object()->is_array(), "not an array")do { if (!(field_val.as_object()->is_array())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 298, "assert(" "field_val.as_object()->is_array()" ") failed" , "not an array"); ::breakpoint(); } } while (0); | |||
299 | value = new StableArrayConstant(field_val.as_object()->as_array(), dimension - 1); | |||
300 | } else { | |||
301 | assert(dimension == 1, "sanity")do { if (!(dimension == 1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 301, "assert(" "dimension == 1" ") failed", "sanity"); ::breakpoint (); } } while (0); | |||
302 | value = as_ValueType(field_val); | |||
303 | } | |||
304 | set_canonical(new Constant(value)); | |||
305 | } | |||
306 | } | |||
307 | } | |||
308 | ||||
309 | void Canonicalizer::do_StoreIndexed (StoreIndexed* x) { | |||
310 | // If a value is going to be stored into a field or array some of | |||
311 | // the conversions emitted by javac are unneeded because the fields | |||
312 | // are packed to their natural size. | |||
313 | Convert* conv = x->value()->as_Convert(); | |||
314 | if (conv) { | |||
315 | Value value = NULL__null; | |||
316 | BasicType type = x->elt_type(); | |||
317 | switch (conv->op()) { | |||
318 | case Bytecodes::_i2b: if (type == T_BYTE) value = conv->value(); break; | |||
319 | case Bytecodes::_i2s: if (type == T_SHORT || type == T_BYTE) value = conv->value(); break; | |||
320 | case Bytecodes::_i2c: if (type == T_CHAR || type == T_BYTE) value = conv->value(); break; | |||
321 | default : break; | |||
322 | } | |||
323 | // limit this optimization to current block | |||
324 | if (value != NULL__null && in_current_block(conv)) { | |||
325 | set_canonical(new StoreIndexed(x->array(), x->index(), x->length(), | |||
326 | x->elt_type(), value, x->state_before(), | |||
327 | x->check_boolean())); | |||
328 | return; | |||
329 | } | |||
330 | } | |||
331 | } | |||
332 | ||||
333 | ||||
334 | void Canonicalizer::do_NegateOp(NegateOp* x) { | |||
335 | ValueType* t = x->x()->type(); | |||
336 | if (t->is_constant()) { | |||
337 | switch (t->tag()) { | |||
338 | case intTag : set_constant(-t->as_IntConstant ()->value()); return; | |||
339 | case longTag : set_constant(-t->as_LongConstant ()->value()); return; | |||
340 | case floatTag : set_constant(-t->as_FloatConstant ()->value()); return; | |||
341 | case doubleTag: set_constant(-t->as_DoubleConstant()->value()); return; | |||
342 | default : ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 342); ::breakpoint(); } while (0); | |||
343 | } | |||
344 | } | |||
345 | } | |||
346 | ||||
347 | ||||
348 | void Canonicalizer::do_ArithmeticOp (ArithmeticOp* x) { do_Op2(x); } | |||
349 | ||||
350 | ||||
351 | void Canonicalizer::do_ShiftOp (ShiftOp* x) { | |||
352 | ValueType* t = x->x()->type(); | |||
353 | ValueType* t2 = x->y()->type(); | |||
354 | if (t->is_constant()) { | |||
355 | switch (t->tag()) { | |||
356 | case intTag : if (t->as_IntConstant()->value() == 0) { set_constant(0); return; } break; | |||
357 | case longTag : if (t->as_LongConstant()->value() == (jlong)0) { set_constant(jlong_cast(0)); return; } break; | |||
358 | default : ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 358); ::breakpoint(); } while (0); | |||
359 | } | |||
360 | if (t2->is_constant()) { | |||
361 | if (t->tag() == intTag) { | |||
362 | jint value = t->as_IntConstant()->value(); | |||
363 | jint shift = t2->as_IntConstant()->value(); | |||
364 | switch (x->op()) { | |||
365 | case Bytecodes::_ishl: set_constant(java_shift_left(value, shift)); return; | |||
366 | case Bytecodes::_ishr: set_constant(java_shift_right(value, shift)); return; | |||
367 | case Bytecodes::_iushr: set_constant(java_shift_right_unsigned(value, shift)); return; | |||
368 | default: break; | |||
369 | } | |||
370 | } else if (t->tag() == longTag) { | |||
371 | jlong value = t->as_LongConstant()->value(); | |||
372 | jint shift = t2->as_IntConstant()->value(); | |||
373 | switch (x->op()) { | |||
374 | case Bytecodes::_lshl: set_constant(java_shift_left(value, shift)); return; | |||
375 | case Bytecodes::_lshr: set_constant(java_shift_right(value, shift)); return; | |||
376 | case Bytecodes::_lushr: set_constant(java_shift_right_unsigned(value, shift)); return; | |||
377 | default: break; | |||
378 | } | |||
379 | } | |||
380 | } | |||
381 | } | |||
382 | if (t2->is_constant()) { | |||
383 | switch (t2->tag()) { | |||
384 | case intTag : if (t2->as_IntConstant()->value() == 0) set_canonical(x->x()); return; | |||
385 | case longTag : if (t2->as_LongConstant()->value() == (jlong)0) set_canonical(x->x()); return; | |||
386 | default : ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 386); ::breakpoint(); } while (0); return; | |||
387 | } | |||
388 | } | |||
389 | } | |||
390 | ||||
391 | ||||
392 | void Canonicalizer::do_LogicOp (LogicOp* x) { do_Op2(x); } | |||
393 | void Canonicalizer::do_CompareOp (CompareOp* x) { | |||
394 | if (x->x() == x->y()) { | |||
395 | switch (x->x()->type()->tag()) { | |||
396 | case longTag: set_constant(0); break; | |||
397 | case floatTag: { | |||
398 | FloatConstant* fc = x->x()->type()->as_FloatConstant(); | |||
399 | if (fc) { | |||
400 | if (g_isnan(fc->value())) { | |||
401 | set_constant(x->op() == Bytecodes::_fcmpl ? -1 : 1); | |||
402 | } else { | |||
403 | set_constant(0); | |||
404 | } | |||
405 | } | |||
406 | break; | |||
407 | } | |||
408 | case doubleTag: { | |||
409 | DoubleConstant* dc = x->x()->type()->as_DoubleConstant(); | |||
410 | if (dc) { | |||
411 | if (g_isnan(dc->value())) { | |||
412 | set_constant(x->op() == Bytecodes::_dcmpl ? -1 : 1); | |||
413 | } else { | |||
414 | set_constant(0); | |||
415 | } | |||
416 | } | |||
417 | break; | |||
418 | } | |||
419 | default: | |||
420 | break; | |||
421 | } | |||
422 | } else if (x->x()->type()->is_constant() && x->y()->type()->is_constant()) { | |||
423 | switch (x->x()->type()->tag()) { | |||
424 | case longTag: { | |||
425 | jlong vx = x->x()->type()->as_LongConstant()->value(); | |||
426 | jlong vy = x->y()->type()->as_LongConstant()->value(); | |||
427 | if (vx == vy) | |||
428 | set_constant(0); | |||
429 | else if (vx < vy) | |||
430 | set_constant(-1); | |||
431 | else | |||
432 | set_constant(1); | |||
433 | break; | |||
434 | } | |||
435 | ||||
436 | case floatTag: { | |||
437 | float vx = x->x()->type()->as_FloatConstant()->value(); | |||
438 | float vy = x->y()->type()->as_FloatConstant()->value(); | |||
439 | if (g_isnan(vx) || g_isnan(vy)) | |||
440 | set_constant(x->op() == Bytecodes::_fcmpl ? -1 : 1); | |||
441 | else if (vx == vy) | |||
442 | set_constant(0); | |||
443 | else if (vx < vy) | |||
444 | set_constant(-1); | |||
445 | else | |||
446 | set_constant(1); | |||
447 | break; | |||
448 | } | |||
449 | ||||
450 | case doubleTag: { | |||
451 | double vx = x->x()->type()->as_DoubleConstant()->value(); | |||
452 | double vy = x->y()->type()->as_DoubleConstant()->value(); | |||
453 | if (g_isnan(vx) || g_isnan(vy)) | |||
454 | set_constant(x->op() == Bytecodes::_dcmpl ? -1 : 1); | |||
455 | else if (vx == vy) | |||
456 | set_constant(0); | |||
457 | else if (vx < vy) | |||
458 | set_constant(-1); | |||
459 | else | |||
460 | set_constant(1); | |||
461 | break; | |||
462 | } | |||
463 | ||||
464 | default: | |||
465 | break; | |||
466 | } | |||
467 | } | |||
468 | } | |||
469 | ||||
470 | ||||
471 | void Canonicalizer::do_IfOp(IfOp* x) { | |||
472 | // Caution: do not use do_Op2(x) here for now since | |||
473 | // we map the condition to the op for now! | |||
474 | move_const_to_right(x); | |||
475 | } | |||
476 | ||||
477 | ||||
478 | void Canonicalizer::do_Intrinsic (Intrinsic* x) { | |||
479 | switch (x->id()) { | |||
480 | case vmIntrinsics::_floatToRawIntBits : { | |||
481 | FloatConstant* c = x->argument_at(0)->type()->as_FloatConstant(); | |||
482 | if (c != NULL__null) { | |||
483 | JavaValue v; | |||
484 | v.set_jfloat(c->value()); | |||
485 | set_constant(v.get_jint()); | |||
486 | } | |||
487 | break; | |||
488 | } | |||
489 | case vmIntrinsics::_intBitsToFloat : { | |||
490 | IntConstant* c = x->argument_at(0)->type()->as_IntConstant(); | |||
491 | if (c != NULL__null) { | |||
492 | JavaValue v; | |||
493 | v.set_jint(c->value()); | |||
494 | set_constant(v.get_jfloat()); | |||
495 | } | |||
496 | break; | |||
497 | } | |||
498 | case vmIntrinsics::_doubleToRawLongBits : { | |||
499 | DoubleConstant* c = x->argument_at(0)->type()->as_DoubleConstant(); | |||
500 | if (c != NULL__null) { | |||
501 | JavaValue v; | |||
502 | v.set_jdouble(c->value()); | |||
503 | set_constant(v.get_jlong()); | |||
504 | } | |||
505 | break; | |||
506 | } | |||
507 | case vmIntrinsics::_longBitsToDouble : { | |||
508 | LongConstant* c = x->argument_at(0)->type()->as_LongConstant(); | |||
509 | if (c != NULL__null) { | |||
510 | JavaValue v; | |||
511 | v.set_jlong(c->value()); | |||
512 | set_constant(v.get_jdouble()); | |||
513 | } | |||
514 | break; | |||
515 | } | |||
516 | case vmIntrinsics::_isInstance : { | |||
517 | assert(x->number_of_arguments() == 2, "wrong type")do { if (!(x->number_of_arguments() == 2)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 517, "assert(" "x->number_of_arguments() == 2" ") failed" , "wrong type"); ::breakpoint(); } } while (0); | |||
518 | ||||
519 | InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant(); | |||
520 | if (c != NULL__null && !c->value()->is_null_object()) { | |||
521 | // ciInstance::java_mirror_type() returns non-NULL only for Java mirrors | |||
522 | ciType* t = c->value()->java_mirror_type(); | |||
523 | if (t->is_klass()) { | |||
524 | // substitute cls.isInstance(obj) of a constant Class into | |||
525 | // an InstantOf instruction | |||
526 | InstanceOf* i = new InstanceOf(t->as_klass(), x->argument_at(1), x->state_before()); | |||
527 | set_canonical(i); | |||
528 | // and try to canonicalize even further | |||
529 | do_InstanceOf(i); | |||
530 | } else { | |||
531 | assert(t->is_primitive_type(), "should be a primitive type")do { if (!(t->is_primitive_type())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 531, "assert(" "t->is_primitive_type()" ") failed", "should be a primitive type" ); ::breakpoint(); } } while (0); | |||
532 | // cls.isInstance(obj) always returns false for primitive classes | |||
533 | set_constant(0); | |||
534 | } | |||
535 | } | |||
536 | break; | |||
537 | } | |||
538 | case vmIntrinsics::_isPrimitive : { | |||
539 | assert(x->number_of_arguments() == 1, "wrong type")do { if (!(x->number_of_arguments() == 1)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 539, "assert(" "x->number_of_arguments() == 1" ") failed" , "wrong type"); ::breakpoint(); } } while (0); | |||
540 | ||||
541 | // Class.isPrimitive is known on constant classes: | |||
542 | InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant(); | |||
543 | if (c != NULL__null && !c->value()->is_null_object()) { | |||
544 | ciType* t = c->value()->java_mirror_type(); | |||
545 | set_constant(t->is_primitive_type()); | |||
546 | } | |||
547 | break; | |||
548 | } | |||
549 | case vmIntrinsics::_getModifiers: { | |||
550 | assert(x->number_of_arguments() == 1, "wrong type")do { if (!(x->number_of_arguments() == 1)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 550, "assert(" "x->number_of_arguments() == 1" ") failed" , "wrong type"); ::breakpoint(); } } while (0); | |||
551 | ||||
552 | // Optimize for Foo.class.getModifier() | |||
553 | InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant(); | |||
554 | if (c != NULL__null && !c->value()->is_null_object()) { | |||
555 | ciType* t = c->value()->java_mirror_type(); | |||
556 | if (t->is_klass()) { | |||
557 | set_constant(t->as_klass()->modifier_flags()); | |||
558 | } else { | |||
559 | assert(t->is_primitive_type(), "should be a primitive type")do { if (!(t->is_primitive_type())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 559, "assert(" "t->is_primitive_type()" ") failed", "should be a primitive type" ); ::breakpoint(); } } while (0); | |||
560 | set_constant(JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC); | |||
561 | } | |||
562 | } | |||
563 | break; | |||
564 | } | |||
565 | default: | |||
566 | break; | |||
567 | } | |||
568 | } | |||
569 | ||||
570 | void Canonicalizer::do_Convert (Convert* x) { | |||
571 | if (x->value()->type()->is_constant()) { | |||
572 | switch (x->op()) { | |||
573 | case Bytecodes::_i2b: set_constant((int)((x->value()->type()->as_IntConstant()->value() << 24) >> 24)); break; | |||
574 | case Bytecodes::_i2s: set_constant((int)((x->value()->type()->as_IntConstant()->value() << 16) >> 16)); break; | |||
575 | case Bytecodes::_i2c: set_constant((int)(x->value()->type()->as_IntConstant()->value() & ((1<<16)-1))); break; | |||
576 | case Bytecodes::_i2l: set_constant((jlong)(x->value()->type()->as_IntConstant()->value())); break; | |||
577 | case Bytecodes::_i2f: set_constant((float)(x->value()->type()->as_IntConstant()->value())); break; | |||
578 | case Bytecodes::_i2d: set_constant((double)(x->value()->type()->as_IntConstant()->value())); break; | |||
579 | case Bytecodes::_l2i: set_constant((int)(x->value()->type()->as_LongConstant()->value())); break; | |||
580 | case Bytecodes::_l2f: set_constant(SharedRuntime::l2f(x->value()->type()->as_LongConstant()->value())); break; | |||
581 | case Bytecodes::_l2d: set_constant(SharedRuntime::l2d(x->value()->type()->as_LongConstant()->value())); break; | |||
582 | case Bytecodes::_f2d: set_constant((double)(x->value()->type()->as_FloatConstant()->value())); break; | |||
583 | case Bytecodes::_f2i: set_constant(SharedRuntime::f2i(x->value()->type()->as_FloatConstant()->value())); break; | |||
584 | case Bytecodes::_f2l: set_constant(SharedRuntime::f2l(x->value()->type()->as_FloatConstant()->value())); break; | |||
585 | case Bytecodes::_d2f: set_constant((float)(x->value()->type()->as_DoubleConstant()->value())); break; | |||
586 | case Bytecodes::_d2i: set_constant(SharedRuntime::d2i(x->value()->type()->as_DoubleConstant()->value())); break; | |||
587 | case Bytecodes::_d2l: set_constant(SharedRuntime::d2l(x->value()->type()->as_DoubleConstant()->value())); break; | |||
588 | default: | |||
589 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 589); ::breakpoint(); } while (0); | |||
590 | } | |||
591 | } | |||
592 | ||||
593 | Value value = x->value(); | |||
594 | BasicType type = T_ILLEGAL; | |||
595 | LoadField* lf = value->as_LoadField(); | |||
596 | if (lf) { | |||
597 | type = lf->field_type(); | |||
598 | } else { | |||
599 | LoadIndexed* li = value->as_LoadIndexed(); | |||
600 | if (li) { | |||
601 | type = li->elt_type(); | |||
602 | } else { | |||
603 | Convert* conv = value->as_Convert(); | |||
604 | if (conv) { | |||
605 | switch (conv->op()) { | |||
606 | case Bytecodes::_i2b: type = T_BYTE; break; | |||
607 | case Bytecodes::_i2s: type = T_SHORT; break; | |||
608 | case Bytecodes::_i2c: type = T_CHAR; break; | |||
609 | default : break; | |||
610 | } | |||
611 | } | |||
612 | } | |||
613 | } | |||
614 | if (type != T_ILLEGAL) { | |||
615 | switch (x->op()) { | |||
616 | case Bytecodes::_i2b: if (type == T_BYTE) set_canonical(x->value()); break; | |||
617 | case Bytecodes::_i2s: if (type == T_SHORT || type == T_BYTE) set_canonical(x->value()); break; | |||
618 | case Bytecodes::_i2c: if (type == T_CHAR) set_canonical(x->value()); break; | |||
619 | default : break; | |||
620 | } | |||
621 | } else { | |||
622 | Op2* op2 = x->value()->as_Op2(); | |||
623 | if (op2 && op2->op() == Bytecodes::_iand && op2->y()->type()->is_constant()) { | |||
624 | jint safebits = 0; | |||
625 | jint mask = op2->y()->type()->as_IntConstant()->value(); | |||
626 | switch (x->op()) { | |||
627 | case Bytecodes::_i2b: safebits = 0x7f; break; | |||
628 | case Bytecodes::_i2s: safebits = 0x7fff; break; | |||
629 | case Bytecodes::_i2c: safebits = 0xffff; break; | |||
630 | default : break; | |||
631 | } | |||
632 | // When casting a masked integer to a smaller signed type, if | |||
633 | // the mask doesn't include the sign bit the cast isn't needed. | |||
634 | if (safebits && (mask & ~safebits) == 0) { | |||
635 | set_canonical(x->value()); | |||
636 | } | |||
637 | } | |||
638 | } | |||
639 | ||||
640 | } | |||
641 | ||||
642 | void Canonicalizer::do_NullCheck (NullCheck* x) { | |||
643 | if (x->obj()->as_NewArray() != NULL__null || x->obj()->as_NewInstance() != NULL__null) { | |||
644 | set_canonical(x->obj()); | |||
645 | } else { | |||
646 | Constant* con = x->obj()->as_Constant(); | |||
647 | if (con) { | |||
648 | ObjectType* c = con->type()->as_ObjectType(); | |||
649 | if (c && c->is_loaded()) { | |||
650 | ObjectConstant* oc = c->as_ObjectConstant(); | |||
651 | if (!oc || !oc->value()->is_null_object()) { | |||
652 | set_canonical(con); | |||
653 | } | |||
654 | } | |||
655 | } | |||
656 | } | |||
657 | } | |||
658 | ||||
659 | void Canonicalizer::do_TypeCast (TypeCast* x) {} | |||
660 | void Canonicalizer::do_Invoke (Invoke* x) {} | |||
661 | void Canonicalizer::do_NewInstance (NewInstance* x) {} | |||
662 | void Canonicalizer::do_NewTypeArray (NewTypeArray* x) {} | |||
663 | void Canonicalizer::do_NewObjectArray (NewObjectArray* x) {} | |||
664 | void Canonicalizer::do_NewMultiArray (NewMultiArray* x) {} | |||
665 | void Canonicalizer::do_CheckCast (CheckCast* x) { | |||
666 | if (x->klass()->is_loaded()) { | |||
667 | Value obj = x->obj(); | |||
668 | ciType* klass = obj->exact_type(); | |||
669 | if (klass == NULL__null) { | |||
670 | klass = obj->declared_type(); | |||
671 | } | |||
672 | if (klass != NULL__null && klass->is_loaded()) { | |||
673 | bool is_interface = klass->is_instance_klass() && | |||
674 | klass->as_instance_klass()->is_interface(); | |||
675 | // Interface casts can't be statically optimized away since verifier doesn't | |||
676 | // enforce interface types in bytecode. | |||
677 | if (!is_interface && klass->is_subtype_of(x->klass())) { | |||
678 | set_canonical(obj); | |||
679 | return; | |||
680 | } | |||
681 | } | |||
682 | // checkcast of null returns null | |||
683 | if (obj->as_Constant() && obj->type()->as_ObjectType()->constant_value()->is_null_object()) { | |||
684 | set_canonical(obj); | |||
685 | } | |||
686 | } | |||
687 | } | |||
688 | void Canonicalizer::do_InstanceOf (InstanceOf* x) { | |||
689 | if (x->klass()->is_loaded()) { | |||
690 | Value obj = x->obj(); | |||
691 | ciType* exact = obj->exact_type(); | |||
692 | if (exact != NULL__null && exact->is_loaded() && (obj->as_NewInstance() || obj->as_NewArray())) { | |||
693 | set_constant(exact->is_subtype_of(x->klass()) ? 1 : 0); | |||
694 | return; | |||
695 | } | |||
696 | // instanceof null returns false | |||
697 | if (obj->as_Constant() && obj->type()->as_ObjectType()->constant_value()->is_null_object()) { | |||
698 | set_constant(0); | |||
699 | } | |||
700 | } | |||
701 | ||||
702 | } | |||
703 | void Canonicalizer::do_MonitorEnter (MonitorEnter* x) {} | |||
704 | void Canonicalizer::do_MonitorExit (MonitorExit* x) {} | |||
705 | void Canonicalizer::do_BlockBegin (BlockBegin* x) {} | |||
706 | void Canonicalizer::do_Goto (Goto* x) {} | |||
707 | ||||
708 | ||||
709 | static bool is_true(jlong x, If::Condition cond, jlong y) { | |||
710 | switch (cond) { | |||
711 | case If::eql: return x == y; | |||
712 | case If::neq: return x != y; | |||
713 | case If::lss: return x < y; | |||
714 | case If::leq: return x <= y; | |||
715 | case If::gtr: return x > y; | |||
716 | case If::geq: return x >= y; | |||
717 | default: | |||
718 | ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 718); ::breakpoint(); } while (0); | |||
719 | return false; | |||
720 | } | |||
721 | } | |||
722 | ||||
723 | static bool is_safepoint(BlockEnd* x, BlockBegin* sux) { | |||
724 | // An Instruction with multiple successors, x, is replaced by a Goto | |||
725 | // to a single successor, sux. Is a safepoint check needed = was the | |||
726 | // instruction being replaced a safepoint and the single remaining | |||
727 | // successor a back branch? | |||
728 | return x->is_safepoint() && (sux->bci() < x->state_before()->bci()); | |||
| ||||
729 | } | |||
730 | ||||
731 | void Canonicalizer::do_If(If* x) { | |||
732 | // move const to right | |||
733 | if (x->x()->type()->is_constant()) x->swap_operands(); | |||
| ||||
734 | // simplify | |||
735 | const Value l = x->x(); ValueType* lt = l->type(); | |||
736 | const Value r = x->y(); ValueType* rt = r->type(); | |||
737 | ||||
738 | if (l == r && !lt->is_float_kind()) { | |||
739 | // pattern: If (a cond a) => simplify to Goto | |||
740 | BlockBegin* sux = NULL__null; | |||
741 | switch (x->cond()) { | |||
742 | case If::eql: sux = x->sux_for(true); break; | |||
743 | case If::neq: sux = x->sux_for(false); break; | |||
744 | case If::lss: sux = x->sux_for(false); break; | |||
745 | case If::leq: sux = x->sux_for(true); break; | |||
746 | case If::gtr: sux = x->sux_for(false); break; | |||
747 | case If::geq: sux = x->sux_for(true); break; | |||
748 | default: ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 748); ::breakpoint(); } while (0); | |||
749 | } | |||
750 | // If is a safepoint then the debug information should come from the state_before of the If. | |||
751 | set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); | |||
752 | return; | |||
753 | } | |||
754 | ||||
755 | if (lt->is_constant() && rt->is_constant()) { | |||
756 | if (x->x()->as_Constant() != NULL__null) { | |||
757 | // pattern: If (lc cond rc) => simplify to: Goto | |||
758 | BlockBegin* sux = x->x()->as_Constant()->compare(x->cond(), x->y(), | |||
759 | x->sux_for(true), | |||
760 | x->sux_for(false)); | |||
761 | if (sux != NULL__null) { | |||
762 | // If is a safepoint then the debug information should come from the state_before of the If. | |||
763 | set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); | |||
764 | } | |||
765 | } | |||
766 | } else if (rt->as_IntConstant() != NULL__null) { | |||
767 | // pattern: If (l cond rc) => investigate further | |||
768 | const jint rc = rt->as_IntConstant()->value(); | |||
769 | if (l->as_CompareOp() != NULL__null) { | |||
770 | // pattern: If ((a cmp b) cond rc) => simplify to: If (x cond y) or: Goto | |||
771 | CompareOp* cmp = l->as_CompareOp(); | |||
772 | bool unordered_is_less = cmp->op() == Bytecodes::_fcmpl || cmp->op() == Bytecodes::_dcmpl; | |||
773 | BlockBegin* lss_sux = x->sux_for(is_true(-1, x->cond(), rc)); // successor for a < b | |||
774 | BlockBegin* eql_sux = x->sux_for(is_true( 0, x->cond(), rc)); // successor for a = b | |||
775 | BlockBegin* gtr_sux = x->sux_for(is_true(+1, x->cond(), rc)); // successor for a > b | |||
776 | BlockBegin* nan_sux = unordered_is_less ? lss_sux : gtr_sux ; // successor for unordered | |||
777 | // Note: At this point all successors (lss_sux, eql_sux, gtr_sux, nan_sux) are | |||
778 | // equal to x->tsux() or x->fsux(). Furthermore, nan_sux equals either | |||
779 | // lss_sux or gtr_sux. | |||
780 | if (lss_sux == eql_sux && eql_sux == gtr_sux) { | |||
781 | // all successors identical => simplify to: Goto | |||
782 | set_canonical(new Goto(lss_sux, x->state_before(), x->is_safepoint())); | |||
783 | } else { | |||
784 | // two successors differ and two successors are the same => simplify to: If (x cmp y) | |||
785 | // determine new condition & successors | |||
786 | If::Condition cond = If::eql; | |||
787 | BlockBegin* tsux = NULL__null; | |||
788 | BlockBegin* fsux = NULL__null; | |||
789 | if (lss_sux == eql_sux) { cond = If::leq; tsux = lss_sux; fsux = gtr_sux; } | |||
790 | else if (lss_sux == gtr_sux) { cond = If::neq; tsux = lss_sux; fsux = eql_sux; } | |||
791 | else if (eql_sux == gtr_sux) { cond = If::geq; tsux = eql_sux; fsux = lss_sux; } | |||
792 | else { ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 792); ::breakpoint(); } while (0); } | |||
793 | If* canon = new If(cmp->x(), cond, nan_sux == tsux, cmp->y(), tsux, fsux, cmp->state_before(), x->is_safepoint()); | |||
794 | if (cmp->x() == cmp->y()) { | |||
795 | do_If(canon); | |||
796 | } else { | |||
797 | if (compilation()->profile_branches() || compilation()->is_profiling()) { | |||
798 | // TODO: If profiling, leave floating point comparisons unoptimized. | |||
799 | // We currently do not support profiling of the unordered case. | |||
800 | switch(cmp->op()) { | |||
801 | case Bytecodes::_fcmpl: case Bytecodes::_fcmpg: | |||
802 | case Bytecodes::_dcmpl: case Bytecodes::_dcmpg: | |||
803 | set_canonical(x); | |||
804 | return; | |||
805 | default: | |||
806 | break; | |||
807 | } | |||
808 | } | |||
809 | set_bci(cmp->state_before()->bci()); | |||
810 | set_canonical(canon); | |||
811 | } | |||
812 | } | |||
813 | } | |||
814 | } else if (rt == objectNull && | |||
815 | (l->as_NewInstance() || l->as_NewArray() || | |||
816 | (l->as_Local() && l->as_Local()->is_receiver()))) { | |||
817 | if (x->cond() == Instruction::eql) { | |||
818 | BlockBegin* sux = x->fsux(); | |||
819 | set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); | |||
820 | } else { | |||
821 | assert(x->cond() == Instruction::neq, "only other valid case")do { if (!(x->cond() == Instruction::neq)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_Canonicalizer.cpp" , 821, "assert(" "x->cond() == Instruction::neq" ") failed" , "only other valid case"); ::breakpoint(); } } while (0); | |||
822 | BlockBegin* sux = x->tsux(); | |||
823 | set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); | |||
824 | } | |||
825 | } | |||
826 | } | |||
827 | ||||
828 | ||||
829 | void Canonicalizer::do_TableSwitch(TableSwitch* x) { | |||
830 | if (x->tag()->type()->is_constant()) { | |||
831 | int v = x->tag()->type()->as_IntConstant()->value(); | |||
832 | BlockBegin* sux = x->default_sux(); | |||
833 | if (v >= x->lo_key() && v <= x->hi_key()) { | |||
834 | sux = x->sux_at(v - x->lo_key()); | |||
835 | } | |||
836 | set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); | |||
837 | } | |||
838 | } | |||
839 | ||||
840 | ||||
841 | void Canonicalizer::do_LookupSwitch(LookupSwitch* x) { | |||
842 | if (x->tag()->type()->is_constant()) { | |||
843 | int v = x->tag()->type()->as_IntConstant()->value(); | |||
844 | BlockBegin* sux = x->default_sux(); | |||
845 | for (int i = 0; i < x->length(); i++) { | |||
846 | if (v == x->key_at(i)) { | |||
847 | sux = x->sux_at(i); | |||
848 | } | |||
849 | } | |||
850 | set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); | |||
851 | } | |||
852 | } | |||
853 | ||||
854 | ||||
855 | void Canonicalizer::do_Return (Return* x) {} | |||
856 | void Canonicalizer::do_Throw (Throw* x) {} | |||
857 | void Canonicalizer::do_Base (Base* x) {} | |||
858 | void Canonicalizer::do_OsrEntry (OsrEntry* x) {} | |||
859 | void Canonicalizer::do_ExceptionObject(ExceptionObject* x) {} | |||
860 | void Canonicalizer::do_RoundFP (RoundFP* x) {} | |||
861 | void Canonicalizer::do_UnsafeGet (UnsafeGet* x) {} | |||
862 | void Canonicalizer::do_UnsafePut (UnsafePut* x) {} | |||
863 | void Canonicalizer::do_UnsafeGetAndSet(UnsafeGetAndSet* x) {} | |||
864 | void Canonicalizer::do_ProfileCall (ProfileCall* x) {} | |||
865 | void Canonicalizer::do_ProfileReturnType(ProfileReturnType* x) {} | |||
866 | void Canonicalizer::do_ProfileInvoke (ProfileInvoke* x) {} | |||
867 | void Canonicalizer::do_RuntimeCall (RuntimeCall* x) {} | |||
868 | void Canonicalizer::do_RangeCheckPredicate(RangeCheckPredicate* x) {} | |||
869 | #ifdef ASSERT1 | |||
870 | void Canonicalizer::do_Assert (Assert* x) {} | |||
871 | #endif | |||
872 | void Canonicalizer::do_MemBar (MemBar* x) {} |
1 | /* |
2 | * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. |
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 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #ifndef SHARE_C1_C1_VALUETYPE_HPP |
26 | #define SHARE_C1_C1_VALUETYPE_HPP |
27 | |
28 | #include "c1/c1_Compilation.hpp" |
29 | #include "ci/ciConstant.hpp" |
30 | #include "ci/ciMethodData.hpp" |
31 | |
32 | // type hierarchy |
33 | class ValueType; |
34 | class VoidType; |
35 | class IntType; |
36 | class IntConstant; |
37 | class LongType; |
38 | class LongConstant; |
39 | class FloatType; |
40 | class FloatConstant; |
41 | class DoubleType; |
42 | class DoubleConstant; |
43 | class ObjectType; |
44 | class ObjectConstant; |
45 | class ArrayType; |
46 | class ArrayConstant; |
47 | class StableArrayConstant; |
48 | class InstanceType; |
49 | class InstanceConstant; |
50 | class MetadataType; |
51 | class ClassType; |
52 | class ClassConstant; |
53 | class MethodType; |
54 | class MethodConstant; |
55 | class AddressType; |
56 | class AddressConstant; |
57 | class IllegalType; |
58 | |
59 | |
60 | // predefined types |
61 | extern VoidType* voidType; |
62 | extern IntType* intType; |
63 | extern LongType* longType; |
64 | extern FloatType* floatType; |
65 | extern DoubleType* doubleType; |
66 | extern ObjectType* objectType; |
67 | extern ArrayType* arrayType; |
68 | extern InstanceType* instanceType; |
69 | extern ClassType* classType; |
70 | extern AddressType* addressType; |
71 | extern IllegalType* illegalType; |
72 | |
73 | |
74 | // predefined constants |
75 | extern IntConstant* intZero; |
76 | extern IntConstant* intOne; |
77 | extern ObjectConstant* objectNull; |
78 | |
79 | |
80 | // tags |
81 | enum ValueTag { |
82 | // all legal tags must come first |
83 | intTag, |
84 | longTag, |
85 | floatTag, |
86 | doubleTag, |
87 | objectTag, |
88 | addressTag, |
89 | metaDataTag, |
90 | number_of_legal_tags, |
91 | // all other tags must follow afterwards |
92 | voidTag = number_of_legal_tags, |
93 | illegalTag, |
94 | number_of_tags |
95 | }; |
96 | |
97 | |
98 | class ValueType: public CompilationResourceObj { |
99 | private: |
100 | const int _size; |
101 | const ValueTag _tag; |
102 | ValueType(); |
103 | protected: |
104 | ValueType(ValueTag tag, int size): _size(size), _tag(tag) {} |
105 | |
106 | public: |
107 | // initialization |
108 | static void initialize(Arena* arena); |
109 | |
110 | // accessors |
111 | virtual ValueType* base() const = 0; // the 'canonical' type (e.g., intType for an IntConstant) |
112 | ValueTag tag() const { return _tag; } // the 'canonical' tag (useful for type matching) |
113 | int size() const { // the size of an object of the type in words |
114 | assert(_size > -1, "shouldn't be asking for size")do { if (!(_size > -1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_ValueType.hpp" , 114, "assert(" "_size > -1" ") failed", "shouldn't be asking for size" ); ::breakpoint(); } } while (0); |
115 | return _size; |
116 | } |
117 | virtual const char tchar() const = 0; // the type 'character' for printing |
118 | virtual const char* name() const = 0; // the type name for printing |
119 | virtual bool is_constant() const { return false; } |
120 | |
121 | // testers |
122 | bool is_void() { return tag() == voidTag; } |
123 | bool is_int() { return tag() == intTag; } |
124 | bool is_long() { return tag() == longTag; } |
125 | bool is_float() { return tag() == floatTag; } |
126 | bool is_double() { return tag() == doubleTag; } |
127 | bool is_object() { return as_ObjectType() != NULL__null; } |
128 | bool is_array() { return as_ArrayType() != NULL__null; } |
129 | bool is_instance() { return as_InstanceType() != NULL__null; } |
130 | bool is_class() { return as_ClassType() != NULL__null; } |
131 | bool is_method() { return as_MethodType() != NULL__null; } |
132 | bool is_address() { return as_AddressType() != NULL__null; } |
133 | bool is_illegal() { return tag() == illegalTag; } |
134 | |
135 | bool is_int_kind() const { return tag() == intTag || tag() == longTag; } |
136 | bool is_float_kind() const { return tag() == floatTag || tag() == doubleTag; } |
137 | bool is_object_kind() const { return tag() == objectTag; } |
138 | |
139 | bool is_single_word() const { return _size == 1; } |
140 | bool is_double_word() const { return _size == 2; } |
141 | |
142 | // casting |
143 | virtual VoidType* as_VoidType() { return NULL__null; } |
144 | virtual IntType* as_IntType() { return NULL__null; } |
145 | virtual LongType* as_LongType() { return NULL__null; } |
146 | virtual FloatType* as_FloatType() { return NULL__null; } |
147 | virtual DoubleType* as_DoubleType() { return NULL__null; } |
148 | virtual ObjectType* as_ObjectType() { return NULL__null; } |
149 | virtual ArrayType* as_ArrayType() { return NULL__null; } |
150 | virtual InstanceType* as_InstanceType() { return NULL__null; } |
151 | virtual ClassType* as_ClassType() { return NULL__null; } |
152 | virtual MetadataType* as_MetadataType() { return NULL__null; } |
153 | virtual MethodType* as_MethodType() { return NULL__null; } |
154 | virtual AddressType* as_AddressType() { return NULL__null; } |
155 | virtual IllegalType* as_IllegalType() { return NULL__null; } |
156 | virtual IntConstant* as_IntConstant() { return NULL__null; } |
157 | virtual LongConstant* as_LongConstant() { return NULL__null; } |
158 | virtual FloatConstant* as_FloatConstant() { return NULL__null; } |
159 | virtual DoubleConstant* as_DoubleConstant() { return NULL__null; } |
160 | virtual ObjectConstant* as_ObjectConstant() { return NULL__null; } |
161 | virtual InstanceConstant* as_InstanceConstant(){ return NULL__null; } |
162 | virtual ClassConstant* as_ClassConstant() { return NULL__null; } |
163 | virtual MethodConstant* as_MethodConstant() { return NULL__null; } |
164 | virtual ArrayConstant* as_ArrayConstant() { return NULL__null; } |
165 | virtual StableArrayConstant* as_StableArrayConstant() { return NULL__null; } |
166 | virtual AddressConstant* as_AddressConstant() { return NULL__null; } |
167 | |
168 | // type operations |
169 | ValueType* meet(ValueType* y) const; |
170 | |
171 | // debugging |
172 | void print(outputStream* s = tty) { s->print("%s", name()); } |
173 | }; |
174 | |
175 | |
176 | class VoidType: public ValueType { |
177 | public: |
178 | VoidType(): ValueType(voidTag, 0) {} |
179 | virtual ValueType* base() const { return voidType; } |
180 | virtual const char tchar() const { return 'v'; } |
181 | virtual const char* name() const { return "void"; } |
182 | virtual VoidType* as_VoidType() { return this; } |
183 | }; |
184 | |
185 | |
186 | class IntType: public ValueType { |
187 | public: |
188 | IntType(): ValueType(intTag, 1) {} |
189 | virtual ValueType* base() const { return intType; } |
190 | virtual const char tchar() const { return 'i'; } |
191 | virtual const char* name() const { return "int"; } |
192 | virtual IntType* as_IntType() { return this; } |
193 | }; |
194 | |
195 | |
196 | class IntConstant: public IntType { |
197 | private: |
198 | jint _value; |
199 | |
200 | public: |
201 | IntConstant(jint value) { _value = value; } |
202 | |
203 | jint value() const { return _value; } |
204 | |
205 | virtual bool is_constant() const { return true; } |
206 | virtual IntConstant* as_IntConstant() { return this; } |
207 | }; |
208 | |
209 | |
210 | class LongType: public ValueType { |
211 | public: |
212 | LongType(): ValueType(longTag, 2) {} |
213 | virtual ValueType* base() const { return longType; } |
214 | virtual const char tchar() const { return 'l'; } |
215 | virtual const char* name() const { return "long"; } |
216 | virtual LongType* as_LongType() { return this; } |
217 | }; |
218 | |
219 | |
220 | class LongConstant: public LongType { |
221 | private: |
222 | jlong _value; |
223 | |
224 | public: |
225 | LongConstant(jlong value) { _value = value; } |
226 | |
227 | jlong value() const { return _value; } |
228 | |
229 | virtual bool is_constant() const { return true; } |
230 | virtual LongConstant* as_LongConstant() { return this; } |
231 | }; |
232 | |
233 | |
234 | class FloatType: public ValueType { |
235 | public: |
236 | FloatType(): ValueType(floatTag, 1) {} |
237 | virtual ValueType* base() const { return floatType; } |
238 | virtual const char tchar() const { return 'f'; } |
239 | virtual const char* name() const { return "float"; } |
240 | virtual FloatType* as_FloatType() { return this; } |
241 | }; |
242 | |
243 | |
244 | class FloatConstant: public FloatType { |
245 | private: |
246 | jfloat _value; |
247 | |
248 | public: |
249 | FloatConstant(jfloat value) { _value = value; } |
250 | |
251 | jfloat value() const { return _value; } |
252 | |
253 | virtual bool is_constant() const { return true; } |
254 | virtual FloatConstant* as_FloatConstant() { return this; } |
255 | }; |
256 | |
257 | |
258 | class DoubleType: public ValueType { |
259 | public: |
260 | DoubleType(): ValueType(doubleTag, 2) {} |
261 | virtual ValueType* base() const { return doubleType; } |
262 | virtual const char tchar() const { return 'd'; } |
263 | virtual const char* name() const { return "double"; } |
264 | virtual DoubleType* as_DoubleType() { return this; } |
265 | }; |
266 | |
267 | |
268 | class DoubleConstant: public DoubleType { |
269 | private: |
270 | jdouble _value; |
271 | |
272 | public: |
273 | DoubleConstant(jdouble value) { _value = value; } |
274 | |
275 | jdouble value() const { return _value; } |
276 | |
277 | virtual bool is_constant() const { return true; } |
278 | virtual DoubleConstant* as_DoubleConstant() { return this; } |
279 | }; |
280 | |
281 | |
282 | class ObjectType: public ValueType { |
283 | public: |
284 | ObjectType(): ValueType(objectTag, 1) {} |
285 | virtual ValueType* base() const { return objectType; } |
286 | virtual const char tchar() const { return 'a'; } |
287 | virtual const char* name() const { return "object"; } |
288 | virtual ObjectType* as_ObjectType() { return this; } |
289 | virtual ciObject* constant_value() const { ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_ValueType.hpp" , 289); ::breakpoint(); } while (0); return NULL__null; } |
290 | virtual ciType* exact_type() const { return NULL__null; } |
291 | bool is_loaded() const; |
292 | jobject encoding() const; |
293 | }; |
294 | |
295 | |
296 | class ObjectConstant: public ObjectType { |
297 | private: |
298 | ciObject* _value; |
299 | |
300 | public: |
301 | ObjectConstant(ciObject* value) { _value = value; } |
302 | |
303 | ciObject* value() const { return _value; } |
304 | |
305 | virtual bool is_constant() const { return true; } |
306 | virtual ObjectConstant* as_ObjectConstant() { return this; } |
307 | virtual ciObject* constant_value() const; |
308 | virtual ciType* exact_type() const; |
309 | }; |
310 | |
311 | |
312 | class ArrayType: public ObjectType { |
313 | public: |
314 | virtual ArrayType* as_ArrayType() { return this; } |
315 | }; |
316 | |
317 | |
318 | class ArrayConstant: public ArrayType { |
319 | private: |
320 | ciArray* _value; |
321 | |
322 | public: |
323 | ArrayConstant(ciArray* value) { _value = value; } |
324 | |
325 | ciArray* value() const { return _value; } |
326 | |
327 | virtual bool is_constant() const { return true; } |
328 | virtual ArrayConstant* as_ArrayConstant() { return this; } |
329 | virtual ciObject* constant_value() const; |
330 | virtual ciType* exact_type() const; |
331 | }; |
332 | |
333 | class StableArrayConstant: public ArrayConstant { |
334 | private: |
335 | jint _dimension; |
336 | |
337 | public: |
338 | StableArrayConstant(ciArray* value, jint dimension) : ArrayConstant(value) { |
339 | assert(dimension > 0, "not a stable array")do { if (!(dimension > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_ValueType.hpp" , 339, "assert(" "dimension > 0" ") failed", "not a stable array" ); ::breakpoint(); } } while (0); |
340 | _dimension = dimension; |
341 | } |
342 | |
343 | jint dimension() const { return _dimension; } |
344 | |
345 | virtual StableArrayConstant* as_StableArrayConstant() { return this; } |
346 | }; |
347 | |
348 | class InstanceType: public ObjectType { |
349 | public: |
350 | virtual InstanceType* as_InstanceType() { return this; } |
351 | }; |
352 | |
353 | |
354 | class InstanceConstant: public InstanceType { |
355 | private: |
356 | ciInstance* _value; |
357 | |
358 | public: |
359 | InstanceConstant(ciInstance* value) { _value = value; } |
360 | |
361 | ciInstance* value() const { return _value; } |
362 | |
363 | virtual bool is_constant() const { return true; } |
364 | virtual InstanceConstant* as_InstanceConstant(){ return this; } |
365 | virtual ciObject* constant_value() const; |
366 | virtual ciType* exact_type() const; |
367 | }; |
368 | |
369 | |
370 | class MetadataType: public ValueType { |
371 | public: |
372 | MetadataType(): ValueType(metaDataTag, 1) {} |
373 | virtual ValueType* base() const { return objectType; } |
374 | virtual const char tchar() const { return 'a'; } |
375 | virtual const char* name() const { return "object"; } |
376 | virtual MetadataType* as_MetadataType() { return this; } |
377 | bool is_loaded() const; |
378 | jobject encoding() const; |
379 | virtual ciMetadata* constant_value() const { ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/c1/c1_ValueType.hpp" , 379); ::breakpoint(); } while (0); return NULL__null; } |
380 | }; |
381 | |
382 | |
383 | class ClassType: public MetadataType { |
384 | public: |
385 | virtual ClassType* as_ClassType() { return this; } |
386 | }; |
387 | |
388 | |
389 | class ClassConstant: public ClassType { |
390 | private: |
391 | ciInstanceKlass* _value; |
392 | |
393 | public: |
394 | ClassConstant(ciInstanceKlass* value) { _value = value; } |
395 | |
396 | ciInstanceKlass* value() const { return _value; } |
397 | |
398 | virtual bool is_constant() const { return true; } |
399 | virtual ClassConstant* as_ClassConstant() { return this; } |
400 | virtual ciMetadata* constant_value() const { return _value; } |
401 | virtual ciType* exact_type() const; |
402 | }; |
403 | |
404 | |
405 | class MethodType: public MetadataType { |
406 | public: |
407 | virtual MethodType* as_MethodType() { return this; } |
408 | }; |
409 | |
410 | |
411 | class MethodConstant: public MethodType { |
412 | private: |
413 | ciMethod* _value; |
414 | |
415 | public: |
416 | MethodConstant(ciMethod* value) { _value = value; } |
417 | |
418 | ciMethod* value() const { return _value; } |
419 | |
420 | virtual bool is_constant() const { return true; } |
421 | |
422 | virtual MethodConstant* as_MethodConstant() { return this; } |
423 | virtual ciMetadata* constant_value() const { return _value; } |
424 | }; |
425 | |
426 | |
427 | class AddressType: public ValueType { |
428 | public: |
429 | AddressType(): ValueType(addressTag, 1) {} |
430 | virtual ValueType* base() const { return addressType; } |
431 | virtual const char tchar() const { return 'r'; } |
432 | virtual const char* name() const { return "address"; } |
433 | virtual AddressType* as_AddressType() { return this; } |
434 | }; |
435 | |
436 | |
437 | class AddressConstant: public AddressType { |
438 | private: |
439 | jint _value; |
440 | |
441 | public: |
442 | AddressConstant(jint value) { _value = value; } |
443 | |
444 | jint value() const { return _value; } |
445 | |
446 | virtual bool is_constant() const { return true; } |
447 | |
448 | virtual AddressConstant* as_AddressConstant() { return this; } |
449 | }; |
450 | |
451 | |
452 | class IllegalType: public ValueType { |
453 | public: |
454 | IllegalType(): ValueType(illegalTag, -1) {} |
455 | virtual ValueType* base() const { return illegalType; } |
456 | virtual const char tchar() const { return ' '; } |
457 | virtual const char* name() const { return "illegal"; } |
458 | virtual IllegalType* as_IllegalType() { return this; } |
459 | }; |
460 | |
461 | |
462 | // conversion between ValueTypes, BasicTypes, and ciConstants |
463 | ValueType* as_ValueType(BasicType type); |
464 | ValueType* as_ValueType(ciConstant value); |
465 | BasicType as_BasicType(ValueType* type); |
466 | |
467 | inline ValueType* as_ValueType(ciType* type) { return as_ValueType(type->basic_type()); } |
468 | |
469 | #endif // SHARE_C1_C1_VALUETYPE_HPP |