src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp
changeset 53439 4b42f828e0c3
parent 53438 9a88ffdc2f43
child 53766 7e4a9e912759
equal deleted inserted replaced
53438:9a88ffdc2f43 53439:4b42f828e0c3
    35 #include "gc/z/zBarrierSet.hpp"
    35 #include "gc/z/zBarrierSet.hpp"
    36 #include "gc/z/c2/zBarrierSetC2.hpp"
    36 #include "gc/z/c2/zBarrierSetC2.hpp"
    37 #include "gc/z/zThreadLocalData.hpp"
    37 #include "gc/z/zThreadLocalData.hpp"
    38 #include "gc/z/zBarrierSetRuntime.hpp"
    38 #include "gc/z/zBarrierSetRuntime.hpp"
    39 
    39 
    40 ZBarrierSetC2State::ZBarrierSetC2State(Arena* comp_arena)
    40 ZBarrierSetC2State::ZBarrierSetC2State(Arena* comp_arena) :
    41   : _load_barrier_nodes(new (comp_arena) GrowableArray<LoadBarrierNode*>(comp_arena, 8,  0, NULL)) {}
    41     _load_barrier_nodes(new (comp_arena) GrowableArray<LoadBarrierNode*>(comp_arena, 8,  0, NULL)) {}
    42 
    42 
    43 int ZBarrierSetC2State::load_barrier_count() const {
    43 int ZBarrierSetC2State::load_barrier_count() const {
    44   return _load_barrier_nodes->length();
    44   return _load_barrier_nodes->length();
    45 }
    45 }
    46 
    46 
   121   }
   121   }
   122 }
   122 }
   123 
   123 
   124 void ZBarrierSetC2::find_dominating_barriers(PhaseIterGVN& igvn) {
   124 void ZBarrierSetC2::find_dominating_barriers(PhaseIterGVN& igvn) {
   125   // Look for dominating barriers on the same address only once all
   125   // Look for dominating barriers on the same address only once all
   126   // other loop opts are over: loop opts may cause a safepoint to be
   126   // other loop opts are over. Loop opts may cause a safepoint to be
   127   // inserted between a barrier and its dominating barrier.
   127   // inserted between a barrier and its dominating barrier.
   128   Compile* C = Compile::current();
   128   Compile* C = Compile::current();
   129   ZBarrierSetC2* bs = (ZBarrierSetC2*)BarrierSet::barrier_set()->barrier_set_c2();
   129   ZBarrierSetC2* bs = (ZBarrierSetC2*)BarrierSet::barrier_set()->barrier_set_c2();
   130   ZBarrierSetC2State* s = bs->state();
   130   ZBarrierSetC2State* s = bs->state();
   131   if (s->load_barrier_count() >= 2) {
   131   if (s->load_barrier_count() >= 2) {
  1008   traverse(preceding_barrier_node, result_region, result_phi, -1);
  1008   traverse(preceding_barrier_node, result_region, result_phi, -1);
  1009 #endif
  1009 #endif
  1010 
  1010 
  1011   assert(is_gc_barrier_node(result_phi), "sanity");
  1011   assert(is_gc_barrier_node(result_phi), "sanity");
  1012   assert(step_over_gc_barrier(result_phi) == in_val, "sanity");
  1012   assert(step_over_gc_barrier(result_phi) == in_val, "sanity");
  1013 
       
  1014   return;
       
  1015 }
  1013 }
  1016 
  1014 
  1017 bool ZBarrierSetC2::expand_barriers(Compile* C, PhaseIterGVN& igvn) const {
  1015 bool ZBarrierSetC2::expand_barriers(Compile* C, PhaseIterGVN& igvn) const {
  1018   ZBarrierSetC2State* s = state();
  1016   ZBarrierSetC2State* s = state();
  1019   if (s->load_barrier_count() > 0) {
  1017   if (s->load_barrier_count() > 0) {
  1034         skipped++;
  1032         skipped++;
  1035         continue;
  1033         continue;
  1036       }
  1034       }
  1037       expand_loadbarrier_node(&macro, n);
  1035       expand_loadbarrier_node(&macro, n);
  1038       assert(s->load_barrier_count() < load_barrier_count, "must have deleted a node from load barrier list");
  1036       assert(s->load_barrier_count() < load_barrier_count, "must have deleted a node from load barrier list");
  1039       if (C->failing())  return true;
  1037       if (C->failing()) {
       
  1038         return true;
       
  1039       }
  1040     }
  1040     }
  1041     while (s->load_barrier_count() > 0) {
  1041     while (s->load_barrier_count() > 0) {
  1042       int load_barrier_count = s->load_barrier_count();
  1042       int load_barrier_count = s->load_barrier_count();
  1043       LoadBarrierNode* n = s->load_barrier_node(load_barrier_count - 1);
  1043       LoadBarrierNode* n = s->load_barrier_node(load_barrier_count - 1);
  1044       assert(!(igvn.type(n) == Type::TOP || (n->in(0) != NULL && n->in(0)->is_top())), "should have been processed already");
  1044       assert(!(igvn.type(n) == Type::TOP || (n->in(0) != NULL && n->in(0)->is_top())), "should have been processed already");
  1045       assert(!n->can_be_eliminated(), "should have been processed already");
  1045       assert(!n->can_be_eliminated(), "should have been processed already");
  1046       expand_loadbarrier_node(&macro, n);
  1046       expand_loadbarrier_node(&macro, n);
  1047       assert(s->load_barrier_count() < load_barrier_count, "must have deleted a node from load barrier list");
  1047       assert(s->load_barrier_count() < load_barrier_count, "must have deleted a node from load barrier list");
  1048       if (C->failing())  return true;
  1048       if (C->failing()) {
       
  1049         return true;
       
  1050       }
  1049     }
  1051     }
  1050     igvn.set_delay_transform(false);
  1052     igvn.set_delay_transform(false);
  1051     igvn.optimize();
  1053     igvn.optimize();
  1052     if (C->failing())  return true;
  1054     if (C->failing()) {
  1053   }
  1055       return true;
       
  1056     }
       
  1057   }
       
  1058 
  1054   return false;
  1059   return false;
  1055 }
  1060 }
  1056 
  1061 
  1057 // == Loop optimization ==
  1062 // == Loop optimization ==
  1058 
  1063 
  1059 static bool replace_with_dominating_barrier(PhaseIdealLoop* phase, LoadBarrierNode* lb, bool last_round) {
  1064 static bool replace_with_dominating_barrier(PhaseIdealLoop* phase, LoadBarrierNode* lb, bool last_round) {
  1060   PhaseIterGVN &igvn = phase->igvn();
  1065   PhaseIterGVN &igvn = phase->igvn();
  1061   Compile* C = Compile::current();
  1066   Compile* C = Compile::current();
  1062 
  1067 
  1063   LoadBarrierNode* lb2 = lb->has_dominating_barrier(phase, false, last_round);
  1068   LoadBarrierNode* lb2 = lb->has_dominating_barrier(phase, false, last_round);
  1064   if (lb2 != NULL) {
  1069   if (lb2 == NULL) {
  1065     if (lb->in(LoadBarrierNode::Oop) != lb2->in(LoadBarrierNode::Oop)) {
  1070     return false;
  1066       assert(lb->in(LoadBarrierNode::Address) == lb2->in(LoadBarrierNode::Address), "");
  1071   }
  1067       igvn.replace_input_of(lb, LoadBarrierNode::Similar, lb2->proj_out(LoadBarrierNode::Oop));
  1072 
  1068       C->set_major_progress();
  1073   if (lb->in(LoadBarrierNode::Oop) != lb2->in(LoadBarrierNode::Oop)) {
  1069     } else  {
  1074     assert(lb->in(LoadBarrierNode::Address) == lb2->in(LoadBarrierNode::Address), "Invalid address");
  1070       // That transformation may cause the Similar edge on dominated load barriers to be invalid
  1075     igvn.replace_input_of(lb, LoadBarrierNode::Similar, lb2->proj_out(LoadBarrierNode::Oop));
  1071       lb->fix_similar_in_uses(&igvn);
  1076     C->set_major_progress();
  1072 
  1077     return false;
  1073       Node* val = lb->proj_out(LoadBarrierNode::Oop);
  1078   }
  1074       assert(lb2->has_true_uses(), "");
  1079 
  1075       assert(lb2->in(LoadBarrierNode::Oop) == lb->in(LoadBarrierNode::Oop), "");
  1080   // That transformation may cause the Similar edge on dominated load barriers to be invalid
  1076 
  1081   lb->fix_similar_in_uses(&igvn);
  1077       phase->lazy_update(lb, lb->in(LoadBarrierNode::Control));
  1082 
  1078       phase->lazy_replace(lb->proj_out(LoadBarrierNode::Control), lb->in(LoadBarrierNode::Control));
  1083   Node* val = lb->proj_out(LoadBarrierNode::Oop);
  1079       igvn.replace_node(val, lb2->proj_out(LoadBarrierNode::Oop));
  1084   assert(lb2->has_true_uses(), "Invalid uses");
  1080 
  1085   assert(lb2->in(LoadBarrierNode::Oop) == lb->in(LoadBarrierNode::Oop), "Invalid oop");
  1081       return true;
  1086   phase->lazy_update(lb, lb->in(LoadBarrierNode::Control));
  1082     }
  1087   phase->lazy_replace(lb->proj_out(LoadBarrierNode::Control), lb->in(LoadBarrierNode::Control));
  1083   }
  1088   igvn.replace_node(val, lb2->proj_out(LoadBarrierNode::Oop));
  1084   return false;
  1089 
       
  1090   return true;
  1085 }
  1091 }
  1086 
  1092 
  1087 static Node* find_dominating_memory(PhaseIdealLoop* phase, Node* mem, Node* dom, int i) {
  1093 static Node* find_dominating_memory(PhaseIdealLoop* phase, Node* mem, Node* dom, int i) {
  1088   assert(dom->is_Region() || i == -1, "");
  1094   assert(dom->is_Region() || i == -1, "");
       
  1095 
  1089   Node* m = mem;
  1096   Node* m = mem;
  1090   while(phase->is_dominator(dom, phase->has_ctrl(m) ? phase->get_ctrl(m) : m->in(0))) {
  1097   while(phase->is_dominator(dom, phase->has_ctrl(m) ? phase->get_ctrl(m) : m->in(0))) {
  1091     if (m->is_Mem()) {
  1098     if (m->is_Mem()) {
  1092       assert(m->as_Mem()->adr_type() == TypeRawPtr::BOTTOM, "");
  1099       assert(m->as_Mem()->adr_type() == TypeRawPtr::BOTTOM, "");
  1093       m = m->in(MemNode::Memory);
  1100       m = m->in(MemNode::Memory);
  1109       m->dump();
  1116       m->dump();
  1110 #endif
  1117 #endif
  1111       ShouldNotReachHere();
  1118       ShouldNotReachHere();
  1112     }
  1119     }
  1113   }
  1120   }
       
  1121 
  1114   return m;
  1122   return m;
  1115 }
  1123 }
  1116 
  1124 
  1117 static LoadBarrierNode* clone_load_barrier(PhaseIdealLoop* phase, LoadBarrierNode* lb, Node* ctl, Node* mem, Node* oop_in) {
  1125 static LoadBarrierNode* clone_load_barrier(PhaseIdealLoop* phase, LoadBarrierNode* lb, Node* ctl, Node* mem, Node* oop_in) {
  1118   PhaseIterGVN &igvn = phase->igvn();
  1126   PhaseIterGVN &igvn = phase->igvn();
  1388   }
  1396   }
  1389 
  1397 
  1390   return false;
  1398   return false;
  1391 }
  1399 }
  1392 
  1400 
  1393 static void optimize_load_barrier(PhaseIdealLoop* phase, LoadBarrierNode* lb, bool last_round) {
  1401 void ZBarrierSetC2::loop_optimize_gc_barrier(PhaseIdealLoop* phase, Node* node, bool last_round) {
  1394   Compile* C = Compile::current();
  1402   if (!Compile::current()->directive()->ZOptimizeLoadBarriersOption) {
  1395 
       
  1396   if (!C->directive()->ZOptimizeLoadBarriersOption) {
       
  1397     return;
  1403     return;
  1398   }
  1404   }
  1399 
  1405 
  1400   if (lb->has_true_uses()) {
  1406   if (!node->is_LoadBarrier()) {
  1401     if (replace_with_dominating_barrier(phase, lb, last_round)) {
  1407     return;
  1402       return;
  1408   }
  1403     }
  1409 
  1404 
  1410   if (!node->as_LoadBarrier()->has_true_uses()) {
  1405     if (split_barrier_thru_phi(phase, lb)) {
  1411     return;
  1406       return;
  1412   }
  1407     }
  1413 
  1408 
  1414   if (replace_with_dominating_barrier(phase, node->as_LoadBarrier(), last_round)) {
  1409     if (move_out_of_loop(phase, lb)) {
  1415     return;
  1410       return;
  1416   }
  1411     }
  1417 
  1412 
  1418   if (split_barrier_thru_phi(phase, node->as_LoadBarrier())) {
  1413     if (common_barriers(phase, lb)) {
  1419     return;
  1414       return;
  1420   }
  1415     }
  1421 
  1416   }
  1422   if (move_out_of_loop(phase, node->as_LoadBarrier())) {
  1417 }
  1423     return;
  1418 
  1424   }
  1419 void ZBarrierSetC2::loop_optimize_gc_barrier(PhaseIdealLoop* phase, Node* node, bool last_round) {
  1425 
  1420   if (node->is_LoadBarrier()) {
  1426   if (common_barriers(phase, node->as_LoadBarrier())) {
  1421     optimize_load_barrier(phase, node->as_LoadBarrier(), last_round);
  1427     return;
  1422   }
  1428   }
  1423 }
  1429 }
  1424 
  1430 
  1425 Node* ZBarrierSetC2::step_over_gc_barrier(Node* c) const {
  1431 Node* ZBarrierSetC2::step_over_gc_barrier(Node* c) const {
  1426   Node* node = c;
  1432   Node* node = c;
  1451 bool ZBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const {
  1457 bool ZBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const {
  1452   return type == T_OBJECT || type == T_ARRAY;
  1458   return type == T_OBJECT || type == T_ARRAY;
  1453 }
  1459 }
  1454 
  1460 
  1455 bool ZBarrierSetC2::final_graph_reshaping(Compile* compile, Node* n, uint opcode) const {
  1461 bool ZBarrierSetC2::final_graph_reshaping(Compile* compile, Node* n, uint opcode) const {
  1456   bool handled;
  1462   if (opcode != Op_LoadBarrierSlowReg &&
  1457   switch (opcode) {
  1463       opcode != Op_LoadBarrierWeakSlowReg) {
  1458     case Op_LoadBarrierSlowReg:
  1464     return false;
  1459     case Op_LoadBarrierWeakSlowReg:
  1465   }
       
  1466 
  1460 #ifdef ASSERT
  1467 #ifdef ASSERT
  1461       if (VerifyOptoOopOffsets) {
  1468   if (VerifyOptoOopOffsets) {
  1462         MemNode* mem  = n->as_Mem();
  1469     MemNode* mem  = n->as_Mem();
  1463         // Check to see if address types have grounded out somehow.
  1470     // Check to see if address types have grounded out somehow.
  1464         const TypeInstPtr* tp = mem->in(MemNode::Address)->bottom_type()->isa_instptr();
  1471     const TypeInstPtr* tp = mem->in(MemNode::Address)->bottom_type()->isa_instptr();
  1465         ciInstanceKlass* k = tp->klass()->as_instance_klass();
  1472     ciInstanceKlass* k = tp->klass()->as_instance_klass();
  1466         bool oop_offset_is_sane = k->contains_field_offset(tp->offset());
  1473     bool oop_offset_is_sane = k->contains_field_offset(tp->offset());
  1467         assert(!tp || oop_offset_is_sane, "");
  1474     assert(!tp || oop_offset_is_sane, "");
  1468       }
  1475   }
  1469 #endif
  1476 #endif
  1470       handled = true;
  1477 
  1471       break;
  1478   return true;
  1472     default:
       
  1473       handled = false;
       
  1474   }
       
  1475   return handled;
       
  1476 }
  1479 }
  1477 
  1480 
  1478 bool ZBarrierSetC2::matcher_find_shared_visit(Matcher* matcher, Matcher::MStack& mstack, Node* n, uint opcode, bool& mem_op, int& mem_addr_idx) const {
  1481 bool ZBarrierSetC2::matcher_find_shared_visit(Matcher* matcher, Matcher::MStack& mstack, Node* n, uint opcode, bool& mem_op, int& mem_addr_idx) const {
  1479   if (opcode == Op_CallLeaf &&
  1482   if (opcode == Op_CallLeaf &&
  1480       (n->as_Call()->entry_point() == ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr() ||
  1483       (n->as_Call()->entry_point() == ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr() ||
  1481        n->as_Call()->entry_point() == ZBarrierSetRuntime::load_barrier_on_weak_oop_field_preloaded_addr())) {
  1484        n->as_Call()->entry_point() == ZBarrierSetRuntime::load_barrier_on_weak_oop_field_preloaded_addr())) {
  1482     mem_op = true;
  1485     mem_op = true;
  1483     mem_addr_idx = TypeFunc::Parms + 1;
  1486     mem_addr_idx = TypeFunc::Parms + 1;
  1484     return true;
  1487     return true;
  1485   }
  1488   }
       
  1489 
  1486   return false;
  1490   return false;
  1487 }
  1491 }
  1488 
  1492 
  1489 // == Verification ==
  1493 // == Verification ==
  1490 
  1494 
  1604   switch (opcode) {
  1608   switch (opcode) {
  1605     case Op_LoadBarrierSlowReg:
  1609     case Op_LoadBarrierSlowReg:
  1606     case Op_LoadBarrierWeakSlowReg:
  1610     case Op_LoadBarrierWeakSlowReg:
  1607       conn_graph->add_objload_to_connection_graph(n, delayed_worklist);
  1611       conn_graph->add_objload_to_connection_graph(n, delayed_worklist);
  1608       return true;
  1612       return true;
       
  1613 
  1609     case Op_Proj:
  1614     case Op_Proj:
  1610       if (n->as_Proj()->_con == LoadBarrierNode::Oop && n->in(0)->is_LoadBarrier()) {
  1615       if (n->as_Proj()->_con != LoadBarrierNode::Oop || !n->in(0)->is_LoadBarrier()) {
  1611         conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(0)->in(LoadBarrierNode::Oop),
  1616         return false;
  1612                                            delayed_worklist);
  1617       }
  1613         return true;
  1618       conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(0)->in(LoadBarrierNode::Oop), delayed_worklist);
  1614       }
  1619       return true;
  1615     default:
  1620   }
  1616       break;
  1621 
  1617   }
       
  1618   return false;
  1622   return false;
  1619 }
  1623 }
  1620 
  1624 
  1621 bool ZBarrierSetC2::escape_add_final_edges(ConnectionGraph* conn_graph, PhaseGVN* gvn, Node* n, uint opcode) const {
  1625 bool ZBarrierSetC2::escape_add_final_edges(ConnectionGraph* conn_graph, PhaseGVN* gvn, Node* n, uint opcode) const {
  1622   switch (opcode) {
  1626   switch (opcode) {
  1623     case Op_LoadBarrierSlowReg:
  1627     case Op_LoadBarrierSlowReg:
  1624     case Op_LoadBarrierWeakSlowReg: {
  1628     case Op_LoadBarrierWeakSlowReg:
  1625       const Type *t = gvn->type(n);
  1629       if (gvn->type(n)->make_ptr() == NULL) {
  1626       if (t->make_ptr() != NULL) {
  1630         return false;
  1627         Node *adr = n->in(MemNode::Address);
  1631       }
  1628         conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL);
  1632       conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(MemNode::Address), NULL);
  1629         return true;
  1633       return true;
  1630       }
  1634 
  1631       break;
  1635     case Op_Proj:
  1632     }
  1636       if (n->as_Proj()->_con != LoadBarrierNode::Oop || !n->in(0)->is_LoadBarrier()) {
  1633     case Op_Proj: {
  1637         return false;
  1634       if (n->as_Proj()->_con == LoadBarrierNode::Oop && n->in(0)->is_LoadBarrier()) {
  1638       }
  1635         conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(0)->in(LoadBarrierNode::Oop), NULL);
  1639       conn_graph->add_local_var_and_edge(n, PointsToNode::NoEscape, n->in(0)->in(LoadBarrierNode::Oop), NULL);
  1636         return true;
  1640       return true;
  1637       }
  1641   }
  1638     }
  1642 
  1639     default:
       
  1640       break;
       
  1641   }
       
  1642   return false;
  1643   return false;
  1643 }
  1644 }