| File: | jdk/src/hotspot/share/opto/castnode.cpp |
| Warning: | line 210, column 25 Value stored to 't' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* |
| 2 | * Copyright (c) 2014, 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 "opto/addnode.hpp" |
| 27 | #include "opto/callnode.hpp" |
| 28 | #include "opto/castnode.hpp" |
| 29 | #include "opto/connode.hpp" |
| 30 | #include "opto/matcher.hpp" |
| 31 | #include "opto/phaseX.hpp" |
| 32 | #include "opto/subnode.hpp" |
| 33 | #include "opto/type.hpp" |
| 34 | |
| 35 | //============================================================================= |
| 36 | // If input is already higher or equal to cast type, then this is an identity. |
| 37 | Node* ConstraintCastNode::Identity(PhaseGVN* phase) { |
| 38 | Node* dom = dominating_cast(phase, phase); |
| 39 | if (dom != NULL__null) { |
| 40 | return dom; |
| 41 | } |
| 42 | if (_dependency != RegularDependency) { |
| 43 | return this; |
| 44 | } |
| 45 | return phase->type(in(1))->higher_equal_speculative(_type) ? in(1) : this; |
| 46 | } |
| 47 | |
| 48 | //------------------------------Value------------------------------------------ |
| 49 | // Take 'join' of input and cast-up type |
| 50 | const Type* ConstraintCastNode::Value(PhaseGVN* phase) const { |
| 51 | if (in(0) && phase->type(in(0)) == Type::TOP) return Type::TOP; |
| 52 | const Type* ft = phase->type(in(1))->filter_speculative(_type); |
| 53 | |
| 54 | #ifdef ASSERT1 |
| 55 | // Previous versions of this function had some special case logic, |
| 56 | // which is no longer necessary. Make sure of the required effects. |
| 57 | switch (Opcode()) { |
| 58 | case Op_CastII: |
| 59 | { |
| 60 | const Type* t1 = phase->type(in(1)); |
| 61 | if( t1 == Type::TOP ) assert(ft == Type::TOP, "special case #1")do { if (!(ft == Type::TOP)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/castnode.cpp" , 61, "assert(" "ft == Type::TOP" ") failed", "special case #1" ); ::breakpoint(); } } while (0); |
| 62 | const Type* rt = t1->join_speculative(_type); |
| 63 | if (rt->empty()) assert(ft == Type::TOP, "special case #2")do { if (!(ft == Type::TOP)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/castnode.cpp" , 63, "assert(" "ft == Type::TOP" ") failed", "special case #2" ); ::breakpoint(); } } while (0); |
| 64 | break; |
| 65 | } |
| 66 | case Op_CastPP: |
| 67 | if (phase->type(in(1)) == TypePtr::NULL_PTR && |
| 68 | _type->isa_ptr() && _type->is_ptr()->_ptr == TypePtr::NotNull) |
| 69 | assert(ft == Type::TOP, "special case #3")do { if (!(ft == Type::TOP)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/castnode.cpp" , 69, "assert(" "ft == Type::TOP" ") failed", "special case #3" ); ::breakpoint(); } } while (0); |
| 70 | break; |
| 71 | } |
| 72 | #endif //ASSERT |
| 73 | |
| 74 | return ft; |
| 75 | } |
| 76 | |
| 77 | //------------------------------Ideal------------------------------------------ |
| 78 | // Return a node which is more "ideal" than the current node. Strip out |
| 79 | // control copies |
| 80 | Node *ConstraintCastNode::Ideal(PhaseGVN *phase, bool can_reshape) { |
| 81 | return (in(0) && remove_dead_region(phase, can_reshape)) ? this : NULL__null; |
| 82 | } |
| 83 | |
| 84 | bool ConstraintCastNode::cmp(const Node &n) const { |
| 85 | return TypeNode::cmp(n) && ((ConstraintCastNode&)n)._dependency == _dependency; |
| 86 | } |
| 87 | |
| 88 | uint ConstraintCastNode::size_of() const { |
| 89 | return sizeof(*this); |
| 90 | } |
| 91 | |
| 92 | Node* ConstraintCastNode::make_cast(int opcode, Node* c, Node *n, const Type *t, DependencyType dependency) { |
| 93 | switch(opcode) { |
| 94 | case Op_CastII: { |
| 95 | Node* cast = new CastIINode(n, t, dependency); |
| 96 | cast->set_req(0, c); |
| 97 | return cast; |
| 98 | } |
| 99 | case Op_CastLL: { |
| 100 | Node* cast = new CastLLNode(n, t, dependency); |
| 101 | cast->set_req(0, c); |
| 102 | return cast; |
| 103 | } |
| 104 | case Op_CastPP: { |
| 105 | Node* cast = new CastPPNode(n, t, dependency); |
| 106 | cast->set_req(0, c); |
| 107 | return cast; |
| 108 | } |
| 109 | case Op_CastFF: { |
| 110 | Node* cast = new CastFFNode(n, t, dependency); |
| 111 | cast->set_req(0, c); |
| 112 | return cast; |
| 113 | } |
| 114 | case Op_CastDD: { |
| 115 | Node* cast = new CastDDNode(n, t, dependency); |
| 116 | cast->set_req(0, c); |
| 117 | return cast; |
| 118 | } |
| 119 | case Op_CastVV: { |
| 120 | Node* cast = new CastVVNode(n, t, dependency); |
| 121 | cast->set_req(0, c); |
| 122 | return cast; |
| 123 | } |
| 124 | case Op_CheckCastPP: return new CheckCastPPNode(c, n, t, dependency); |
| 125 | default: |
| 126 | fatal("Bad opcode %d", opcode)do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/opto/castnode.cpp" , 126, "Bad opcode %d", opcode); ::breakpoint(); } while (0); |
| 127 | } |
| 128 | return NULL__null; |
| 129 | } |
| 130 | |
| 131 | Node* ConstraintCastNode::make(Node* c, Node *n, const Type *t, BasicType bt) { |
| 132 | switch(bt) { |
| 133 | case T_INT: { |
| 134 | return make_cast(Op_CastII, c, n, t, RegularDependency); |
| 135 | } |
| 136 | case T_LONG: { |
| 137 | return make_cast(Op_CastLL, c, n, t, RegularDependency); |
| 138 | } |
| 139 | default: |
| 140 | fatal("Bad basic type %s", type2name(bt))do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/opto/castnode.cpp" , 140, "Bad basic type %s", type2name(bt)); ::breakpoint(); } while (0); |
| 141 | } |
| 142 | return NULL__null; |
| 143 | } |
| 144 | |
| 145 | TypeNode* ConstraintCastNode::dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const { |
| 146 | if (_dependency == UnconditionalDependency) { |
| 147 | return NULL__null; |
| 148 | } |
| 149 | Node* val = in(1); |
| 150 | Node* ctl = in(0); |
| 151 | int opc = Opcode(); |
| 152 | if (ctl == NULL__null) { |
| 153 | return NULL__null; |
| 154 | } |
| 155 | // Range check CastIIs may all end up under a single range check and |
| 156 | // in that case only the narrower CastII would be kept by the code |
| 157 | // below which would be incorrect. |
| 158 | if (is_CastII() && as_CastII()->has_range_check()) { |
| 159 | return NULL__null; |
| 160 | } |
| 161 | if (type()->isa_rawptr() && (gvn->type_or_null(val) == NULL__null || gvn->type(val)->isa_oopptr())) { |
| 162 | return NULL__null; |
| 163 | } |
| 164 | for (DUIterator_Fast imax, i = val->fast_outs(imax); i < imax; i++) { |
| 165 | Node* u = val->fast_out(i); |
| 166 | if (u != this && |
| 167 | u->outcnt() > 0 && |
| 168 | u->Opcode() == opc && |
| 169 | u->in(0) != NULL__null && |
| 170 | u->bottom_type()->higher_equal(type())) { |
| 171 | if (pt->is_dominator(u->in(0), ctl)) { |
| 172 | return u->as_Type(); |
| 173 | } |
| 174 | if (is_CheckCastPP() && u->in(1)->is_Proj() && u->in(1)->in(0)->is_Allocate() && |
| 175 | u->in(0)->is_Proj() && u->in(0)->in(0)->is_Initialize() && |
| 176 | u->in(1)->in(0)->as_Allocate()->initialization() == u->in(0)->in(0)) { |
| 177 | // CheckCastPP following an allocation always dominates all |
| 178 | // use of the allocation result |
| 179 | return u->as_Type(); |
| 180 | } |
| 181 | } |
| 182 | } |
| 183 | return NULL__null; |
| 184 | } |
| 185 | |
| 186 | #ifndef PRODUCT |
| 187 | void ConstraintCastNode::dump_spec(outputStream *st) const { |
| 188 | TypeNode::dump_spec(st); |
| 189 | if (_dependency != RegularDependency) { |
| 190 | st->print(" %s dependency", _dependency == StrongDependency ? "strong" : "unconditional"); |
| 191 | } |
| 192 | } |
| 193 | #endif |
| 194 | |
| 195 | const Type* CastIINode::Value(PhaseGVN* phase) const { |
| 196 | const Type *res = ConstraintCastNode::Value(phase); |
| 197 | |
| 198 | // Try to improve the type of the CastII if we recognize a CmpI/If |
| 199 | // pattern. |
| 200 | if (_dependency != RegularDependency) { |
| 201 | if (in(0) != NULL__null && in(0)->in(0) != NULL__null && in(0)->in(0)->is_If()) { |
| 202 | assert(in(0)->is_IfFalse() || in(0)->is_IfTrue(), "should be If proj")do { if (!(in(0)->is_IfFalse() || in(0)->is_IfTrue())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/castnode.cpp" , 202, "assert(" "in(0)->is_IfFalse() || in(0)->is_IfTrue()" ") failed", "should be If proj"); ::breakpoint(); } } while ( 0); |
| 203 | Node* proj = in(0); |
| 204 | if (proj->in(0)->in(1)->is_Bool()) { |
| 205 | Node* b = proj->in(0)->in(1); |
| 206 | if (b->in(1)->Opcode() == Op_CmpI) { |
| 207 | Node* cmp = b->in(1); |
| 208 | if (cmp->in(1) == in(1) && phase->type(cmp->in(2))->isa_int()) { |
| 209 | const TypeInt* in2_t = phase->type(cmp->in(2))->is_int(); |
| 210 | const Type* t = TypeInt::INT; |
Value stored to 't' during its initialization is never read | |
| 211 | BoolTest test = b->as_Bool()->_test; |
| 212 | if (proj->is_IfFalse()) { |
| 213 | test = test.negate(); |
| 214 | } |
| 215 | BoolTest::mask m = test._test; |
| 216 | jlong lo_long = min_jint; |
| 217 | jlong hi_long = max_jint; |
| 218 | if (m == BoolTest::le || m == BoolTest::lt) { |
| 219 | hi_long = in2_t->_hi; |
| 220 | if (m == BoolTest::lt) { |
| 221 | hi_long -= 1; |
| 222 | } |
| 223 | } else if (m == BoolTest::ge || m == BoolTest::gt) { |
| 224 | lo_long = in2_t->_lo; |
| 225 | if (m == BoolTest::gt) { |
| 226 | lo_long += 1; |
| 227 | } |
| 228 | } else if (m == BoolTest::eq) { |
| 229 | lo_long = in2_t->_lo; |
| 230 | hi_long = in2_t->_hi; |
| 231 | } else if (m == BoolTest::ne) { |
| 232 | // can't do any better |
| 233 | } else { |
| 234 | stringStream ss; |
| 235 | test.dump_on(&ss); |
| 236 | fatal("unexpected comparison %s", ss.as_string())do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/opto/castnode.cpp" , 236, "unexpected comparison %s", ss.as_string()); ::breakpoint (); } while (0); |
| 237 | } |
| 238 | int lo_int = (int)lo_long; |
| 239 | int hi_int = (int)hi_long; |
| 240 | |
| 241 | if (lo_long != (jlong)lo_int) { |
| 242 | lo_int = min_jint; |
| 243 | } |
| 244 | if (hi_long != (jlong)hi_int) { |
| 245 | hi_int = max_jint; |
| 246 | } |
| 247 | |
| 248 | t = TypeInt::make(lo_int, hi_int, Type::WidenMax); |
| 249 | |
| 250 | res = res->filter_speculative(t); |
| 251 | |
| 252 | return res; |
| 253 | } |
| 254 | } |
| 255 | } |
| 256 | } |
| 257 | } |
| 258 | return res; |
| 259 | } |
| 260 | |
| 261 | static Node* find_or_make_CastII(PhaseIterGVN* igvn, Node* parent, Node* control, const TypeInt* type, ConstraintCastNode::DependencyType dependency) { |
| 262 | Node* n = new CastIINode(parent, type, dependency); |
| 263 | n->set_req(0, control); |
| 264 | Node* existing = igvn->hash_find_insert(n); |
| 265 | if (existing != NULL__null) { |
| 266 | n->destruct(igvn); |
| 267 | return existing; |
| 268 | } |
| 269 | return igvn->register_new_node_with_optimizer(n); |
| 270 | } |
| 271 | |
| 272 | Node *CastIINode::Ideal(PhaseGVN *phase, bool can_reshape) { |
| 273 | Node* progress = ConstraintCastNode::Ideal(phase, can_reshape); |
| 274 | if (progress != NULL__null) { |
| 275 | return progress; |
| 276 | } |
| 277 | |
| 278 | PhaseIterGVN *igvn = phase->is_IterGVN(); |
| 279 | const TypeInt* this_type = this->type()->is_int(); |
| 280 | Node* z = in(1); |
| 281 | const TypeInteger* rx = NULL__null; |
| 282 | const TypeInteger* ry = NULL__null; |
| 283 | // Similar to ConvI2LNode::Ideal() for the same reasons |
| 284 | if (!_range_check_dependency && Compile::push_thru_add(phase, z, this_type, rx, ry, T_INT)) { |
| 285 | if (igvn == NULL__null) { |
| 286 | // Postpone this optimization to iterative GVN, where we can handle deep |
| 287 | // AddI chains without an exponential number of recursive Ideal() calls. |
| 288 | phase->record_for_igvn(this); |
| 289 | return NULL__null; |
| 290 | } |
| 291 | int op = z->Opcode(); |
| 292 | Node* x = z->in(1); |
| 293 | Node* y = z->in(2); |
| 294 | |
| 295 | Node* cx = find_or_make_CastII(igvn, x, in(0), rx->is_int(), _dependency); |
| 296 | Node* cy = find_or_make_CastII(igvn, y, in(0), ry->is_int(), _dependency); |
| 297 | switch (op) { |
| 298 | case Op_AddI: return new AddINode(cx, cy); |
| 299 | case Op_SubI: return new SubINode(cx, cy); |
| 300 | default: ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/opto/castnode.cpp" , 300); ::breakpoint(); } while (0); |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | // Similar to ConvI2LNode::Ideal() for the same reasons |
| 305 | // Do not narrow the type of range check dependent CastIINodes to |
| 306 | // avoid corruption of the graph if a CastII is replaced by TOP but |
| 307 | // the corresponding range check is not removed. |
| 308 | if (can_reshape && !_range_check_dependency) { |
| 309 | if (phase->C->post_loop_opts_phase()) { |
| 310 | const TypeInt* this_type = this->type()->is_int(); |
| 311 | const TypeInt* in_type = phase->type(in(1))->isa_int(); |
| 312 | if (in_type != NULL__null && this_type != NULL__null && |
| 313 | (in_type->_lo != this_type->_lo || |
| 314 | in_type->_hi != this_type->_hi)) { |
| 315 | jint lo1 = this_type->_lo; |
| 316 | jint hi1 = this_type->_hi; |
| 317 | int w1 = this_type->_widen; |
| 318 | |
| 319 | if (lo1 >= 0) { |
| 320 | // Keep a range assertion of >=0. |
| 321 | lo1 = 0; hi1 = max_jint; |
| 322 | } else if (hi1 < 0) { |
| 323 | // Keep a range assertion of <0. |
| 324 | lo1 = min_jint; hi1 = -1; |
| 325 | } else { |
| 326 | lo1 = min_jint; hi1 = max_jint; |
| 327 | } |
| 328 | const TypeInt* wtype = TypeInt::make(MAX2(in_type->_lo, lo1), |
| 329 | MIN2(in_type->_hi, hi1), |
| 330 | MAX2((int)in_type->_widen, w1)); |
| 331 | if (wtype != type()) { |
| 332 | set_type(wtype); |
| 333 | return this; |
| 334 | } |
| 335 | } |
| 336 | } else { |
| 337 | phase->C->record_for_post_loop_opts_igvn(this); |
| 338 | } |
| 339 | } |
| 340 | return NULL__null; |
| 341 | } |
| 342 | |
| 343 | Node* CastIINode::Identity(PhaseGVN* phase) { |
| 344 | Node* progress = ConstraintCastNode::Identity(phase); |
| 345 | if (progress != this) { |
| 346 | return progress; |
| 347 | } |
| 348 | if (_range_check_dependency) { |
| 349 | if (phase->C->post_loop_opts_phase()) { |
| 350 | return this->in(1); |
| 351 | } else { |
| 352 | phase->C->record_for_post_loop_opts_igvn(this); |
| 353 | } |
| 354 | } |
| 355 | return this; |
| 356 | } |
| 357 | |
| 358 | bool CastIINode::cmp(const Node &n) const { |
| 359 | return ConstraintCastNode::cmp(n) && ((CastIINode&)n)._range_check_dependency == _range_check_dependency; |
| 360 | } |
| 361 | |
| 362 | uint CastIINode::size_of() const { |
| 363 | return sizeof(*this); |
| 364 | } |
| 365 | |
| 366 | #ifndef PRODUCT |
| 367 | void CastIINode::dump_spec(outputStream* st) const { |
| 368 | ConstraintCastNode::dump_spec(st); |
| 369 | if (_range_check_dependency) { |
| 370 | st->print(" range check dependency"); |
| 371 | } |
| 372 | } |
| 373 | #endif |
| 374 | |
| 375 | //============================================================================= |
| 376 | //------------------------------Identity--------------------------------------- |
| 377 | // If input is already higher or equal to cast type, then this is an identity. |
| 378 | Node* CheckCastPPNode::Identity(PhaseGVN* phase) { |
| 379 | Node* dom = dominating_cast(phase, phase); |
| 380 | if (dom != NULL__null) { |
| 381 | return dom; |
| 382 | } |
| 383 | if (_dependency != RegularDependency) { |
| 384 | return this; |
| 385 | } |
| 386 | const Type* t = phase->type(in(1)); |
| 387 | if (EnableVectorReboxing && in(1)->Opcode() == Op_VectorBox) { |
| 388 | if (t->higher_equal_speculative(phase->type(this))) { |
| 389 | return in(1); |
| 390 | } |
| 391 | } else if (t == phase->type(this)) { |
| 392 | // Toned down to rescue meeting at a Phi 3 different oops all implementing |
| 393 | // the same interface. |
| 394 | return in(1); |
| 395 | } |
| 396 | return this; |
| 397 | } |
| 398 | |
| 399 | //------------------------------Value------------------------------------------ |
| 400 | // Take 'join' of input and cast-up type, unless working with an Interface |
| 401 | const Type* CheckCastPPNode::Value(PhaseGVN* phase) const { |
| 402 | if( in(0) && phase->type(in(0)) == Type::TOP ) return Type::TOP; |
| 403 | |
| 404 | const Type *inn = phase->type(in(1)); |
| 405 | if( inn == Type::TOP ) return Type::TOP; // No information yet |
| 406 | |
| 407 | const TypePtr *in_type = inn->isa_ptr(); |
| 408 | const TypePtr *my_type = _type->isa_ptr(); |
| 409 | const Type *result = _type; |
| 410 | if( in_type != NULL__null && my_type != NULL__null ) { |
| 411 | TypePtr::PTR in_ptr = in_type->ptr(); |
| 412 | if (in_ptr == TypePtr::Null) { |
| 413 | result = in_type; |
| 414 | } else if (in_ptr == TypePtr::Constant) { |
| 415 | if (my_type->isa_rawptr()) { |
| 416 | result = my_type; |
| 417 | } else { |
| 418 | const TypeOopPtr *jptr = my_type->isa_oopptr(); |
| 419 | assert(jptr, "")do { if (!(jptr)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/castnode.cpp" , 419, "assert(" "jptr" ") failed", ""); ::breakpoint(); } } while (0); |
| 420 | result = !in_type->higher_equal(_type) |
| 421 | ? my_type->cast_to_ptr_type(TypePtr::NotNull) |
| 422 | : in_type; |
| 423 | } |
| 424 | } else { |
| 425 | result = my_type->cast_to_ptr_type( my_type->join_ptr(in_ptr) ); |
| 426 | } |
| 427 | } |
| 428 | |
| 429 | // This is the code from TypePtr::xmeet() that prevents us from |
| 430 | // having 2 ways to represent the same type. We have to replicate it |
| 431 | // here because we don't go through meet/join. |
| 432 | if (result->remove_speculative() == result->speculative()) { |
| 433 | result = result->remove_speculative(); |
| 434 | } |
| 435 | |
| 436 | // Same as above: because we don't go through meet/join, remove the |
| 437 | // speculative type if we know we won't use it. |
| 438 | return result->cleanup_speculative(); |
| 439 | |
| 440 | // JOIN NOT DONE HERE BECAUSE OF INTERFACE ISSUES. |
| 441 | // FIX THIS (DO THE JOIN) WHEN UNION TYPES APPEAR! |
| 442 | |
| 443 | // |
| 444 | // Remove this code after overnight run indicates no performance |
| 445 | // loss from not performing JOIN at CheckCastPPNode |
| 446 | // |
| 447 | // const TypeInstPtr *in_oop = in->isa_instptr(); |
| 448 | // const TypeInstPtr *my_oop = _type->isa_instptr(); |
| 449 | // // If either input is an 'interface', return destination type |
| 450 | // assert (in_oop == NULL || in_oop->klass() != NULL, ""); |
| 451 | // assert (my_oop == NULL || my_oop->klass() != NULL, ""); |
| 452 | // if( (in_oop && in_oop->klass()->is_interface()) |
| 453 | // ||(my_oop && my_oop->klass()->is_interface()) ) { |
| 454 | // TypePtr::PTR in_ptr = in->isa_ptr() ? in->is_ptr()->_ptr : TypePtr::BotPTR; |
| 455 | // // Preserve cast away nullness for interfaces |
| 456 | // if( in_ptr == TypePtr::NotNull && my_oop && my_oop->_ptr == TypePtr::BotPTR ) { |
| 457 | // return my_oop->cast_to_ptr_type(TypePtr::NotNull); |
| 458 | // } |
| 459 | // return _type; |
| 460 | // } |
| 461 | // |
| 462 | // // Neither the input nor the destination type is an interface, |
| 463 | // |
| 464 | // // history: JOIN used to cause weird corner case bugs |
| 465 | // // return (in == TypeOopPtr::NULL_PTR) ? in : _type; |
| 466 | // // JOIN picks up NotNull in common instance-of/check-cast idioms, both oops. |
| 467 | // // JOIN does not preserve NotNull in other cases, e.g. RawPtr vs InstPtr |
| 468 | // const Type *join = in->join(_type); |
| 469 | // // Check if join preserved NotNull'ness for pointers |
| 470 | // if( join->isa_ptr() && _type->isa_ptr() ) { |
| 471 | // TypePtr::PTR join_ptr = join->is_ptr()->_ptr; |
| 472 | // TypePtr::PTR type_ptr = _type->is_ptr()->_ptr; |
| 473 | // // If there isn't any NotNull'ness to preserve |
| 474 | // // OR if join preserved NotNull'ness then return it |
| 475 | // if( type_ptr == TypePtr::BotPTR || type_ptr == TypePtr::Null || |
| 476 | // join_ptr == TypePtr::NotNull || join_ptr == TypePtr::Constant ) { |
| 477 | // return join; |
| 478 | // } |
| 479 | // // ELSE return same old type as before |
| 480 | // return _type; |
| 481 | // } |
| 482 | // // Not joining two pointers |
| 483 | // return join; |
| 484 | } |
| 485 | |
| 486 | //============================================================================= |
| 487 | //------------------------------Value------------------------------------------ |
| 488 | const Type* CastX2PNode::Value(PhaseGVN* phase) const { |
| 489 | const Type* t = phase->type(in(1)); |
| 490 | if (t == Type::TOP) return Type::TOP; |
| 491 | if (t->base() == Type_XType::Long && t->singleton()) { |
| 492 | uintptr_t bits = (uintptr_t) t->is_intptr_tis_long()->get_con(); |
| 493 | if (bits == 0) return TypePtr::NULL_PTR; |
| 494 | return TypeRawPtr::make((address) bits); |
| 495 | } |
| 496 | return CastX2PNode::bottom_type(); |
| 497 | } |
| 498 | |
| 499 | //------------------------------Idealize--------------------------------------- |
| 500 | static inline bool fits_in_int(const Type* t, bool but_not_min_int = false) { |
| 501 | if (t == Type::TOP) return false; |
| 502 | const TypeXTypeLong* tl = t->is_intptr_tis_long(); |
| 503 | jint lo = min_jint; |
| 504 | jint hi = max_jint; |
| 505 | if (but_not_min_int) ++lo; // caller wants to negate the value w/o overflow |
| 506 | return (tl->_lo >= lo) && (tl->_hi <= hi); |
| 507 | } |
| 508 | |
| 509 | static inline Node* addP_of_X2P(PhaseGVN *phase, |
| 510 | Node* base, |
| 511 | Node* dispX, |
| 512 | bool negate = false) { |
| 513 | if (negate) { |
| 514 | dispX = phase->transform(new SubXNodeSubLNode(phase->MakeConXlongcon(0), dispX)); |
| 515 | } |
| 516 | return new AddPNode(phase->C->top(), |
| 517 | phase->transform(new CastX2PNode(base)), |
| 518 | dispX); |
| 519 | } |
| 520 | |
| 521 | Node *CastX2PNode::Ideal(PhaseGVN *phase, bool can_reshape) { |
| 522 | // convert CastX2P(AddX(x, y)) to AddP(CastX2P(x), y) if y fits in an int |
| 523 | int op = in(1)->Opcode(); |
| 524 | Node* x; |
| 525 | Node* y; |
| 526 | switch (op) { |
| 527 | case Op_SubXOp_SubL: |
| 528 | x = in(1)->in(1); |
| 529 | // Avoid ideal transformations ping-pong between this and AddP for raw pointers. |
| 530 | if (phase->find_intptr_t_confind_long_con(x, -1) == 0) |
| 531 | break; |
| 532 | y = in(1)->in(2); |
| 533 | if (fits_in_int(phase->type(y), true)) { |
| 534 | return addP_of_X2P(phase, x, y, true); |
| 535 | } |
| 536 | break; |
| 537 | case Op_AddXOp_AddL: |
| 538 | x = in(1)->in(1); |
| 539 | y = in(1)->in(2); |
| 540 | if (fits_in_int(phase->type(y))) { |
| 541 | return addP_of_X2P(phase, x, y); |
| 542 | } |
| 543 | if (fits_in_int(phase->type(x))) { |
| 544 | return addP_of_X2P(phase, y, x); |
| 545 | } |
| 546 | break; |
| 547 | } |
| 548 | return NULL__null; |
| 549 | } |
| 550 | |
| 551 | //------------------------------Identity--------------------------------------- |
| 552 | Node* CastX2PNode::Identity(PhaseGVN* phase) { |
| 553 | if (in(1)->Opcode() == Op_CastP2X) return in(1)->in(1); |
| 554 | return this; |
| 555 | } |
| 556 | |
| 557 | //============================================================================= |
| 558 | //------------------------------Value------------------------------------------ |
| 559 | const Type* CastP2XNode::Value(PhaseGVN* phase) const { |
| 560 | const Type* t = phase->type(in(1)); |
| 561 | if (t == Type::TOP) return Type::TOP; |
| 562 | if (t->base() == Type::RawPtr && t->singleton()) { |
| 563 | uintptr_t bits = (uintptr_t) t->is_rawptr()->get_con(); |
| 564 | return TypeXTypeLong::make(bits); |
| 565 | } |
| 566 | return CastP2XNode::bottom_type(); |
| 567 | } |
| 568 | |
| 569 | Node *CastP2XNode::Ideal(PhaseGVN *phase, bool can_reshape) { |
| 570 | return (in(0) && remove_dead_region(phase, can_reshape)) ? this : NULL__null; |
| 571 | } |
| 572 | |
| 573 | //------------------------------Identity--------------------------------------- |
| 574 | Node* CastP2XNode::Identity(PhaseGVN* phase) { |
| 575 | if (in(1)->Opcode() == Op_CastX2P) return in(1)->in(1); |
| 576 | return this; |
| 577 | } |
| 578 | |
| 579 | Node* ConstraintCastNode::make_cast_for_type(Node* c, Node* in, const Type* type, DependencyType dependency) { |
| 580 | Node* cast= NULL__null; |
| 581 | if (type->isa_int()) { |
| 582 | cast = make_cast(Op_CastII, c, in, type, dependency); |
| 583 | } else if (type->isa_long()) { |
| 584 | cast = make_cast(Op_CastLL, c, in, type, dependency); |
| 585 | } else if (type->isa_float()) { |
| 586 | cast = make_cast(Op_CastFF, c, in, type, dependency); |
| 587 | } else if (type->isa_double()) { |
| 588 | cast = make_cast(Op_CastDD, c, in, type, dependency); |
| 589 | } else if (type->isa_vect()) { |
| 590 | cast = make_cast(Op_CastVV, c, in, type, dependency); |
| 591 | } else if (type->isa_ptr()) { |
| 592 | cast = make_cast(Op_CastPP, c, in, type, dependency); |
| 593 | } |
| 594 | return cast; |
| 595 | } |