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