< prev index next >

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

Print this page




  21  *
  22  */
  23 
  24 #include "precompiled.hpp"
  25 #include "gc/shared/barrierSet.hpp"
  26 #include "gc/shenandoah/shenandoahForwarding.hpp"
  27 #include "gc/shenandoah/shenandoahHeap.hpp"
  28 #include "gc/shenandoah/shenandoahHeuristics.hpp"
  29 #include "gc/shenandoah/shenandoahRuntime.hpp"
  30 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
  31 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
  32 #include "gc/shenandoah/c2/shenandoahSupport.hpp"
  33 #include "opto/arraycopynode.hpp"
  34 #include "opto/escape.hpp"
  35 #include "opto/graphKit.hpp"
  36 #include "opto/idealKit.hpp"
  37 #include "opto/macro.hpp"
  38 #include "opto/movenode.hpp"
  39 #include "opto/narrowptrnode.hpp"
  40 #include "opto/rootnode.hpp"

  41 
  42 ShenandoahBarrierSetC2* ShenandoahBarrierSetC2::bsc2() {
  43   return reinterpret_cast<ShenandoahBarrierSetC2*>(BarrierSet::barrier_set()->barrier_set_c2());
  44 }
  45 
  46 ShenandoahBarrierSetC2State::ShenandoahBarrierSetC2State(Arena* comp_arena)
  47   : _enqueue_barriers(new (comp_arena) GrowableArray<ShenandoahEnqueueBarrierNode*>(comp_arena, 8,  0, NULL)),
  48     _load_reference_barriers(new (comp_arena) GrowableArray<ShenandoahLoadReferenceBarrierNode*>(comp_arena, 8,  0, NULL)) {
  49 }
  50 
  51 int ShenandoahBarrierSetC2State::enqueue_barriers_count() const {
  52   return _enqueue_barriers->length();
  53 }
  54 
  55 ShenandoahEnqueueBarrierNode* ShenandoahBarrierSetC2State::enqueue_barrier(int idx) const {
  56   return _enqueue_barriers->at(idx);
  57 }
  58 
  59 void ShenandoahBarrierSetC2State::add_enqueue_barrier(ShenandoahEnqueueBarrierNode * n) {
  60   assert(!_enqueue_barriers->contains(n), "duplicate entry in barrier list");


 444   // Final sync IdealKit and GraphKit.
 445   kit->final_sync(ideal);
 446 }
 447 
 448 #undef __
 449 
 450 const TypeFunc* ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type() {
 451   const Type **fields = TypeTuple::fields(2);
 452   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value
 453   fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // thread
 454   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields);
 455 
 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(3);
 465   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // src
 466   fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // dst
 467   fields[TypeFunc::Parms+2] = TypeInt::INT; // length
 468   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+3, fields);
 469 
 470   // create result type (range)
 471   fields = TypeTuple::fields(0);
 472   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
 473 
 474   return TypeFunc::make(domain, range);
 475 }
 476 
 477 const TypeFunc* ShenandoahBarrierSetC2::shenandoah_load_reference_barrier_Type() {
 478   const Type **fields = TypeTuple::fields(2);
 479   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value
 480   fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM;   // original load address
 481 
 482   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields);
 483 
 484   // create result type (range)
 485   fields = TypeTuple::fields(1);
 486   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL;
 487   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields);
 488 


 779         return true;
 780       } else {
 781         if (!src_type->klass_is_exact()) {
 782           Compile::current()->dependencies()->assert_leaf_type(ik);
 783         }
 784       }
 785     } else {
 786       return true;
 787         }
 788   } else if (src_type->isa_aryptr()) {
 789     BasicType src_elem  = src_type->klass()->as_array_klass()->element_type()->basic_type();
 790     if (src_elem == T_OBJECT || src_elem == T_ARRAY) {
 791       return true;
 792     }
 793   } else {
 794     return true;
 795   }
 796   return false;
 797 }
 798 
 799 #define XTOP LP64_ONLY(COMMA phase->top())
 800 
 801 void ShenandoahBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const {
 802   Node* ctrl = ac->in(TypeFunc::Control);
 803   Node* mem = ac->in(TypeFunc::Memory);
 804   Node* src = ac->in(ArrayCopyNode::Src);
 805   Node* src_offset = ac->in(ArrayCopyNode::SrcPos);
 806   Node* dest = ac->in(ArrayCopyNode::Dest);
 807   Node* dest_offset = ac->in(ArrayCopyNode::DestPos);
 808   Node* length = ac->in(ArrayCopyNode::Length);
 809   assert (src_offset == NULL && dest_offset == NULL, "for clone offsets should be null");



 810   if (ShenandoahCloneBarrier && clone_needs_barrier(src, phase->igvn())) {
 811     Node* call = phase->make_leaf_call(ctrl, mem,





























 812                     ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type(),
 813                     CAST_FROM_FN_PTR(address, ShenandoahRuntime::shenandoah_clone_barrier),
 814                     "shenandoah_clone",
 815                     TypeRawPtr::BOTTOM,
 816                     src, dest, length);
 817     call = phase->transform_later(call);




















 818     phase->igvn().replace_node(ac, call);
 819   } else {
 820     BarrierSetC2::clone_at_expansion(phase, ac);
 821   }
 822 }
 823 
 824 
 825 // Support for macro expanded GC barriers
 826 void ShenandoahBarrierSetC2::register_potential_barrier_node(Node* node) const {
 827   if (node->Opcode() == Op_ShenandoahEnqueueBarrier) {
 828     state()->add_enqueue_barrier((ShenandoahEnqueueBarrierNode*) node);
 829   }
 830   if (node->Opcode() == Op_ShenandoahLoadReferenceBarrier) {
 831     state()->add_load_reference_barrier((ShenandoahLoadReferenceBarrierNode*) node);
 832   }
 833 }
 834 
 835 void ShenandoahBarrierSetC2::unregister_potential_barrier_node(Node* node) const {
 836   if (node->Opcode() == Op_ShenandoahEnqueueBarrier) {
 837     state()->remove_enqueue_barrier((ShenandoahEnqueueBarrierNode*) node);




  21  *
  22  */
  23 
  24 #include "precompiled.hpp"
  25 #include "gc/shared/barrierSet.hpp"
  26 #include "gc/shenandoah/shenandoahForwarding.hpp"
  27 #include "gc/shenandoah/shenandoahHeap.hpp"
  28 #include "gc/shenandoah/shenandoahHeuristics.hpp"
  29 #include "gc/shenandoah/shenandoahRuntime.hpp"
  30 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
  31 #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"
  32 #include "gc/shenandoah/c2/shenandoahSupport.hpp"
  33 #include "opto/arraycopynode.hpp"
  34 #include "opto/escape.hpp"
  35 #include "opto/graphKit.hpp"
  36 #include "opto/idealKit.hpp"
  37 #include "opto/macro.hpp"
  38 #include "opto/movenode.hpp"
  39 #include "opto/narrowptrnode.hpp"
  40 #include "opto/rootnode.hpp"
  41 #include "opto/runtime.hpp"
  42 
  43 ShenandoahBarrierSetC2* ShenandoahBarrierSetC2::bsc2() {
  44   return reinterpret_cast<ShenandoahBarrierSetC2*>(BarrierSet::barrier_set()->barrier_set_c2());
  45 }
  46 
  47 ShenandoahBarrierSetC2State::ShenandoahBarrierSetC2State(Arena* comp_arena)
  48   : _enqueue_barriers(new (comp_arena) GrowableArray<ShenandoahEnqueueBarrierNode*>(comp_arena, 8,  0, NULL)),
  49     _load_reference_barriers(new (comp_arena) GrowableArray<ShenandoahLoadReferenceBarrierNode*>(comp_arena, 8,  0, NULL)) {
  50 }
  51 
  52 int ShenandoahBarrierSetC2State::enqueue_barriers_count() const {
  53   return _enqueue_barriers->length();
  54 }
  55 
  56 ShenandoahEnqueueBarrierNode* ShenandoahBarrierSetC2State::enqueue_barrier(int idx) const {
  57   return _enqueue_barriers->at(idx);
  58 }
  59 
  60 void ShenandoahBarrierSetC2State::add_enqueue_barrier(ShenandoahEnqueueBarrierNode * n) {
  61   assert(!_enqueue_barriers->contains(n), "duplicate entry in barrier list");


 445   // Final sync IdealKit and GraphKit.
 446   kit->final_sync(ideal);
 447 }
 448 
 449 #undef __
 450 
 451 const TypeFunc* ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type() {
 452   const Type **fields = TypeTuple::fields(2);
 453   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value
 454   fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // thread
 455   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields);
 456 
 457   // create result type (range)
 458   fields = TypeTuple::fields(0);
 459   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
 460 
 461   return TypeFunc::make(domain, range);
 462 }
 463 
 464 const TypeFunc* ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type() {
 465   const Type **fields = TypeTuple::fields(1);
 466   fields[TypeFunc::Parms+0] = TypeOopPtr::NOTNULL; // src oop
 467   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields);


 468 
 469   // create result type (range)
 470   fields = TypeTuple::fields(0);
 471   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
 472 
 473   return TypeFunc::make(domain, range);
 474 }
 475 
 476 const TypeFunc* ShenandoahBarrierSetC2::shenandoah_load_reference_barrier_Type() {
 477   const Type **fields = TypeTuple::fields(2);
 478   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value
 479   fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM;   // original load address
 480 
 481   const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields);
 482 
 483   // create result type (range)
 484   fields = TypeTuple::fields(1);
 485   fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL;
 486   const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields);
 487 


 778         return true;
 779       } else {
 780         if (!src_type->klass_is_exact()) {
 781           Compile::current()->dependencies()->assert_leaf_type(ik);
 782         }
 783       }
 784     } else {
 785       return true;
 786         }
 787   } else if (src_type->isa_aryptr()) {
 788     BasicType src_elem  = src_type->klass()->as_array_klass()->element_type()->basic_type();
 789     if (src_elem == T_OBJECT || src_elem == T_ARRAY) {
 790       return true;
 791     }
 792   } else {
 793     return true;
 794   }
 795   return false;
 796 }
 797 


 798 void ShenandoahBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const {
 799   Node* ctrl = ac->in(TypeFunc::Control);
 800   Node* mem = ac->in(TypeFunc::Memory);
 801   Node* src = ac->in(ArrayCopyNode::Src);
 802   Node* src_offset = ac->in(ArrayCopyNode::SrcPos);
 803   Node* dest = ac->in(ArrayCopyNode::Dest);
 804   Node* dest_offset = ac->in(ArrayCopyNode::DestPos);
 805   Node* length = ac->in(ArrayCopyNode::Length);
 806   assert (src_offset == NULL && dest_offset == NULL, "for clone offsets should be null");
 807   assert (src->is_AddP(), "for clone the src should be the interior ptr");
 808   assert (dest->is_AddP(), "for clone the dst should be the interior ptr");
 809 
 810   if (ShenandoahCloneBarrier && clone_needs_barrier(src, phase->igvn())) {
 811     // Check if heap is has forwarded objects. If it does, we need to call into the special
 812     // routine that would fix up source references before we can continue.
 813 
 814     enum { _heap_stable = 1, _heap_unstable, PATH_LIMIT };
 815     Node* region = new RegionNode(PATH_LIMIT);
 816     Node* mem_phi = new PhiNode(region, Type::MEMORY, TypeRawPtr::BOTTOM);
 817 
 818     Node* thread = phase->transform_later(new ThreadLocalNode());
 819     Node* offset = phase->igvn().MakeConX(in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
 820     Node* gc_state_addr = phase->transform_later(new AddPNode(phase->C->top(), thread, offset));
 821 
 822     uint gc_state_idx = Compile::AliasIdxRaw;
 823     const TypePtr* gc_state_adr_type = NULL; // debug-mode-only argument
 824     debug_only(gc_state_adr_type = phase->C->get_adr_type(gc_state_idx));
 825 
 826     Node* gc_state    = phase->transform_later(new LoadBNode(ctrl, mem, gc_state_addr, gc_state_adr_type, TypeInt::BYTE, MemNode::unordered));
 827     Node* stable_and  = phase->transform_later(new AndINode(gc_state, phase->igvn().intcon(ShenandoahHeap::HAS_FORWARDED)));
 828     Node* stable_cmp  = phase->transform_later(new CmpINode(stable_and, phase->igvn().zerocon(T_INT)));
 829     Node* stable_test = phase->transform_later(new BoolNode(stable_cmp, BoolTest::ne));
 830 
 831     IfNode* stable_iff  = phase->transform_later(new IfNode(ctrl, stable_test, PROB_UNLIKELY(0.999), COUNT_UNKNOWN))->as_If();
 832     Node* stable_ctrl   = phase->transform_later(new IfFalseNode(stable_iff));
 833     Node* unstable_ctrl = phase->transform_later(new IfTrueNode(stable_iff));
 834 
 835     // Heap is stable, no need to do anything additional
 836     region->init_req(_heap_stable, stable_ctrl);
 837     mem_phi->init_req(_heap_stable, mem);
 838 
 839     // Heap is unstable, call into clone barrier stub
 840     Node* call = phase->make_leaf_call(unstable_ctrl, mem,
 841                     ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type(),
 842                     CAST_FROM_FN_PTR(address, ShenandoahRuntime::shenandoah_clone_barrier),
 843                     "shenandoah_clone",
 844                     TypeRawPtr::BOTTOM,
 845                     src->in(AddPNode::Base));
 846     call = phase->transform_later(call);
 847 
 848     ctrl = phase->transform_later(new ProjNode(call, TypeFunc::Control));
 849     mem = phase->transform_later(new ProjNode(call, TypeFunc::Memory));
 850     region->init_req(_heap_unstable, ctrl);
 851     mem_phi->init_req(_heap_unstable, mem);
 852 
 853     // Wire up the actual arraycopy stub now
 854     ctrl = phase->transform_later(region);
 855     mem = phase->transform_later(mem_phi);
 856 
 857     const char* name = "arraycopy";
 858     call = phase->make_leaf_call(ctrl, mem,
 859                                  OptoRuntime::fast_arraycopy_Type(),
 860                                  phase->basictype2arraycopy(T_LONG, NULL, NULL, true, name, true),
 861                                  name, TypeRawPtr::BOTTOM,
 862                                  src, dest, length
 863                                  LP64_ONLY(COMMA phase->top()));
 864     call = phase->transform_later(call);
 865 
 866     // Hook up the whole thing into the graph
 867     phase->igvn().replace_node(ac, call);
 868   } else {
 869     BarrierSetC2::clone_at_expansion(phase, ac);
 870   }
 871 }
 872 
 873 
 874 // Support for macro expanded GC barriers
 875 void ShenandoahBarrierSetC2::register_potential_barrier_node(Node* node) const {
 876   if (node->Opcode() == Op_ShenandoahEnqueueBarrier) {
 877     state()->add_enqueue_barrier((ShenandoahEnqueueBarrierNode*) node);
 878   }
 879   if (node->Opcode() == Op_ShenandoahLoadReferenceBarrier) {
 880     state()->add_load_reference_barrier((ShenandoahLoadReferenceBarrierNode*) node);
 881   }
 882 }
 883 
 884 void ShenandoahBarrierSetC2::unregister_potential_barrier_node(Node* node) const {
 885   if (node->Opcode() == Op_ShenandoahEnqueueBarrier) {
 886     state()->remove_enqueue_barrier((ShenandoahEnqueueBarrierNode*) node);


< prev index next >