src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp
changeset 59324 5e8f9713e343
parent 59025 b398685dd029
equal deleted inserted replaced
59323:ae2eb76c486d 59324:5e8f9713e343
    26 #include "gc/z/c2/zBarrierSetC2.hpp"
    26 #include "gc/z/c2/zBarrierSetC2.hpp"
    27 #include "gc/z/zBarrierSet.hpp"
    27 #include "gc/z/zBarrierSet.hpp"
    28 #include "gc/z/zBarrierSetAssembler.hpp"
    28 #include "gc/z/zBarrierSetAssembler.hpp"
    29 #include "gc/z/zBarrierSetRuntime.hpp"
    29 #include "gc/z/zBarrierSetRuntime.hpp"
    30 #include "opto/arraycopynode.hpp"
    30 #include "opto/arraycopynode.hpp"
       
    31 #include "opto/addnode.hpp"
    31 #include "opto/block.hpp"
    32 #include "opto/block.hpp"
    32 #include "opto/compile.hpp"
    33 #include "opto/compile.hpp"
    33 #include "opto/graphKit.hpp"
    34 #include "opto/graphKit.hpp"
    34 #include "opto/machnode.hpp"
    35 #include "opto/machnode.hpp"
    35 #include "opto/macro.hpp"
    36 #include "opto/macro.hpp"
   213 bool ZBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type,
   214 bool ZBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type,
   214                                                     bool is_clone, ArrayCopyPhase phase) const {
   215                                                     bool is_clone, ArrayCopyPhase phase) const {
   215   return type == T_OBJECT || type == T_ARRAY;
   216   return type == T_OBJECT || type == T_ARRAY;
   216 }
   217 }
   217 
   218 
       
   219 // This TypeFunc assumes a 64bit system
   218 static const TypeFunc* clone_type() {
   220 static const TypeFunc* clone_type() {
   219   // Create input type (domain)
   221   // Create input type (domain)
   220   const Type** domain_fields = TypeTuple::fields(3);
   222   const Type** domain_fields = TypeTuple::fields(4);
   221   domain_fields[TypeFunc::Parms + 0] = TypeInstPtr::NOTNULL;  // src
   223   domain_fields[TypeFunc::Parms + 0] = TypeInstPtr::NOTNULL;  // src
   222   domain_fields[TypeFunc::Parms + 1] = TypeInstPtr::NOTNULL;  // dst
   224   domain_fields[TypeFunc::Parms + 1] = TypeInstPtr::NOTNULL;  // dst
   223   domain_fields[TypeFunc::Parms + 2] = TypeInt::INT;          // size
   225   domain_fields[TypeFunc::Parms + 2] = TypeLong::LONG;        // size lower
   224   const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + 3, domain_fields);
   226   domain_fields[TypeFunc::Parms + 3] = Type::HALF;            // size upper
       
   227   const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms + 4, domain_fields);
   225 
   228 
   226   // Create result type (range)
   229   // Create result type (range)
   227   const Type** range_fields = TypeTuple::fields(0);
   230   const Type** range_fields = TypeTuple::fields(0);
   228   const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 0, range_fields);
   231   const TypeTuple* range = TypeTuple::make(TypeFunc::Parms + 0, range_fields);
   229 
   232 
   230   return TypeFunc::make(domain, range);
   233   return TypeFunc::make(domain, range);
   231 }
   234 }
   232 
   235 
       
   236 // Node n is pointing to the start of oop payload - return base pointer
       
   237 static Node* get_base_for_arracycopy_clone(PhaseMacroExpand* phase, Node* n) {
       
   238   // This would normally be handled by optimizations, but the type system
       
   239   // checks get confused when it thinks it already has a base pointer.
       
   240   const int base_offset = BarrierSetC2::arraycopy_payload_base_offset(false);
       
   241 
       
   242   if (n->is_AddP() &&
       
   243       n->in(AddPNode::Offset)->is_Con() &&
       
   244       n->in(AddPNode::Offset)->get_long() == base_offset) {
       
   245     assert(n->in(AddPNode::Base) == n->in(AddPNode::Address), "Sanity check");
       
   246     return n->in(AddPNode::Base);
       
   247   } else {
       
   248     return phase->basic_plus_adr(n, phase->longcon(-base_offset));
       
   249   }
       
   250 }
       
   251 
   233 void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const {
   252 void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const {
   234   Node* const src = ac->in(ArrayCopyNode::Src);
   253   Node* const src = ac->in(ArrayCopyNode::Src);
   235 
   254   if (ac->is_clone_array()) {
   236   if (src->bottom_type()->isa_aryptr()) {
       
   237     // Clone primitive array
   255     // Clone primitive array
   238     BarrierSetC2::clone_at_expansion(phase, ac);
   256     BarrierSetC2::clone_at_expansion(phase, ac);
   239     return;
   257     return;
   240   }
   258   }
   241 
   259 
   242   // Clone instance
   260   // Clone instance
   243   Node* const ctrl = ac->in(TypeFunc::Control);
   261   assert(ac->is_clone_inst(), "Sanity check");
   244   Node* const mem = ac->in(TypeFunc::Memory);
   262 
   245   Node* const dst = ac->in(ArrayCopyNode::Dest);
   263   Node* const ctrl       = ac->in(TypeFunc::Control);
       
   264   Node* const mem        = ac->in(TypeFunc::Memory);
       
   265   Node* const dst        = ac->in(ArrayCopyNode::Dest);
   246   Node* const src_offset = ac->in(ArrayCopyNode::SrcPos);
   266   Node* const src_offset = ac->in(ArrayCopyNode::SrcPos);
   247   Node* const dst_offset = ac->in(ArrayCopyNode::DestPos);
   267   Node* const dst_offset = ac->in(ArrayCopyNode::DestPos);
   248   Node* const size = ac->in(ArrayCopyNode::Length);
   268   Node* const size       = ac->in(ArrayCopyNode::Length);
   249 
   269 
   250   assert(src->bottom_type()->isa_instptr(), "Should be an instance");
       
   251   assert(dst->bottom_type()->isa_instptr(), "Should be an instance");
       
   252   assert(src_offset == NULL, "Should be null");
   270   assert(src_offset == NULL, "Should be null");
   253   assert(dst_offset == NULL, "Should be null");
   271   assert(dst_offset == NULL, "Should be null");
       
   272   assert(size->bottom_type()->is_long(), "Should be long");
       
   273 
       
   274   // The src and dst point to the object payload rather than the object base
       
   275   Node* const src_base = get_base_for_arracycopy_clone(phase, src);
       
   276   Node* const dst_base = get_base_for_arracycopy_clone(phase, dst);
       
   277 
       
   278   // The size must also be increased to match the instance size
       
   279   Node* const base_offset = phase->longcon(arraycopy_payload_base_offset(false) >> LogBytesPerLong);
       
   280   Node* const full_size = phase->transform_later(new AddLNode(size, base_offset));
   254 
   281 
   255   Node* const call = phase->make_leaf_call(ctrl,
   282   Node* const call = phase->make_leaf_call(ctrl,
   256                                            mem,
   283                                            mem,
   257                                            clone_type(),
   284                                            clone_type(),
   258                                            ZBarrierSetRuntime::clone_addr(),
   285                                            ZBarrierSetRuntime::clone_addr(),
   259                                            "ZBarrierSetRuntime::clone",
   286                                            "ZBarrierSetRuntime::clone",
   260                                            TypeRawPtr::BOTTOM,
   287                                            TypeRawPtr::BOTTOM,
   261                                            src,
   288                                            src_base,
   262                                            dst,
   289                                            dst_base,
   263                                            size);
   290                                            full_size,
       
   291                                            phase->top());
   264   phase->transform_later(call);
   292   phase->transform_later(call);
   265   phase->igvn().replace_node(ac, call);
   293   phase->igvn().replace_node(ac, call);
   266 }
   294 }
   267 
   295 
   268 // == Dominating barrier elision ==
   296 // == Dominating barrier elision ==
   340 
   368 
   341     for (uint j = 0; j < mem_ops.size(); j++) {
   369     for (uint j = 0; j < mem_ops.size(); j++) {
   342       MachNode* mem = mem_ops.at(j)->as_Mach();
   370       MachNode* mem = mem_ops.at(j)->as_Mach();
   343       const TypePtr* mem_adr_type = NULL;
   371       const TypePtr* mem_adr_type = NULL;
   344       intptr_t mem_offset = 0;
   372       intptr_t mem_offset = 0;
   345       const Node* mem_obj = mem_obj = mem->get_base_and_disp(mem_offset, mem_adr_type);
   373       const Node* mem_obj = mem->get_base_and_disp(mem_offset, mem_adr_type);
   346       Block* mem_block = cfg->get_block_for_node(mem);
   374       Block* mem_block = cfg->get_block_for_node(mem);
   347       uint mem_index = block_index(mem_block, mem);
   375       uint mem_index = block_index(mem_block, mem);
   348 
   376 
   349       if (load_obj == NodeSentinel || mem_obj == NodeSentinel ||
   377       if (load_obj == NodeSentinel || mem_obj == NodeSentinel ||
   350           load_obj == NULL || mem_obj == NULL ||
   378           load_obj == NULL || mem_obj == NULL ||