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);
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 }
1108
1109 // Check that we did not follow a loop back to ourselves
|
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);
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 (can_reshape &&
1063 n->Opcode() == Op_If &&
1064 ShenandoahBarrierC2Support::is_heap_stable_test(n) &&
1065 n->in(0) != NULL) {
1066 Node* dom = n->in(0);
1067 Node* prev_dom = n;
1068 int op = n->Opcode();
1069 int dist = 16;
1070 // Search up the dominator tree for another heap stable test
1071 while (dom->Opcode() != op || // Not same opcode?
1072 !ShenandoahBarrierC2Support::is_heap_stable_test(dom) || // Not same input 1?
1073 prev_dom->in(0) != dom) { // One path of test does not dominate?
1074 if (dist < 0) return NULL;
1075
1076 dist--;
1077 prev_dom = dom;
1078 dom = IfNode::up_one_dom(dom);
1079 if (!dom) return NULL;
1080 }
1081
1082 // Check that we did not follow a loop back to ourselves
|