1 /* 2 * Copyright (c) 2015, Red Hat, Inc. and/or its affiliates. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 #include "gc/shenandoah/brooksPointer.hpp" 25 #include "opto/callnode.hpp" 26 #include "opto/movenode.hpp" 27 #include "opto/phaseX.hpp" 28 #include "opto/shenandoahSupport.hpp" 29 30 Node* ShenandoahBarrierNode::skip_through_barrier(Node* n) { 31 if (n->is_ShenandoahBarrier()) { 32 return n->in(ValueIn); 33 } else { 34 return n; 35 } 36 } 37 38 bool ShenandoahBarrierNode::needs_barrier(PhaseTransform* phase, Node* orig, Node* n, Node* rb_mem) { 39 Unique_Node_List visited; 40 return needs_barrier_impl(phase, orig, n, rb_mem, visited); 41 } 42 43 bool ShenandoahBarrierNode::needs_barrier_impl(PhaseTransform* phase, Node* orig, Node* n, Node* rb_mem, Unique_Node_List &visited) { 44 45 if (visited.member(n)) { 46 return false; // Been there. 47 } 48 visited.push(n); 49 50 if (n->is_Allocate()) { 51 // tty->print_cr("killed barrier for newly allocated object"); 52 return false; 53 } 54 55 if (n->is_CallJava()) { 56 return true; 57 } 58 59 const Type* type = phase->type(n); 60 if (type->higher_equal(TypePtr::NULL_PTR)) { 61 // tty->print_cr("killed barrier for NULL object"); 62 return false; 63 } 64 if (type->isa_oopptr() && type->is_oopptr()->const_oop() != NULL) { 65 // tty->print_cr("killed barrier for constant object"); 66 return false; 67 } 68 69 if (n->is_CheckCastPP() || n->is_ConstraintCast()) { 70 return needs_barrier_impl(phase, orig, n->in(1), rb_mem, visited); 71 } 72 if (n->is_Parm()) { 73 return true; 74 } 75 if (n->is_Proj()) { 76 return needs_barrier_impl(phase, orig, n->in(0), rb_mem, visited); 77 } 78 if (n->is_Phi()) { 79 bool need_barrier = false; 80 for (uint i = 1; i < n->req() && ! need_barrier; i++) { 81 Node* input = n->in(i); 82 if (input == NULL) { 83 need_barrier = true; // Phi not complete yet? 84 } else if (needs_barrier_impl(phase, orig, input, rb_mem, visited)) { 85 need_barrier = true; 86 } 87 } 88 return need_barrier; 89 } 90 if (n->is_CMove()) { 91 return needs_barrier_impl(phase, orig, n->in(CMoveNode::IfFalse), rb_mem, visited) || 92 needs_barrier_impl(phase, orig, n->in(CMoveNode::IfTrue ), rb_mem, visited); 93 } 94 if (n->Opcode() == Op_CreateEx) { 95 return true; 96 } 97 if (n->Opcode() == Op_ShenandoahWriteBarrier) { 98 // tty->print_cr("skipped barrier for chained write barrier object"); 99 return false; 100 } 101 if (n->Opcode() == Op_ShenandoahReadBarrier) { 102 if (rb_mem == n->in(Memory)) { 103 // tty->print_cr("Eliminated chained read barrier"); 104 return false; 105 } else { 106 return true; 107 } 108 } 109 110 if (n->Opcode() == Op_LoadP) { 111 return true; 112 } 113 #ifdef ASSERT 114 tty->print("need barrier on?: "); n->dump(); 115 #endif 116 return true; 117 } 118 119 bool ShenandoahReadBarrierNode::dominates_memory_rb_impl(PhaseTransform* phase, 120 Node* b1, 121 Node* b2, 122 Node* current, 123 Unique_Node_List &visited) { 124 if (current == NULL) { 125 return false; // Incomplete phi. Try again later. 126 } else if (visited.member(current)) { 127 // We have already seen it. 128 return true; 129 } 130 visited.push(current); 131 132 if (current == b1) { 133 return true; 134 } else if (current == phase->C->immutable_memory()) { 135 return false; 136 } else if (current->isa_Phi()) { 137 bool dominates = true; 138 for (uint i = 1; i < current->req() && dominates == true; i++) { 139 Node* in = current->in(i); 140 dominates = dominates && dominates_memory_rb_impl(phase, b1, b2, in, visited); 141 } 142 return dominates; 143 } else if (current->Opcode() == Op_ShenandoahWriteBarrier) { 144 const Type* in_type = current->bottom_type(); 145 const Type* this_type = b2->bottom_type(); 146 if (is_independent(in_type, this_type)) { 147 Node* in = current->in(Memory); 148 return dominates_memory_rb_impl(phase, b1, b2, in, visited); 149 } else { 150 return false; 151 } 152 } else if (current->Opcode() == Op_ShenandoahWBMemProj) { 153 Node* in = current->in(0); 154 return dominates_memory_rb_impl(phase, b1, b2, in, visited); 155 } else if (current->is_top()) { 156 return true; // Dead path 157 } else if (current->is_Proj()) { 158 return dominates_memory_rb_impl(phase, b1, b2, current->in(0), visited); 159 } else if (current->is_Call()) { 160 return false; // TODO: Maybe improve by looking at the call's memory effects? 161 } else if (current->is_MemBar()) { 162 return false; // TODO: Do we need to stop at *any* membar? 163 } else if (current->is_MergeMem()) { 164 // if (true) return false; 165 // tty->print_cr("current == mergemem: "); current->dump(); 166 const TypePtr* adr_type = phase->type(b2)->is_ptr()->add_offset(BrooksPointer::BYTE_OFFSET); 167 uint alias_idx = phase->C->get_alias_index(adr_type); 168 Node* mem_in = current->as_MergeMem()->memory_at(alias_idx); 169 return dominates_memory_rb_impl(phase, b1, b2, current->in(TypeFunc::Memory), visited); 170 } else { 171 // tty->print_cr("what else can we see here:"); 172 #ifdef ASSERT 173 current->dump(); 174 #endif 175 ShouldNotReachHere(); 176 return false; 177 } 178 } 179 180 bool ShenandoahReadBarrierNode::dominates_memory_rb(PhaseTransform* phase, Node* b1, Node* b2) { 181 Unique_Node_List visited; 182 return dominates_memory_rb_impl(phase, b1->in(Memory), b2, b2->in(Memory), visited); 183 } 184 185 bool ShenandoahReadBarrierNode::is_independent(const Type* in_type, const Type* this_type) const { 186 assert(in_type->isa_oopptr(), "expect oop ptr"); 187 assert(this_type->isa_oopptr(), "expect oop ptr"); 188 /* 189 if ((! in_type->isa_oopptr()) || (! this_type->isa_oopptr())) { 190 #ifdef ASSERT 191 tty->print_cr("not oopptr"); 192 tty->print("in: "); in_type->dump(); tty->print_cr(" "); 193 tty->print("this: "); this_type->dump(); tty->print_cr(" "); 194 #endif 195 return false; 196 } 197 */ 198 199 ciKlass* in_kls = in_type->is_oopptr()->klass(); 200 ciKlass* this_kls = this_type->is_oopptr()->klass(); 201 if ((!in_kls->is_subclass_of(this_kls)) && 202 (!this_kls->is_subclass_of(in_kls))) { 203 #ifdef ASSERT 204 // tty->print_cr("independent: "); 205 // tty->print("in: "); in_kls->print(); tty->print_cr(" "); 206 // tty->print("this: "); this_kls->print(); tty->print_cr(" "); 207 #endif 208 return true; 209 } 210 #ifdef ASSERT 211 // tty->print_cr("possibly dependend?"); 212 // tty->print("in: "); in_type->dump(); tty->print_cr(" "); 213 // tty->print("this: "); this_type->dump(); tty->print_cr(" "); 214 #endif 215 return false; 216 } 217 218 Node* ShenandoahReadBarrierNode::Ideal(PhaseGVN *phase, bool can_reshape) { 219 220 if (! can_reshape) { 221 return NULL; 222 } 223 224 if (in(Memory) == phase->C->immutable_memory()) return NULL; 225 226 // If memory input is a MergeMem, take the appropriate slice out of it. 227 Node* mem_in = in(Memory); 228 if (mem_in->isa_MergeMem()) { 229 const TypePtr* adr_type = bottom_type()->is_ptr()->add_offset(BrooksPointer::BYTE_OFFSET); 230 uint alias_idx = phase->C->get_alias_index(adr_type); 231 mem_in = mem_in->as_MergeMem()->memory_at(alias_idx); 232 set_req(Memory, mem_in); 233 return this; 234 } 235 236 Node* input = in(Memory); 237 if (input->Opcode() == Op_ShenandoahWBMemProj) { 238 input = input->in(0); 239 if (input->is_top()) return NULL; // Dead path. 240 assert(input->Opcode() == Op_ShenandoahWriteBarrier, "expect write barrier"); 241 const Type* in_type = phase->type(input); 242 const Type* this_type = phase->type(this); 243 if (is_independent(in_type, this_type)) { 244 phase->igvn_rehash_node_delayed(input); 245 set_req(Memory, input->in(Memory)); 246 return this; 247 } 248 } 249 return NULL; 250 } 251 252 bool ShenandoahBarrierNode::has_barrier_users(Node* n, Unique_Node_List &visited) { 253 if (visited.member(n)) { 254 return false; 255 } 256 visited.push(n); 257 258 bool has_users = false; 259 for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax && ! has_users; j++) { 260 Node* o = n->fast_out(j); 261 if (o->Opcode() == Op_ShenandoahReadBarrier || 262 o->Opcode() == Op_ShenandoahWriteBarrier) { 263 // tty->print("counting barrier"); o->dump(); 264 has_users = true; 265 } else if (o->isa_Phi()) { 266 has_users = has_barrier_users(o, visited); 267 } else if (o->Opcode() == Op_MergeMem) { 268 // Not a user. ? 269 } else { 270 // tty->print_cr("unknown user"); o->dump(); 271 ShouldNotReachHere(); 272 } 273 } 274 return has_users; 275 } 276 277 Node* ShenandoahWriteBarrierNode::Ideal(PhaseGVN *phase, bool can_reshape) { 278 279 if (! can_reshape) return NULL; 280 281 if (in(Memory) == phase->C->immutable_memory()) return NULL; 282 283 Node* mem_in = in(Memory); 284 if (mem_in->isa_MergeMem()) { 285 const TypePtr* adr_type = bottom_type()->is_ptr()->add_offset(BrooksPointer::BYTE_OFFSET); 286 uint alias_idx = phase->C->get_alias_index(adr_type); 287 mem_in = mem_in->as_MergeMem()->memory_at(alias_idx); 288 set_req(Memory, mem_in); 289 return this; 290 } 291 292 Node* mem_proj = find_out_with(Op_ShenandoahWBMemProj); 293 if (mem_proj == NULL) { 294 // tty->print_cr("no mem proj: kill input mem"); dump(); 295 set_req(Memory, phase->C->immutable_memory()); 296 return this; 297 } 298 299 // if (true) return NULL; 300 301 Unique_Node_List visited; 302 if (! has_barrier_users(mem_proj, visited)) { 303 // tty->print_cr("no users of mem projection. kill input mem"); dump(); 304 phase->igvn_rehash_node_delayed(in(Memory)); 305 set_req(Memory, phase->C->immutable_memory()); 306 307 // tty->print_cr("reshaped wb: "); 308 // dump(); 309 return this; 310 } 311 // tty->print_cr("leave mem proj alone"); 312 return NULL; 313 } 314 /* 315 bool ShenandoahBarrierNode::dominates_control_impl(PhaseTransform* phase, 316 Node* c1, 317 Node* c2, 318 Node* current, 319 Unique_Node_List & visited) { 320 if (current == NULL) { 321 return true; 322 } else if (visited.member(current)) { 323 return true; 324 } 325 visited.push(current); 326 327 current->dump(); 328 ShouldNotReachHere(); 329 } 330 */ 331 332 bool ShenandoahBarrierNode::dominates_control(PhaseTransform* phase, 333 Node* c1, 334 Node* c2) { 335 if (c1 == c2) { 336 return true; 337 } 338 if (c1 == NULL) { 339 return true; 340 } 341 #ifdef ASSERT 342 tty->print("c1: "); c1->dump(2); 343 tty->print("c2: "); c2->dump(2); 344 #endif 345 ShouldNotReachHere(); 346 return false; 347 } 348 349 bool ShenandoahBarrierNode::dominates_memory_impl(PhaseTransform* phase, 350 Node* b1, 351 Node* b2, 352 Node* current, 353 Unique_Node_List &visited) { 354 /* 355 tty->print_cr("phistack:"); 356 for (int x = 0; x < phistack->length(); x++) { 357 tty->print("-->"); 358 phistack->at(x)->dump(); 359 } 360 */ 361 if (current == NULL) { 362 return false; 363 } else if (visited.member(current)) { 364 // We have already seen it. 365 return true; 366 } 367 368 visited.push(current); 369 370 if (current == b1) { 371 // tty->print_cr("current == b1: "); current->dump(); 372 return true; 373 } else if (current == b2) { 374 // tty->print_cr("current == b2: "); current->dump(); 375 return false; 376 } else if (current == phase->C->immutable_memory()) { 377 // tty->print_cr("current == immutable_memory: "); current->dump(); 378 return false; 379 } else if (current->isa_Phi()) { 380 // tty->print_cr("current == phi: "); current->dump(); 381 bool dominates = true; 382 for (uint i = 1; i < current->req() && dominates == true; i++) { 383 Node* in = current->in(i); 384 dominates = dominates && dominates_memory_impl(phase, b1, b2, in, visited); 385 } 386 return dominates; 387 } else if (current->Opcode() == Op_ShenandoahWriteBarrier) { 388 // tty->print_cr("current == wb: "); current->dump(); 389 // Follow through memory input. 390 Node* in = current->in(Memory); 391 return dominates_memory_impl(phase, b1, b2, in, visited); 392 } else if (current->Opcode() == Op_ShenandoahWBMemProj) { 393 // tty->print_cr("current == wb-memproj: "); current->dump(); 394 // Follow through memory input. 395 Node* in = current->in(0); 396 return dominates_memory_impl(phase, b1, b2, in, visited); 397 } else if (current->is_top()) { 398 return true; // Dead path 399 } else if (current->is_Proj()) { 400 // tty->print_cr("current == proj: "); current->dump(); 401 return dominates_memory_impl(phase, b1, b2, current->in(0), visited); 402 } else if (current->is_Call()) { 403 // tty->print_cr("current == call: "); current->dump(); 404 return dominates_memory_impl(phase, b1, b2, current->in(TypeFunc::Memory), visited); 405 } else if (current->is_MemBar()) { 406 // tty->print_cr("current == membar: "); current->dump(); 407 return dominates_memory_impl(phase, b1, b2, current->in(TypeFunc::Memory), visited); 408 } else if (current->is_MergeMem()) { 409 // tty->print_cr("current == mergemem: "); current->dump(); 410 const TypePtr* adr_type = phase->type(b2)->is_ptr()->add_offset(BrooksPointer::BYTE_OFFSET); 411 uint alias_idx = phase->C->get_alias_index(adr_type); 412 Node* mem_in = current->as_MergeMem()->memory_at(alias_idx); 413 return dominates_memory_impl(phase, b1, b2, current->in(TypeFunc::Memory), visited); 414 } else { 415 // tty->print_cr("what else can we see here:"); 416 #ifdef ASSERT 417 current->dump(); 418 #endif 419 ShouldNotReachHere(); 420 return false; 421 } 422 } 423 424 /** 425 * Determines if b1 dominates b2 through memory inputs. It returns true if: 426 * - b1 can be reached by following each branch in b2's memory input (through phis, etc) 427 * - or we get back to b2 (i.e. through a loop) without seeing b1 428 * In all other cases, (in particular, if we reach immutable_memory without having seen b1) 429 * we return false. 430 */ 431 bool ShenandoahBarrierNode::dominates_memory(PhaseTransform* phase, Node* b1, Node* b2) { 432 Unique_Node_List visited; 433 return dominates_memory_impl(phase, b1->in(Memory), b2, b2->in(Memory), visited); 434 } 435 436 Node* ShenandoahBarrierNode::Identity_impl(PhaseTransform* phase) { 437 Node* n = in(ValueIn); 438 439 Node* rb_mem = Opcode() == Op_ShenandoahReadBarrier ? in(Memory) : NULL; 440 if (! needs_barrier(phase, this, n, rb_mem)) { 441 return n; 442 } 443 444 // tty->print_cr("find sibling for: "); dump(2); 445 // Try to find a write barrier sibling with identical inputs that we can fold into. 446 for (DUIterator i = n->outs(); n->has_out(i); i++) { 447 Node* sibling = n->out(i); 448 if (sibling == this) { 449 continue; 450 } 451 /* 452 assert(sibling->Opcode() != Op_ShenandoahWriteBarrier || 453 Opcode() != Op_ShenandoahWriteBarrier || hash() == sibling->hash(), 454 "if this is a write barrier, then sibling can't be write barrier too"); 455 */ 456 if (sibling->Opcode() != Op_ShenandoahWriteBarrier) { 457 continue; 458 } 459 /* 460 if (sibling->outcnt() == 0) { 461 // Some dead node. 462 continue; 463 } 464 */ 465 assert(sibling->in(ValueIn) == in(ValueIn), "sanity"); 466 assert(sibling->Opcode() == Op_ShenandoahWriteBarrier, "sanity"); 467 // tty->print_cr("candidate: "); sibling->dump(); 468 469 if (dominates_control(phase, sibling->in(Control), in(Control)) && 470 dominates_memory(phase, sibling, this)) { 471 472 /* 473 tty->print_cr("matched barrier:"); 474 sibling->dump(); 475 tty->print_cr("for: "); 476 dump(); 477 */ 478 return sibling; 479 } 480 481 /* 482 tty->print_cr("couldn't match candidate:"); 483 sibling->dump(2); 484 */ 485 } 486 /* 487 tty->print_cr("couldn't match barrier to any:"); 488 dump(); 489 */ 490 return this; 491 } 492 493 Node* ShenandoahBarrierNode::Identity(PhaseTransform* phase) { 494 495 Node* replacement = Identity_impl(phase); 496 if (replacement != this) { 497 // If we have a memory projection, we first need to make it go away. 498 Node* mem_proj = find_out_with(Op_ShenandoahWBMemProj); 499 if (mem_proj != NULL) { 500 phase->igvn_rehash_node_delayed(mem_proj); 501 return this; 502 } 503 } 504 return replacement; 505 } 506 507 Node* ShenandoahReadBarrierNode::Identity(PhaseTransform* phase) { 508 509 // if (true) return this; 510 511 // tty->print("optimizing rb: "); dump(); 512 Node* id = ShenandoahBarrierNode::Identity(phase); 513 514 if (id == this && phase->is_IterGVN()) { 515 Node* n = in(ValueIn); 516 // No success in super call. Try to combine identical read barriers. 517 for (DUIterator i = n->outs(); n->has_out(i); i++) { 518 Node* sibling = n->out(i); 519 if (sibling == this || sibling->Opcode() != Op_ShenandoahReadBarrier) { 520 continue; 521 } 522 assert(sibling->in(ValueIn) == in(ValueIn), "sanity"); 523 if (phase->is_IterGVN()->hash_find(sibling) && 524 sibling->bottom_type() == bottom_type() && 525 sibling->in(Control) == in(Control) && 526 dominates_memory_rb(phase, sibling, this)) { 527 /* 528 if (in(Memory) != sibling->in(Memory)) { 529 tty->print_cr("interesting rb-fold"); 530 dump(); 531 sibling->dump(); 532 } 533 */ 534 return sibling; 535 } 536 } 537 } 538 return id; 539 } 540 541 const Type* ShenandoahBarrierNode::Value(PhaseTransform* phase) const { 542 // Either input is TOP ==> the result is TOP 543 const Type *t1 = phase->type(in(Memory)); 544 if (t1 == Type::TOP) return Type::TOP; 545 const Type *t2 = phase->type(in(ValueIn)); 546 if( t2 == Type::TOP ) return Type::TOP; 547 548 Node* input = in(ValueIn); 549 const Type* type = phase->type(input); 550 return type; 551 } 552 553 Node* ShenandoahWBMemProjNode::Identity(PhaseTransform* phase) { 554 555 Node* wb = in(0); 556 if (wb->is_top()) return phase->C->top(); // Dead path. 557 558 assert(wb->Opcode() == Op_ShenandoahWriteBarrier, "expect write barrier"); 559 if (wb->as_ShenandoahBarrier()->Identity_impl(phase) != wb) { 560 // If the parent write barrier would go away, make this mem proj go away first. 561 // Poke parent to give it a chance to go away too. 562 phase->igvn_rehash_node_delayed(wb); 563 return wb->in(ShenandoahBarrierNode::Memory); 564 } 565 566 // We can't do the below unless the graph is fully constructed. 567 if (! phase->is_IterGVN()) { 568 return this; 569 } 570 571 // If the mem projection has no barrier users, it's not needed anymore. 572 Unique_Node_List visited; 573 if (! ShenandoahWriteBarrierNode::has_barrier_users(this, visited)) { 574 // tty->print_cr("mem proj has no users. kill"); dump(); 575 phase->igvn_rehash_node_delayed(wb); 576 return wb->in(ShenandoahBarrierNode::Memory); 577 } 578 579 return this; 580 }