1.1 --- a/src/share/vm/c1/c1_LIRGenerator.cpp Mon Aug 20 09:07:21 2012 -0700 1.2 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Mon Aug 20 09:58:58 2012 -0700 1.3 @@ -2176,9 +2176,9 @@ 1.4 off.load_item(); 1.5 src.load_item(); 1.6 1.7 - LIR_Opr reg = rlock_result(x, x->basic_type()); 1.8 - 1.9 - get_Object_unsafe(reg, src.result(), off.result(), type, x->is_volatile()); 1.10 + LIR_Opr value = rlock_result(x, x->basic_type()); 1.11 + 1.12 + get_Object_unsafe(value, src.result(), off.result(), type, x->is_volatile()); 1.13 1.14 #ifndef SERIALGC 1.15 // We might be reading the value of the referent field of a 1.16 @@ -2191,19 +2191,16 @@ 1.17 // if (offset == java_lang_ref_Reference::referent_offset) { 1.18 // if (src != NULL) { 1.19 // if (klass(src)->reference_type() != REF_NONE) { 1.20 - // pre_barrier(..., reg, ...); 1.21 + // pre_barrier(..., value, ...); 1.22 // } 1.23 // } 1.24 // } 1.25 - // 1.26 - // The first non-constant check of either the offset or 1.27 - // the src operand will be done here; the remainder 1.28 - // will take place in the generated code stub. 1.29 1.30 if (UseG1GC && type == T_OBJECT) { 1.31 - bool gen_code_stub = true; // Assume we need to generate the slow code stub. 1.32 - bool gen_offset_check = true; // Assume the code stub has to generate the offset guard. 1.33 - bool gen_source_check = true; // Assume the code stub has to check the src object for null. 1.34 + bool gen_pre_barrier = true; // Assume we need to generate pre_barrier. 1.35 + bool gen_offset_check = true; // Assume we need to generate the offset guard. 1.36 + bool gen_source_check = true; // Assume we need to check the src object for null. 1.37 + bool gen_type_check = true; // Assume we need to check the reference_type. 1.38 1.39 if (off.is_constant()) { 1.40 jlong off_con = (off.type()->is_int() ? 1.41 @@ -2215,7 +2212,7 @@ 1.42 // The constant offset is something other than referent_offset. 1.43 // We can skip generating/checking the remaining guards and 1.44 // skip generation of the code stub. 1.45 - gen_code_stub = false; 1.46 + gen_pre_barrier = false; 1.47 } else { 1.48 // The constant offset is the same as referent_offset - 1.49 // we do not need to generate a runtime offset check. 1.50 @@ -2224,11 +2221,11 @@ 1.51 } 1.52 1.53 // We don't need to generate stub if the source object is an array 1.54 - if (gen_code_stub && src.type()->is_array()) { 1.55 - gen_code_stub = false; 1.56 + if (gen_pre_barrier && src.type()->is_array()) { 1.57 + gen_pre_barrier = false; 1.58 } 1.59 1.60 - if (gen_code_stub) { 1.61 + if (gen_pre_barrier) { 1.62 // We still need to continue with the checks. 1.63 if (src.is_constant()) { 1.64 ciObject* src_con = src.get_jobject_constant(); 1.65 @@ -2236,7 +2233,7 @@ 1.66 if (src_con->is_null_object()) { 1.67 // The constant src object is null - We can skip 1.68 // generating the code stub. 1.69 - gen_code_stub = false; 1.70 + gen_pre_barrier = false; 1.71 } else { 1.72 // Non-null constant source object. We still have to generate 1.73 // the slow stub - but we don't need to generate the runtime 1.74 @@ -2245,20 +2242,28 @@ 1.75 } 1.76 } 1.77 } 1.78 - 1.79 - if (gen_code_stub) { 1.80 - // Temoraries. 1.81 - LIR_Opr src_klass = new_register(T_OBJECT); 1.82 - 1.83 - // Get the thread pointer for the pre-barrier 1.84 - LIR_Opr thread = getThreadPointer(); 1.85 - 1.86 - CodeStub* stub; 1.87 + if (gen_pre_barrier && !PatchALot) { 1.88 + // Can the klass of object be statically determined to be 1.89 + // a sub-class of Reference? 1.90 + ciType* type = src.value()->declared_type(); 1.91 + if ((type != NULL) && type->is_loaded()) { 1.92 + if (type->is_subtype_of(compilation()->env()->Reference_klass())) { 1.93 + gen_type_check = false; 1.94 + } else if (type->is_klass() && 1.95 + !compilation()->env()->Object_klass()->is_subtype_of(type->as_klass())) { 1.96 + // Not Reference and not Object klass. 1.97 + gen_pre_barrier = false; 1.98 + } 1.99 + } 1.100 + } 1.101 + 1.102 + if (gen_pre_barrier) { 1.103 + LabelObj* Lcont = new LabelObj(); 1.104 1.105 // We can have generate one runtime check here. Let's start with 1.106 // the offset check. 1.107 if (gen_offset_check) { 1.108 - // if (offset == referent_offset) -> slow code stub 1.109 + // if (offset != referent_offset) -> continue 1.110 // If offset is an int then we can do the comparison with the 1.111 // referent_offset constant; otherwise we need to move 1.112 // referent_offset into a temporary register and generate 1.113 @@ -2273,43 +2278,36 @@ 1.114 referent_off = new_register(T_LONG); 1.115 __ move(LIR_OprFact::longConst(java_lang_ref_Reference::referent_offset), referent_off); 1.116 } 1.117 - 1.118 - __ cmp(lir_cond_equal, off.result(), referent_off); 1.119 - 1.120 - // Optionally generate "src == null" check. 1.121 - stub = new G1UnsafeGetObjSATBBarrierStub(reg, src.result(), 1.122 - src_klass, thread, 1.123 - gen_source_check); 1.124 - 1.125 - __ branch(lir_cond_equal, as_BasicType(off.type()), stub); 1.126 - } else { 1.127 - if (gen_source_check) { 1.128 - // offset is a const and equals referent offset 1.129 - // if (source != null) -> slow code stub 1.130 - __ cmp(lir_cond_notEqual, src.result(), LIR_OprFact::oopConst(NULL)); 1.131 - 1.132 - // Since we are generating the "if src == null" guard here, 1.133 - // there is no need to generate the "src == null" check again. 1.134 - stub = new G1UnsafeGetObjSATBBarrierStub(reg, src.result(), 1.135 - src_klass, thread, 1.136 - false); 1.137 - 1.138 - __ branch(lir_cond_notEqual, T_OBJECT, stub); 1.139 - } else { 1.140 - // We have statically determined that offset == referent_offset 1.141 - // && src != null so we unconditionally branch to code stub 1.142 - // to perform the guards and record reg in the SATB log buffer. 1.143 - 1.144 - stub = new G1UnsafeGetObjSATBBarrierStub(reg, src.result(), 1.145 - src_klass, thread, 1.146 - false); 1.147 - 1.148 - __ branch(lir_cond_always, T_ILLEGAL, stub); 1.149 - } 1.150 + __ cmp(lir_cond_notEqual, off.result(), referent_off); 1.151 + __ branch(lir_cond_notEqual, as_BasicType(off.type()), Lcont->label()); 1.152 } 1.153 - 1.154 - // Continuation point 1.155 - __ branch_destination(stub->continuation()); 1.156 + if (gen_source_check) { 1.157 + // offset is a const and equals referent offset 1.158 + // if (source == null) -> continue 1.159 + __ cmp(lir_cond_equal, src.result(), LIR_OprFact::oopConst(NULL)); 1.160 + __ branch(lir_cond_equal, T_OBJECT, Lcont->label()); 1.161 + } 1.162 + LIR_Opr src_klass = new_register(T_OBJECT); 1.163 + if (gen_type_check) { 1.164 + // We have determined that offset == referent_offset && src != null. 1.165 + // if (src->_klass->_reference_type == REF_NONE) -> continue 1.166 + __ move(new LIR_Address(src.result(), oopDesc::klass_offset_in_bytes(), T_OBJECT), src_klass); 1.167 + LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(instanceKlass::reference_type_offset()), T_BYTE); 1.168 + LIR_Opr reference_type = new_register(T_INT); 1.169 + __ move(reference_type_addr, reference_type); 1.170 + __ cmp(lir_cond_equal, reference_type, LIR_OprFact::intConst(REF_NONE)); 1.171 + __ branch(lir_cond_equal, T_INT, Lcont->label()); 1.172 + } 1.173 + { 1.174 + // We have determined that src->_klass->_reference_type != REF_NONE 1.175 + // so register the value in the referent field with the pre-barrier. 1.176 + pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */, 1.177 + value /* pre_val */, 1.178 + false /* do_load */, 1.179 + false /* patch */, 1.180 + NULL /* info */); 1.181 + } 1.182 + __ branch_destination(Lcont->label()); 1.183 } 1.184 } 1.185 #endif // SERIALGC