464
465 // create result type (range)
466 fields = TypeTuple::fields(0);
467 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
468
469 return TypeFunc::make(domain, range);
470 }
471
472 const TypeFunc* ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type() {
473 const Type **fields = TypeTuple::fields(1);
474 fields[TypeFunc::Parms+0] = TypeOopPtr::NOTNULL; // src oop
475 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields);
476
477 // create result type (range)
478 fields = TypeTuple::fields(0);
479 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
480
481 return TypeFunc::make(domain, range);
482 }
483
484 const TypeFunc* ShenandoahBarrierSetC2::shenandoah_load_reference_barrier_Type(const Type* value_type) {
485 const Type **fields = TypeTuple::fields(2);
486 fields[TypeFunc::Parms+0] = value_type; // original field value
487 fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // original load address
488
489 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields);
490
491 // create result type (range)
492 fields = TypeTuple::fields(1);
493 fields[TypeFunc::Parms+0] = value_type;
494 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields);
495
496 return TypeFunc::make(domain, range);
497 }
498
499 Node* ShenandoahBarrierSetC2::store_at_resolved(C2Access& access, C2AccessValue& val) const {
500 DecoratorSet decorators = access.decorators();
501
502 const TypePtr* adr_type = access.addr().type();
503 Node* adr = access.addr().node();
504
505 bool anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
506 bool on_heap = (decorators & IN_HEAP) != 0;
507
508 if (!access.is_oop() || (!on_heap && !anonymous)) {
509 return BarrierSetC2::store_at_resolved(access, val);
510 }
511
512 if (access.is_parse_access()) {
513 C2ParseAccess& parse_access = static_cast<C2ParseAccess&>(access);
1028 Node *load_ctrl = load->in(0);
1029
1030 if (if_ctrl != load_ctrl) {
1031 // Skip possible CProj->NeverBranch in infinite loops
1032 if ((if_ctrl->is_Proj() && if_ctrl->Opcode() == Op_CProj)
1033 && (if_ctrl->in(0)->is_MultiBranch() && if_ctrl->in(0)->Opcode() == Op_NeverBranch)) {
1034 if_ctrl = if_ctrl->in(0)->in(0);
1035 }
1036 }
1037 assert(load_ctrl != NULL && if_ctrl == load_ctrl, "controls must match");
1038 }
1039 }
1040 }
1041 }
1042 }
1043 }
1044 }
1045 }
1046 #endif
1047
1048 bool ShenandoahBarrierSetC2::maybe_skip_barrier(Node* n, uint i, PhaseGVN* phase) const {
1049 PhaseIterGVN* igvn = phase->is_IterGVN();
1050 Node* in = step_over_gc_barrier(n->in(i));
1051 if (in != n->in(i)) {
1052 if (igvn != NULL) {
1053 n->set_req_X(i, in, igvn);
1054 } else {
1055 n->set_req(i, in);
1056 }
1057 return true;
1058 }
1059 return false;
1060 }
1061
1062 Node* ShenandoahBarrierSetC2::ideal_node(PhaseGVN* phase, Node* n, bool can_reshape) const {
1063 if (is_shenandoah_wb_pre_call(n)) {
1064 uint cnt = ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type()->domain()->cnt();
1065 if (n->req() > cnt) {
1066 Node* addp = n->in(cnt);
1067 if (has_only_shenandoah_wb_pre_uses(addp)) {
1068 n->del_req(cnt);
1069 if (can_reshape) {
1070 phase->is_IterGVN()->_worklist.push(addp);
1071 }
1072 return n;
1073 }
1074 }
1075 }
1076 if (n->Opcode() == Op_CmpP) {
1077 Node* in1 = n->in(1);
1078 Node* in2 = n->in(2);
1079 if (in1->bottom_type() == TypePtr::NULL_PTR) {
1080 in2 = step_over_gc_barrier(in2);
1081 }
1082 if (in2->bottom_type() == TypePtr::NULL_PTR) {
1083 in1 = step_over_gc_barrier(in1);
1084 }
1085 PhaseIterGVN* igvn = phase->is_IterGVN();
1086 if (in1 != n->in(1)) {
1087 if (igvn != NULL) {
1088 n->set_req_X(1, in1, igvn);
1089 } else {
1090 n->set_req(1, in1);
1091 }
1092 assert(in2 == n->in(2), "only one change");
1093 return n;
1094 }
1095 if (in2 != n->in(2)) {
1096 if (igvn != NULL) {
1097 n->set_req_X(2, in2, igvn);
1098 } else {
1099 n->set_req(2, in2);
1100 }
1101 return n;
1102 }
1103 } else if (n->Opcode() == Op_CallStaticJava) {
1104 if (n->as_CallStaticJava()->uncommon_trap_request() != 0) {
1105 // Uncommon traps don't need barriers, values are handled
1106 // during deoptimization. It also affects optimizing null-checks
1107 // into implicit null-checks.
1108 PhaseIterGVN* igvn = phase->is_IterGVN();
1109 Node* ret = NULL;
1110 for (uint i = TypeFunc::Parms; i < n->len(); i++) {
1111 if (maybe_skip_barrier(n, i, phase)) {
1112 ret = n;
1113 }
1114 }
1115 return ret;
1116 }
1117 } else if (can_reshape &&
1118 n->Opcode() == Op_If &&
1119 ShenandoahBarrierC2Support::is_heap_stable_test(n) &&
1120 n->in(0) != NULL) {
1121 Node* dom = n->in(0);
1122 Node* prev_dom = n;
1123 int op = n->Opcode();
1124 int dist = 16;
1125 // Search up the dominator tree for another heap stable test
1126 while (dom->Opcode() != op || // Not same opcode?
1127 !ShenandoahBarrierC2Support::is_heap_stable_test(dom) || // Not same input 1?
1128 prev_dom->in(0) != dom) { // One path of test does not dominate?
1129 if (dist < 0) return NULL;
1130
1131 dist--;
1132 prev_dom = dom;
1133 dom = IfNode::up_one_dom(dom);
1134 if (!dom) return NULL;
1135 }
|
464
465 // create result type (range)
466 fields = TypeTuple::fields(0);
467 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
468
469 return TypeFunc::make(domain, range);
470 }
471
472 const TypeFunc* ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type() {
473 const Type **fields = TypeTuple::fields(1);
474 fields[TypeFunc::Parms+0] = TypeOopPtr::NOTNULL; // src oop
475 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields);
476
477 // create result type (range)
478 fields = TypeTuple::fields(0);
479 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
480
481 return TypeFunc::make(domain, range);
482 }
483
484 const TypeFunc* ShenandoahBarrierSetC2::shenandoah_load_reference_barrier_Type() {
485 const Type **fields = TypeTuple::fields(2);
486 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value
487 fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // original load address
488
489 const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+2, fields);
490
491 // create result type (range)
492 fields = TypeTuple::fields(1);
493 fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL;
494 const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+1, fields);
495
496 return TypeFunc::make(domain, range);
497 }
498
499 Node* ShenandoahBarrierSetC2::store_at_resolved(C2Access& access, C2AccessValue& val) const {
500 DecoratorSet decorators = access.decorators();
501
502 const TypePtr* adr_type = access.addr().type();
503 Node* adr = access.addr().node();
504
505 bool anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
506 bool on_heap = (decorators & IN_HEAP) != 0;
507
508 if (!access.is_oop() || (!on_heap && !anonymous)) {
509 return BarrierSetC2::store_at_resolved(access, val);
510 }
511
512 if (access.is_parse_access()) {
513 C2ParseAccess& parse_access = static_cast<C2ParseAccess&>(access);
1028 Node *load_ctrl = load->in(0);
1029
1030 if (if_ctrl != load_ctrl) {
1031 // Skip possible CProj->NeverBranch in infinite loops
1032 if ((if_ctrl->is_Proj() && if_ctrl->Opcode() == Op_CProj)
1033 && (if_ctrl->in(0)->is_MultiBranch() && if_ctrl->in(0)->Opcode() == Op_NeverBranch)) {
1034 if_ctrl = if_ctrl->in(0)->in(0);
1035 }
1036 }
1037 assert(load_ctrl != NULL && if_ctrl == load_ctrl, "controls must match");
1038 }
1039 }
1040 }
1041 }
1042 }
1043 }
1044 }
1045 }
1046 #endif
1047
1048 Node* ShenandoahBarrierSetC2::ideal_node(PhaseGVN* phase, Node* n, bool can_reshape) const {
1049 if (is_shenandoah_wb_pre_call(n)) {
1050 uint cnt = ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type()->domain()->cnt();
1051 if (n->req() > cnt) {
1052 Node* addp = n->in(cnt);
1053 if (has_only_shenandoah_wb_pre_uses(addp)) {
1054 n->del_req(cnt);
1055 if (can_reshape) {
1056 phase->is_IterGVN()->_worklist.push(addp);
1057 }
1058 return n;
1059 }
1060 }
1061 }
1062 if (n->Opcode() == Op_CmpP) {
1063 Node* in1 = n->in(1);
1064 Node* in2 = n->in(2);
1065 if (in1->bottom_type() == TypePtr::NULL_PTR) {
1066 in2 = step_over_gc_barrier(in2);
1067 }
1068 if (in2->bottom_type() == TypePtr::NULL_PTR) {
1069 in1 = step_over_gc_barrier(in1);
1070 }
1071 PhaseIterGVN* igvn = phase->is_IterGVN();
1072 if (in1 != n->in(1)) {
1073 if (igvn != NULL) {
1074 n->set_req_X(1, in1, igvn);
1075 } else {
1076 n->set_req(1, in1);
1077 }
1078 assert(in2 == n->in(2), "only one change");
1079 return n;
1080 }
1081 if (in2 != n->in(2)) {
1082 if (igvn != NULL) {
1083 n->set_req_X(2, in2, igvn);
1084 } else {
1085 n->set_req(2, in2);
1086 }
1087 return n;
1088 }
1089 } else if (can_reshape &&
1090 n->Opcode() == Op_If &&
1091 ShenandoahBarrierC2Support::is_heap_stable_test(n) &&
1092 n->in(0) != NULL) {
1093 Node* dom = n->in(0);
1094 Node* prev_dom = n;
1095 int op = n->Opcode();
1096 int dist = 16;
1097 // Search up the dominator tree for another heap stable test
1098 while (dom->Opcode() != op || // Not same opcode?
1099 !ShenandoahBarrierC2Support::is_heap_stable_test(dom) || // Not same input 1?
1100 prev_dom->in(0) != dom) { // One path of test does not dominate?
1101 if (dist < 0) return NULL;
1102
1103 dist--;
1104 prev_dom = dom;
1105 dom = IfNode::up_one_dom(dom);
1106 if (!dom) return NULL;
1107 }
|