| 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 |