hotspot/src/share/vm/c1/c1_LIRGenerator.cpp
changeset 13486 4f0635e148c1
parent 13391 30245956af37
child 13487 75aa4880b15f
equal deleted inserted replaced
13485:6c7faa516fc6 13486:4f0635e148c1
  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();