2174 LIRItem off(x->offset(), this); |
2174 LIRItem off(x->offset(), this); |
2175 |
2175 |
2176 off.load_item(); |
2176 off.load_item(); |
2177 src.load_item(); |
2177 src.load_item(); |
2178 |
2178 |
2179 LIR_Opr reg = rlock_result(x, x->basic_type()); |
2179 LIR_Opr value = rlock_result(x, x->basic_type()); |
2180 |
2180 |
2181 get_Object_unsafe(reg, src.result(), off.result(), type, x->is_volatile()); |
2181 get_Object_unsafe(value, src.result(), off.result(), type, x->is_volatile()); |
2182 |
2182 |
2183 #ifndef SERIALGC |
2183 #ifndef SERIALGC |
2184 // We might be reading the value of the referent field of a |
2184 // We might be reading the value of the referent field of a |
2185 // Reference object in order to attach it back to the live |
2185 // Reference object in order to attach it back to the live |
2186 // object graph. If G1 is enabled then we need to record |
2186 // object graph. If G1 is enabled then we need to record |
2189 // We need to generate code similar to the following... |
2189 // We need to generate code similar to the following... |
2190 // |
2190 // |
2191 // if (offset == java_lang_ref_Reference::referent_offset) { |
2191 // if (offset == java_lang_ref_Reference::referent_offset) { |
2192 // if (src != NULL) { |
2192 // if (src != NULL) { |
2193 // if (klass(src)->reference_type() != REF_NONE) { |
2193 // if (klass(src)->reference_type() != REF_NONE) { |
2194 // pre_barrier(..., reg, ...); |
2194 // pre_barrier(..., value, ...); |
2195 // } |
2195 // } |
2196 // } |
2196 // } |
2197 // } |
2197 // } |
2198 // |
|
2199 // The first non-constant check of either the offset or |
|
2200 // the src operand will be done here; the remainder |
|
2201 // will take place in the generated code stub. |
|
2202 |
2198 |
2203 if (UseG1GC && type == T_OBJECT) { |
2199 if (UseG1GC && type == T_OBJECT) { |
2204 bool gen_code_stub = true; // Assume we need to generate the slow code stub. |
2200 bool gen_pre_barrier = true; // Assume we need to generate pre_barrier. |
2205 bool gen_offset_check = true; // Assume the code stub has to generate the offset guard. |
2201 bool gen_offset_check = true; // Assume we need to generate the offset guard. |
2206 bool gen_source_check = true; // Assume the code stub has to check the src object for null. |
2202 bool gen_source_check = true; // Assume we need to check the src object for null. |
|
2203 bool gen_type_check = true; // Assume we need to check the reference_type. |
2207 |
2204 |
2208 if (off.is_constant()) { |
2205 if (off.is_constant()) { |
2209 jlong off_con = (off.type()->is_int() ? |
2206 jlong off_con = (off.type()->is_int() ? |
2210 (jlong) off.get_jint_constant() : |
2207 (jlong) off.get_jint_constant() : |
2211 off.get_jlong_constant()); |
2208 off.get_jlong_constant()); |
2213 |
2210 |
2214 if (off_con != (jlong) java_lang_ref_Reference::referent_offset) { |
2211 if (off_con != (jlong) java_lang_ref_Reference::referent_offset) { |
2215 // The constant offset is something other than referent_offset. |
2212 // The constant offset is something other than referent_offset. |
2216 // We can skip generating/checking the remaining guards and |
2213 // We can skip generating/checking the remaining guards and |
2217 // skip generation of the code stub. |
2214 // skip generation of the code stub. |
2218 gen_code_stub = false; |
2215 gen_pre_barrier = false; |
2219 } else { |
2216 } else { |
2220 // The constant offset is the same as referent_offset - |
2217 // The constant offset is the same as referent_offset - |
2221 // we do not need to generate a runtime offset check. |
2218 // we do not need to generate a runtime offset check. |
2222 gen_offset_check = false; |
2219 gen_offset_check = false; |
2223 } |
2220 } |
2224 } |
2221 } |
2225 |
2222 |
2226 // We don't need to generate stub if the source object is an array |
2223 // We don't need to generate stub if the source object is an array |
2227 if (gen_code_stub && src.type()->is_array()) { |
2224 if (gen_pre_barrier && src.type()->is_array()) { |
2228 gen_code_stub = false; |
2225 gen_pre_barrier = false; |
2229 } |
2226 } |
2230 |
2227 |
2231 if (gen_code_stub) { |
2228 if (gen_pre_barrier) { |
2232 // We still need to continue with the checks. |
2229 // We still need to continue with the checks. |
2233 if (src.is_constant()) { |
2230 if (src.is_constant()) { |
2234 ciObject* src_con = src.get_jobject_constant(); |
2231 ciObject* src_con = src.get_jobject_constant(); |
2235 |
2232 |
2236 if (src_con->is_null_object()) { |
2233 if (src_con->is_null_object()) { |
2237 // The constant src object is null - We can skip |
2234 // The constant src object is null - We can skip |
2238 // generating the code stub. |
2235 // generating the code stub. |
2239 gen_code_stub = false; |
2236 gen_pre_barrier = false; |
2240 } else { |
2237 } else { |
2241 // Non-null constant source object. We still have to generate |
2238 // Non-null constant source object. We still have to generate |
2242 // the slow stub - but we don't need to generate the runtime |
2239 // the slow stub - but we don't need to generate the runtime |
2243 // null object check. |
2240 // null object check. |
2244 gen_source_check = false; |
2241 gen_source_check = false; |
2245 } |
2242 } |
2246 } |
2243 } |
2247 } |
2244 } |
2248 |
2245 if (gen_pre_barrier && !PatchALot) { |
2249 if (gen_code_stub) { |
2246 // Can the klass of object be statically determined to be |
2250 // Temoraries. |
2247 // a sub-class of Reference? |
2251 LIR_Opr src_klass = new_register(T_OBJECT); |
2248 ciType* type = src.value()->declared_type(); |
2252 |
2249 if ((type != NULL) && type->is_loaded()) { |
2253 // Get the thread pointer for the pre-barrier |
2250 if (type->is_subtype_of(compilation()->env()->Reference_klass())) { |
2254 LIR_Opr thread = getThreadPointer(); |
2251 gen_type_check = false; |
2255 |
2252 } else if (type->is_klass() && |
2256 CodeStub* stub; |
2253 !compilation()->env()->Object_klass()->is_subtype_of(type->as_klass())) { |
|
2254 // Not Reference and not Object klass. |
|
2255 gen_pre_barrier = false; |
|
2256 } |
|
2257 } |
|
2258 } |
|
2259 |
|
2260 if (gen_pre_barrier) { |
|
2261 LabelObj* Lcont = new LabelObj(); |
2257 |
2262 |
2258 // We can have generate one runtime check here. Let's start with |
2263 // We can have generate one runtime check here. Let's start with |
2259 // the offset check. |
2264 // the offset check. |
2260 if (gen_offset_check) { |
2265 if (gen_offset_check) { |
2261 // if (offset == referent_offset) -> slow code stub |
2266 // if (offset != referent_offset) -> continue |
2262 // If offset is an int then we can do the comparison with the |
2267 // If offset is an int then we can do the comparison with the |
2263 // referent_offset constant; otherwise we need to move |
2268 // referent_offset constant; otherwise we need to move |
2264 // referent_offset into a temporary register and generate |
2269 // referent_offset into a temporary register and generate |
2265 // a reg-reg compare. |
2270 // a reg-reg compare. |
2266 |
2271 |
2271 } else { |
2276 } else { |
2272 assert(off.type()->is_long(), "what else?"); |
2277 assert(off.type()->is_long(), "what else?"); |
2273 referent_off = new_register(T_LONG); |
2278 referent_off = new_register(T_LONG); |
2274 __ move(LIR_OprFact::longConst(java_lang_ref_Reference::referent_offset), referent_off); |
2279 __ move(LIR_OprFact::longConst(java_lang_ref_Reference::referent_offset), referent_off); |
2275 } |
2280 } |
2276 |
2281 __ cmp(lir_cond_notEqual, off.result(), referent_off); |
2277 __ cmp(lir_cond_equal, off.result(), referent_off); |
2282 __ branch(lir_cond_notEqual, as_BasicType(off.type()), Lcont->label()); |
2278 |
2283 } |
2279 // Optionally generate "src == null" check. |
2284 if (gen_source_check) { |
2280 stub = new G1UnsafeGetObjSATBBarrierStub(reg, src.result(), |
2285 // offset is a const and equals referent offset |
2281 src_klass, thread, |
2286 // if (source == null) -> continue |
2282 gen_source_check); |
2287 __ cmp(lir_cond_equal, src.result(), LIR_OprFact::oopConst(NULL)); |
2283 |
2288 __ branch(lir_cond_equal, T_OBJECT, Lcont->label()); |
2284 __ branch(lir_cond_equal, as_BasicType(off.type()), stub); |
2289 } |
2285 } else { |
2290 LIR_Opr src_klass = new_register(T_OBJECT); |
2286 if (gen_source_check) { |
2291 if (gen_type_check) { |
2287 // offset is a const and equals referent offset |
2292 // We have determined that offset == referent_offset && src != null. |
2288 // if (source != null) -> slow code stub |
2293 // if (src->_klass->_reference_type == REF_NONE) -> continue |
2289 __ cmp(lir_cond_notEqual, src.result(), LIR_OprFact::oopConst(NULL)); |
2294 __ move(new LIR_Address(src.result(), oopDesc::klass_offset_in_bytes(), T_OBJECT), src_klass); |
2290 |
2295 LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(instanceKlass::reference_type_offset()), T_BYTE); |
2291 // Since we are generating the "if src == null" guard here, |
2296 LIR_Opr reference_type = new_register(T_INT); |
2292 // there is no need to generate the "src == null" check again. |
2297 __ move(reference_type_addr, reference_type); |
2293 stub = new G1UnsafeGetObjSATBBarrierStub(reg, src.result(), |
2298 __ cmp(lir_cond_equal, reference_type, LIR_OprFact::intConst(REF_NONE)); |
2294 src_klass, thread, |
2299 __ branch(lir_cond_equal, T_INT, Lcont->label()); |
2295 false); |
2300 } |
2296 |
2301 { |
2297 __ branch(lir_cond_notEqual, T_OBJECT, stub); |
2302 // We have determined that src->_klass->_reference_type != REF_NONE |
2298 } else { |
2303 // so register the value in the referent field with the pre-barrier. |
2299 // We have statically determined that offset == referent_offset |
2304 pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */, |
2300 // && src != null so we unconditionally branch to code stub |
2305 value /* pre_val */, |
2301 // to perform the guards and record reg in the SATB log buffer. |
2306 false /* do_load */, |
2302 |
2307 false /* patch */, |
2303 stub = new G1UnsafeGetObjSATBBarrierStub(reg, src.result(), |
2308 NULL /* info */); |
2304 src_klass, thread, |
2309 } |
2305 false); |
2310 __ branch_destination(Lcont->label()); |
2306 |
|
2307 __ branch(lir_cond_always, T_ILLEGAL, stub); |
|
2308 } |
|
2309 } |
|
2310 |
|
2311 // Continuation point |
|
2312 __ branch_destination(stub->continuation()); |
|
2313 } |
2311 } |
2314 } |
2312 } |
2315 #endif // SERIALGC |
2313 #endif // SERIALGC |
2316 |
2314 |
2317 if (x->is_volatile() && os::is_MP()) __ membar_acquire(); |
2315 if (x->is_volatile() && os::is_MP()) __ membar_acquire(); |