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 |
1034 skipped++; |
1032 skipped++; |
1035 continue; |
1033 continue; |
1036 } |
1034 } |
1037 expand_loadbarrier_node(¯o, n); |
1035 expand_loadbarrier_node(¯o, 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(¯o, n); |
1046 expand_loadbarrier_node(¯o, 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); |
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 } |