< prev index next >

src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp

Print this page




 456   // create result type (range)
 457   fields = TypeTuple::fields(0);
 458   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
 459 
 460   return TypeFunc::make(domain, range);
 461 }
 462 
 463 const TypeFunc* ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type() {
 464   const Type **fields = TypeTuple::fields(1);
 465   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value
 466   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields);
 467 
 468   // create result type (range)
 469   fields = TypeTuple::fields(0);
 470   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
 471 
 472   return TypeFunc::make(domain, range);
 473 }
 474 
 475 const TypeFunc* ShenandoahBarrierSetC2::shenandoah_load_reference_barrier_Type() {
 476   const Type **fields = TypeTuple::fields(1);
 477   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value
 478   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields);


 479 
 480   // create result type (range)
 481   fields = TypeTuple::fields(1);
 482   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL;
 483   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields);
 484 
 485   return TypeFunc::make(domain, range);
 486 }
 487 
 488 Node* ShenandoahBarrierSetC2::store_at_resolved(C2Access& access, C2AccessValue& val) const {
 489   DecoratorSet decorators = access.decorators();
 490 
 491   const TypePtr* adr_type = access.addr().type();
 492   Node* adr = access.addr().node();
 493 
 494   bool anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
 495   bool on_heap = (decorators & IN_HEAP) != 0;
 496 
 497   if (!access.is_oop() || (!on_heap && !anonymous)) {
 498     return BarrierSetC2::store_at_resolved(access, val);


 527 Node* ShenandoahBarrierSetC2::load_at_resolved(C2Access& access, const Type* val_type) const {
 528   DecoratorSet decorators = access.decorators();
 529 
 530   Node* adr = access.addr().node();
 531   Node* obj = access.base();
 532 
 533   bool mismatched = (decorators & C2_MISMATCHED) != 0;
 534   bool unknown = (decorators & ON_UNKNOWN_OOP_REF) != 0;
 535   bool on_heap = (decorators & IN_HEAP) != 0;
 536   bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
 537   bool is_unordered = (decorators & MO_UNORDERED) != 0;
 538   bool need_cpu_mem_bar = !is_unordered || mismatched || !on_heap;
 539 
 540   Node* top = Compile::current()->top();
 541 
 542   Node* offset = adr->is_AddP() ? adr->in(AddPNode::Offset) : top;
 543   Node* load = BarrierSetC2::load_at_resolved(access, val_type);
 544 
 545   if (access.is_oop()) {
 546     if (ShenandoahLoadRefBarrier) {
 547       load = new ShenandoahLoadReferenceBarrierNode(NULL, load);
 548       if (access.is_parse_access()) {
 549         load = static_cast<C2ParseAccess &>(access).kit()->gvn().transform(load);
 550       } else {
 551         load = static_cast<C2OptAccess &>(access).gvn().transform(load);
 552       }
 553     }
 554   }
 555 
 556   // If we are reading the value of the referent field of a Reference
 557   // object (either by using Unsafe directly or through reflection)
 558   // then, if SATB is enabled, we need to record the referent in an
 559   // SATB log buffer using the pre-barrier mechanism.
 560   // Also we need to add memory barrier to prevent commoning reads
 561   // from this field across safepoint since GC can change its value.
 562   bool need_read_barrier = ShenandoahKeepAliveBarrier &&
 563     (on_heap && (on_weak || (unknown && offset != top && obj != top)));
 564 
 565   if (!access.is_oop() || !need_read_barrier) {
 566     return load;
 567   }


 612         load_store = kit->gvn().transform(new CompareAndExchangeNNode(kit->control(), mem, adr, newval_enc, oldval_enc, adr_type, value_type->make_narrowoop(), mo));
 613       }
 614     } else
 615 #endif
 616     {
 617       if (ShenandoahCASBarrier) {
 618         load_store = kit->gvn().transform(new ShenandoahCompareAndExchangePNode(kit->control(), mem, adr, new_val, expected_val, adr_type, value_type->is_oopptr(), mo));
 619       } else {
 620         load_store = kit->gvn().transform(new CompareAndExchangePNode(kit->control(), mem, adr, new_val, expected_val, adr_type, value_type->is_oopptr(), mo));
 621       }
 622     }
 623 
 624     access.set_raw_access(load_store);
 625     pin_atomic_op(access);
 626 
 627 #ifdef _LP64
 628     if (adr->bottom_type()->is_ptr_to_narrowoop()) {
 629       load_store = kit->gvn().transform(new DecodeNNode(load_store, load_store->get_ptr_type()));
 630     }
 631 #endif
 632     load_store = kit->gvn().transform(new ShenandoahLoadReferenceBarrierNode(NULL, load_store));
 633     return load_store;
 634   }
 635   return BarrierSetC2::atomic_cmpxchg_val_at_resolved(access, expected_val, new_val, value_type);
 636 }
 637 
 638 Node* ShenandoahBarrierSetC2::atomic_cmpxchg_bool_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
 639                                                               Node* new_val, const Type* value_type) const {
 640   GraphKit* kit = access.kit();
 641   if (access.is_oop()) {
 642     new_val = shenandoah_storeval_barrier(kit, new_val);
 643     shenandoah_write_barrier_pre(kit, false /* do_load */,
 644                                  NULL, NULL, max_juint, NULL, NULL,
 645                                  expected_val /* pre_val */, T_OBJECT);
 646     DecoratorSet decorators = access.decorators();
 647     MemNode::MemOrd mo = access.mem_node_mo();
 648     Node* mem = access.memory();
 649     bool is_weak_cas = (decorators & C2_WEAK_CMPXCHG) != 0;
 650     Node* load_store = NULL;
 651     Node* adr = access.addr().node();
 652 #ifdef _LP64


 680           load_store = kit->gvn().transform(new WeakCompareAndSwapPNode(kit->control(), mem, adr, new_val, expected_val, mo));
 681         } else {
 682           load_store = kit->gvn().transform(new CompareAndSwapPNode(kit->control(), mem, adr, new_val, expected_val, mo));
 683         }
 684       }
 685     }
 686     access.set_raw_access(load_store);
 687     pin_atomic_op(access);
 688     return load_store;
 689   }
 690   return BarrierSetC2::atomic_cmpxchg_bool_at_resolved(access, expected_val, new_val, value_type);
 691 }
 692 
 693 Node* ShenandoahBarrierSetC2::atomic_xchg_at_resolved(C2AtomicParseAccess& access, Node* val, const Type* value_type) const {
 694   GraphKit* kit = access.kit();
 695   if (access.is_oop()) {
 696     val = shenandoah_storeval_barrier(kit, val);
 697   }
 698   Node* result = BarrierSetC2::atomic_xchg_at_resolved(access, val, value_type);
 699   if (access.is_oop()) {
 700     result = kit->gvn().transform(new ShenandoahLoadReferenceBarrierNode(NULL, result));
 701     shenandoah_write_barrier_pre(kit, false /* do_load */,
 702                                  NULL, NULL, max_juint, NULL, NULL,
 703                                  result /* pre_val */, T_OBJECT);
 704   }
 705   return result;
 706 }
 707 
 708 void ShenandoahBarrierSetC2::clone(GraphKit* kit, Node* src, Node* dst, Node* size, bool is_array) const {
 709   assert(!src->is_AddP(), "unexpected input");
 710   BarrierSetC2::clone(kit, src, dst, size, is_array);
 711 }
 712 
 713 // Support for GC barriers emitted during parsing
 714 bool ShenandoahBarrierSetC2::is_gc_barrier_node(Node* node) const {
 715   if (node->Opcode() == Op_ShenandoahLoadReferenceBarrier) return true;
 716   if (node->Opcode() != Op_CallLeaf && node->Opcode() != Op_CallLeafNoFP) {
 717     return false;
 718   }
 719   CallLeafNode *call = node->as_CallLeaf();
 720   if (call->_name == NULL) {


1180     case Op_ShenandoahEnqueueBarrier:
1181       conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(1), NULL);
1182       return true;
1183     case Op_ShenandoahLoadReferenceBarrier:
1184       conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(ShenandoahLoadReferenceBarrierNode::ValueIn), NULL);
1185       return true;
1186     default:
1187       // Nothing
1188       break;
1189   }
1190   return false;
1191 }
1192 
1193 bool ShenandoahBarrierSetC2::escape_has_out_with_unsafe_object(Node* n) const {
1194   return n->has_out_with(Op_ShenandoahCompareAndExchangeP) || n->has_out_with(Op_ShenandoahCompareAndExchangeN) ||
1195          n->has_out_with(Op_ShenandoahCompareAndSwapP, Op_ShenandoahCompareAndSwapN, Op_ShenandoahWeakCompareAndSwapP, Op_ShenandoahWeakCompareAndSwapN);
1196 
1197 }
1198 
1199 bool ShenandoahBarrierSetC2::escape_is_barrier_node(Node* n) const {
1200   return n->Opcode() == Op_ShenandoahLoadReferenceBarrier;
1201 }
1202 
1203 bool ShenandoahBarrierSetC2::matcher_find_shared_post_visit(Matcher* matcher, Node* n, uint opcode) const {
1204   switch (opcode) {
1205     case Op_ShenandoahCompareAndExchangeP:
1206     case Op_ShenandoahCompareAndExchangeN:
1207     case Op_ShenandoahWeakCompareAndSwapP:
1208     case Op_ShenandoahWeakCompareAndSwapN:
1209     case Op_ShenandoahCompareAndSwapP:
1210     case Op_ShenandoahCompareAndSwapN: {   // Convert trinary to binary-tree
1211       Node* newval = n->in(MemNode::ValueIn);
1212       Node* oldval = n->in(LoadStoreConditionalNode::ExpectedIn);
1213       Node* pair = new BinaryNode(oldval, newval);
1214       n->set_req(MemNode::ValueIn,pair);
1215       n->del_req(LoadStoreConditionalNode::ExpectedIn);
1216       return true;
1217     }
1218     default:
1219       break;
1220   }


 456   // create result type (range)
 457   fields = TypeTuple::fields(0);
 458   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
 459 
 460   return TypeFunc::make(domain, range);
 461 }
 462 
 463 const TypeFunc* ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type() {
 464   const Type **fields = TypeTuple::fields(1);
 465   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value
 466   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields);
 467 
 468   // create result type (range)
 469   fields = TypeTuple::fields(0);
 470   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
 471 
 472   return TypeFunc::make(domain, range);
 473 }
 474 
 475 const TypeFunc* ShenandoahBarrierSetC2::shenandoah_load_reference_barrier_Type() {
 476   const Type **fields = TypeTuple::fields(2);
 477   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value
 478   fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM;   // original load address
 479 
 480   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields);
 481 
 482   // create result type (range)
 483   fields = TypeTuple::fields(1);
 484   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL;
 485   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields);
 486 
 487   return TypeFunc::make(domain, range);
 488 }
 489 
 490 Node* ShenandoahBarrierSetC2::store_at_resolved(C2Access& access, C2AccessValue& val) const {
 491   DecoratorSet decorators = access.decorators();
 492 
 493   const TypePtr* adr_type = access.addr().type();
 494   Node* adr = access.addr().node();
 495 
 496   bool anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
 497   bool on_heap = (decorators & IN_HEAP) != 0;
 498 
 499   if (!access.is_oop() || (!on_heap && !anonymous)) {
 500     return BarrierSetC2::store_at_resolved(access, val);


 529 Node* ShenandoahBarrierSetC2::load_at_resolved(C2Access& access, const Type* val_type) const {
 530   DecoratorSet decorators = access.decorators();
 531 
 532   Node* adr = access.addr().node();
 533   Node* obj = access.base();
 534 
 535   bool mismatched = (decorators & C2_MISMATCHED) != 0;
 536   bool unknown = (decorators & ON_UNKNOWN_OOP_REF) != 0;
 537   bool on_heap = (decorators & IN_HEAP) != 0;
 538   bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
 539   bool is_unordered = (decorators & MO_UNORDERED) != 0;
 540   bool need_cpu_mem_bar = !is_unordered || mismatched || !on_heap;
 541 
 542   Node* top = Compile::current()->top();
 543 
 544   Node* offset = adr->is_AddP() ? adr->in(AddPNode::Offset) : top;
 545   Node* load = BarrierSetC2::load_at_resolved(access, val_type);
 546 
 547   if (access.is_oop()) {
 548     if (ShenandoahLoadRefBarrier) {
 549       load = new ShenandoahLoadReferenceBarrierNode(NULL, load, adr);
 550       if (access.is_parse_access()) {
 551         load = static_cast<C2ParseAccess &>(access).kit()->gvn().transform(load);
 552       } else {
 553         load = static_cast<C2OptAccess &>(access).gvn().transform(load);
 554       }
 555     }
 556   }
 557 
 558   // If we are reading the value of the referent field of a Reference
 559   // object (either by using Unsafe directly or through reflection)
 560   // then, if SATB is enabled, we need to record the referent in an
 561   // SATB log buffer using the pre-barrier mechanism.
 562   // Also we need to add memory barrier to prevent commoning reads
 563   // from this field across safepoint since GC can change its value.
 564   bool need_read_barrier = ShenandoahKeepAliveBarrier &&
 565     (on_heap && (on_weak || (unknown && offset != top && obj != top)));
 566 
 567   if (!access.is_oop() || !need_read_barrier) {
 568     return load;
 569   }


 614         load_store = kit->gvn().transform(new CompareAndExchangeNNode(kit->control(), mem, adr, newval_enc, oldval_enc, adr_type, value_type->make_narrowoop(), mo));
 615       }
 616     } else
 617 #endif
 618     {
 619       if (ShenandoahCASBarrier) {
 620         load_store = kit->gvn().transform(new ShenandoahCompareAndExchangePNode(kit->control(), mem, adr, new_val, expected_val, adr_type, value_type->is_oopptr(), mo));
 621       } else {
 622         load_store = kit->gvn().transform(new CompareAndExchangePNode(kit->control(), mem, adr, new_val, expected_val, adr_type, value_type->is_oopptr(), mo));
 623       }
 624     }
 625 
 626     access.set_raw_access(load_store);
 627     pin_atomic_op(access);
 628 
 629 #ifdef _LP64
 630     if (adr->bottom_type()->is_ptr_to_narrowoop()) {
 631       load_store = kit->gvn().transform(new DecodeNNode(load_store, load_store->get_ptr_type()));
 632     }
 633 #endif
 634     load_store = kit->gvn().transform(new ShenandoahLoadReferenceBarrierNode(NULL, load_store, kit->null()));
 635     return load_store;
 636   }
 637   return BarrierSetC2::atomic_cmpxchg_val_at_resolved(access, expected_val, new_val, value_type);
 638 }
 639 
 640 Node* ShenandoahBarrierSetC2::atomic_cmpxchg_bool_at_resolved(C2AtomicParseAccess& access, Node* expected_val,
 641                                                               Node* new_val, const Type* value_type) const {
 642   GraphKit* kit = access.kit();
 643   if (access.is_oop()) {
 644     new_val = shenandoah_storeval_barrier(kit, new_val);
 645     shenandoah_write_barrier_pre(kit, false /* do_load */,
 646                                  NULL, NULL, max_juint, NULL, NULL,
 647                                  expected_val /* pre_val */, T_OBJECT);
 648     DecoratorSet decorators = access.decorators();
 649     MemNode::MemOrd mo = access.mem_node_mo();
 650     Node* mem = access.memory();
 651     bool is_weak_cas = (decorators & C2_WEAK_CMPXCHG) != 0;
 652     Node* load_store = NULL;
 653     Node* adr = access.addr().node();
 654 #ifdef _LP64


 682           load_store = kit->gvn().transform(new WeakCompareAndSwapPNode(kit->control(), mem, adr, new_val, expected_val, mo));
 683         } else {
 684           load_store = kit->gvn().transform(new CompareAndSwapPNode(kit->control(), mem, adr, new_val, expected_val, mo));
 685         }
 686       }
 687     }
 688     access.set_raw_access(load_store);
 689     pin_atomic_op(access);
 690     return load_store;
 691   }
 692   return BarrierSetC2::atomic_cmpxchg_bool_at_resolved(access, expected_val, new_val, value_type);
 693 }
 694 
 695 Node* ShenandoahBarrierSetC2::atomic_xchg_at_resolved(C2AtomicParseAccess& access, Node* val, const Type* value_type) const {
 696   GraphKit* kit = access.kit();
 697   if (access.is_oop()) {
 698     val = shenandoah_storeval_barrier(kit, val);
 699   }
 700   Node* result = BarrierSetC2::atomic_xchg_at_resolved(access, val, value_type);
 701   if (access.is_oop()) {
 702     result = kit->gvn().transform(new ShenandoahLoadReferenceBarrierNode(NULL, result, kit->null()));
 703     shenandoah_write_barrier_pre(kit, false /* do_load */,
 704                                  NULL, NULL, max_juint, NULL, NULL,
 705                                  result /* pre_val */, T_OBJECT);
 706   }
 707   return result;
 708 }
 709 
 710 void ShenandoahBarrierSetC2::clone(GraphKit* kit, Node* src, Node* dst, Node* size, bool is_array) const {
 711   assert(!src->is_AddP(), "unexpected input");
 712   BarrierSetC2::clone(kit, src, dst, size, is_array);
 713 }
 714 
 715 // Support for GC barriers emitted during parsing
 716 bool ShenandoahBarrierSetC2::is_gc_barrier_node(Node* node) const {
 717   if (node->Opcode() == Op_ShenandoahLoadReferenceBarrier) return true;
 718   if (node->Opcode() != Op_CallLeaf && node->Opcode() != Op_CallLeafNoFP) {
 719     return false;
 720   }
 721   CallLeafNode *call = node->as_CallLeaf();
 722   if (call->_name == NULL) {


1182     case Op_ShenandoahEnqueueBarrier:
1183       conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(1), NULL);
1184       return true;
1185     case Op_ShenandoahLoadReferenceBarrier:
1186       conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(ShenandoahLoadReferenceBarrierNode::ValueIn), NULL);
1187       return true;
1188     default:
1189       // Nothing
1190       break;
1191   }
1192   return false;
1193 }
1194 
1195 bool ShenandoahBarrierSetC2::escape_has_out_with_unsafe_object(Node* n) const {
1196   return n->has_out_with(Op_ShenandoahCompareAndExchangeP) || n->has_out_with(Op_ShenandoahCompareAndExchangeN) ||
1197          n->has_out_with(Op_ShenandoahCompareAndSwapP, Op_ShenandoahCompareAndSwapN, Op_ShenandoahWeakCompareAndSwapP, Op_ShenandoahWeakCompareAndSwapN);
1198 
1199 }
1200 
1201 bool ShenandoahBarrierSetC2::escape_is_barrier_node(Node* n) const {
1202   return false;
1203 }
1204 
1205 bool ShenandoahBarrierSetC2::matcher_find_shared_post_visit(Matcher* matcher, Node* n, uint opcode) const {
1206   switch (opcode) {
1207     case Op_ShenandoahCompareAndExchangeP:
1208     case Op_ShenandoahCompareAndExchangeN:
1209     case Op_ShenandoahWeakCompareAndSwapP:
1210     case Op_ShenandoahWeakCompareAndSwapN:
1211     case Op_ShenandoahCompareAndSwapP:
1212     case Op_ShenandoahCompareAndSwapN: {   // Convert trinary to binary-tree
1213       Node* newval = n->in(MemNode::ValueIn);
1214       Node* oldval = n->in(LoadStoreConditionalNode::ExpectedIn);
1215       Node* pair = new BinaryNode(oldval, newval);
1216       n->set_req(MemNode::ValueIn,pair);
1217       n->del_req(LoadStoreConditionalNode::ExpectedIn);
1218       return true;
1219     }
1220     default:
1221       break;
1222   }
< prev index next >