2205 if (log2_scale != 0) {
2206 // temporary fix (platform dependent code without shift on Intel would be better)
2207 // TODO: ARM also allows embedded shift in the address
2208 __ shift_left(index_op, log2_scale, index_op);
2209 }
2210
2211 LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type());
2212 #endif // !GENERATE_ADDRESS_IS_PREFERRED
2213 __ move(value.result(), addr);
2214 }
2215
2216
2217 void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) {
2218 BasicType type = x->basic_type();
2219 LIRItem src(x->object(), this);
2220 LIRItem off(x->offset(), this);
2221
2222 off.load_item();
2223 src.load_item();
2224
2225 LIR_Opr value = rlock_result(x, x->basic_type());
2226
2227 get_Object_unsafe(value, src.result(), off.result(), type, x->is_volatile());
2228
2229 #if INCLUDE_ALL_GCS
2230 // We might be reading the value of the referent field of a
2231 // Reference object in order to attach it back to the live
2232 // object graph. If G1 is enabled then we need to record
2233 // the value that is being returned in an SATB log buffer.
2234 //
2235 // We need to generate code similar to the following...
2236 //
2237 // if (offset == java_lang_ref_Reference::referent_offset) {
2238 // if (src != NULL) {
2239 // if (klass(src)->reference_type() != REF_NONE) {
2240 // pre_barrier(..., value, ...);
2241 // }
2242 // }
2243 // }
2244
2245 if (UseG1GC && type == T_OBJECT) {
2246 bool gen_pre_barrier = true; // Assume we need to generate pre_barrier.
2247 bool gen_offset_check = true; // Assume we need to generate the offset guard.
2248 bool gen_source_check = true; // Assume we need to check the src object for null.
2249 bool gen_type_check = true; // Assume we need to check the reference_type.
2250
2251 if (off.is_constant()) {
2252 jlong off_con = (off.type()->is_int() ?
2253 (jlong) off.get_jint_constant() :
2254 off.get_jlong_constant());
2255
2256
2257 if (off_con != (jlong) java_lang_ref_Reference::referent_offset) {
2258 // The constant offset is something other than referent_offset.
2259 // We can skip generating/checking the remaining guards and
2260 // skip generation of the code stub.
2261 gen_pre_barrier = false;
2262 } else {
2263 // The constant offset is the same as referent_offset -
2264 // we do not need to generate a runtime offset check.
2265 gen_offset_check = false;
2266 }
2267 }
2268
2269 // We don't need to generate stub if the source object is an array
2270 if (gen_pre_barrier && src.type()->is_array()) {
2271 gen_pre_barrier = false;
2308 LabelObj* Lcont = new LabelObj();
2309
2310 // We can have generate one runtime check here. Let's start with
2311 // the offset check.
2312 if (gen_offset_check) {
2313 // if (offset != referent_offset) -> continue
2314 // If offset is an int then we can do the comparison with the
2315 // referent_offset constant; otherwise we need to move
2316 // referent_offset into a temporary register and generate
2317 // a reg-reg compare.
2318
2319 LIR_Opr referent_off;
2320
2321 if (off.type()->is_int()) {
2322 referent_off = LIR_OprFact::intConst(java_lang_ref_Reference::referent_offset);
2323 } else {
2324 assert(off.type()->is_long(), "what else?");
2325 referent_off = new_register(T_LONG);
2326 __ move(LIR_OprFact::longConst(java_lang_ref_Reference::referent_offset), referent_off);
2327 }
2328 __ cmp(lir_cond_notEqual, off.result(), referent_off);
2329 __ branch(lir_cond_notEqual, as_BasicType(off.type()), Lcont->label());
2330 }
2331 if (gen_source_check) {
2332 // offset is a const and equals referent offset
2333 // if (source == null) -> continue
2334 __ cmp(lir_cond_equal, src.result(), LIR_OprFact::oopConst(NULL));
2335 __ branch(lir_cond_equal, T_OBJECT, Lcont->label());
2336 }
2337 LIR_Opr src_klass = new_register(T_OBJECT);
2338 if (gen_type_check) {
2339 // We have determined that offset == referent_offset && src != null.
2340 // if (src->_klass->_reference_type == REF_NONE) -> continue
2341 __ move(new LIR_Address(src.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), src_klass);
2342 LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(InstanceKlass::reference_type_offset()), T_BYTE);
2343 LIR_Opr reference_type = new_register(T_INT);
2344 __ move(reference_type_addr, reference_type);
2345 __ cmp(lir_cond_equal, reference_type, LIR_OprFact::intConst(REF_NONE));
2346 __ branch(lir_cond_equal, T_INT, Lcont->label());
2347 }
2348 {
2359 }
2360 #endif // INCLUDE_ALL_GCS
2361
2362 if (x->is_volatile() && os::is_MP()) __ membar_acquire();
2363 }
2364
2365
2366 void LIRGenerator::do_UnsafePutObject(UnsafePutObject* x) {
2367 BasicType type = x->basic_type();
2368 LIRItem src(x->object(), this);
2369 LIRItem off(x->offset(), this);
2370 LIRItem data(x->value(), this);
2371
2372 src.load_item();
2373 if (type == T_BOOLEAN || type == T_BYTE) {
2374 data.load_byte_item();
2375 } else {
2376 data.load_item();
2377 }
2378 off.load_item();
2379
2380 set_no_result(x);
2381
2382 if (x->is_volatile() && os::is_MP()) __ membar_release();
2383 put_Object_unsafe(src.result(), off.result(), data.result(), type, x->is_volatile());
2384 if (x->is_volatile() && os::is_MP()) __ membar();
2385 }
2386
2387
2388 void LIRGenerator::do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux) {
2389 int lng = x->length();
2390
2391 for (int i = 0; i < lng; i++) {
2392 SwitchRange* one_range = x->at(i);
2393 int low_key = one_range->low_key();
2394 int high_key = one_range->high_key();
2395 BlockBegin* dest = one_range->sux();
2396 if (low_key == high_key) {
2397 __ cmp(lir_cond_equal, value, low_key);
2398 __ branch(lir_cond_equal, T_INT, dest);
2399 } else if (high_key - low_key == 1) {
2400 __ cmp(lir_cond_equal, value, low_key);
2401 __ branch(lir_cond_equal, T_INT, dest);
2402 __ cmp(lir_cond_equal, value, high_key);
2403 __ branch(lir_cond_equal, T_INT, dest);
|
2205 if (log2_scale != 0) {
2206 // temporary fix (platform dependent code without shift on Intel would be better)
2207 // TODO: ARM also allows embedded shift in the address
2208 __ shift_left(index_op, log2_scale, index_op);
2209 }
2210
2211 LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type());
2212 #endif // !GENERATE_ADDRESS_IS_PREFERRED
2213 __ move(value.result(), addr);
2214 }
2215
2216
2217 void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) {
2218 BasicType type = x->basic_type();
2219 LIRItem src(x->object(), this);
2220 LIRItem off(x->offset(), this);
2221
2222 off.load_item();
2223 src.load_item();
2224
2225 LIR_Opr offset = unpack_offset(src.result(), off.result());
2226 LIR_Opr value = rlock_result(x, x->basic_type());
2227
2228 get_Object_unsafe(value, src.result(), offset, type, x->is_volatile());
2229
2230 #if INCLUDE_ALL_GCS
2231 // We might be reading the value of the referent field of a
2232 // Reference object in order to attach it back to the live
2233 // object graph. If G1 is enabled then we need to record
2234 // the value that is being returned in an SATB log buffer.
2235 //
2236 // We need to generate code similar to the following...
2237 //
2238 // if (offset == java_lang_ref_Reference::referent_offset) {
2239 // if (src != NULL) {
2240 // if (klass(src)->reference_type() != REF_NONE) {
2241 // pre_barrier(..., value, ...);
2242 // }
2243 // }
2244 // }
2245
2246 if (UseG1GC && type == T_OBJECT) {
2247 bool gen_pre_barrier = true; // Assume we need to generate pre_barrier.
2248 bool gen_offset_check = true; // Assume we need to generate the offset guard.
2249 bool gen_source_check = true; // Assume we need to check the src object for null.
2250 bool gen_type_check = true; // Assume we need to check the reference_type.
2251
2252 if (false /*off.is_constant()*/) {
2253 jlong off_con = (off.type()->is_int() ?
2254 (jlong) off.get_jint_constant() :
2255 off.get_jlong_constant());
2256
2257
2258 if (off_con != (jlong) java_lang_ref_Reference::referent_offset) {
2259 // The constant offset is something other than referent_offset.
2260 // We can skip generating/checking the remaining guards and
2261 // skip generation of the code stub.
2262 gen_pre_barrier = false;
2263 } else {
2264 // The constant offset is the same as referent_offset -
2265 // we do not need to generate a runtime offset check.
2266 gen_offset_check = false;
2267 }
2268 }
2269
2270 // We don't need to generate stub if the source object is an array
2271 if (gen_pre_barrier && src.type()->is_array()) {
2272 gen_pre_barrier = false;
2309 LabelObj* Lcont = new LabelObj();
2310
2311 // We can have generate one runtime check here. Let's start with
2312 // the offset check.
2313 if (gen_offset_check) {
2314 // if (offset != referent_offset) -> continue
2315 // If offset is an int then we can do the comparison with the
2316 // referent_offset constant; otherwise we need to move
2317 // referent_offset into a temporary register and generate
2318 // a reg-reg compare.
2319
2320 LIR_Opr referent_off;
2321
2322 if (off.type()->is_int()) {
2323 referent_off = LIR_OprFact::intConst(java_lang_ref_Reference::referent_offset);
2324 } else {
2325 assert(off.type()->is_long(), "what else?");
2326 referent_off = new_register(T_LONG);
2327 __ move(LIR_OprFact::longConst(java_lang_ref_Reference::referent_offset), referent_off);
2328 }
2329 __ cmp(lir_cond_notEqual, offset, referent_off);
2330 __ branch(lir_cond_notEqual, as_BasicType(off.type()), Lcont->label());
2331 }
2332 if (gen_source_check) {
2333 // offset is a const and equals referent offset
2334 // if (source == null) -> continue
2335 __ cmp(lir_cond_equal, src.result(), LIR_OprFact::oopConst(NULL));
2336 __ branch(lir_cond_equal, T_OBJECT, Lcont->label());
2337 }
2338 LIR_Opr src_klass = new_register(T_OBJECT);
2339 if (gen_type_check) {
2340 // We have determined that offset == referent_offset && src != null.
2341 // if (src->_klass->_reference_type == REF_NONE) -> continue
2342 __ move(new LIR_Address(src.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), src_klass);
2343 LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(InstanceKlass::reference_type_offset()), T_BYTE);
2344 LIR_Opr reference_type = new_register(T_INT);
2345 __ move(reference_type_addr, reference_type);
2346 __ cmp(lir_cond_equal, reference_type, LIR_OprFact::intConst(REF_NONE));
2347 __ branch(lir_cond_equal, T_INT, Lcont->label());
2348 }
2349 {
2360 }
2361 #endif // INCLUDE_ALL_GCS
2362
2363 if (x->is_volatile() && os::is_MP()) __ membar_acquire();
2364 }
2365
2366
2367 void LIRGenerator::do_UnsafePutObject(UnsafePutObject* x) {
2368 BasicType type = x->basic_type();
2369 LIRItem src(x->object(), this);
2370 LIRItem off(x->offset(), this);
2371 LIRItem data(x->value(), this);
2372
2373 src.load_item();
2374 if (type == T_BOOLEAN || type == T_BYTE) {
2375 data.load_byte_item();
2376 } else {
2377 data.load_item();
2378 }
2379 off.load_item();
2380 LIR_Opr offset = unpack_offset(src.result(), off.result());
2381 set_no_result(x);
2382
2383 if (x->is_volatile() && os::is_MP()) __ membar_release();
2384 put_Object_unsafe(src.result(), offset, data.result(), type, x->is_volatile());
2385 if (x->is_volatile() && os::is_MP()) __ membar();
2386 }
2387
2388
2389 void LIRGenerator::do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux) {
2390 int lng = x->length();
2391
2392 for (int i = 0; i < lng; i++) {
2393 SwitchRange* one_range = x->at(i);
2394 int low_key = one_range->low_key();
2395 int high_key = one_range->high_key();
2396 BlockBegin* dest = one_range->sux();
2397 if (low_key == high_key) {
2398 __ cmp(lir_cond_equal, value, low_key);
2399 __ branch(lir_cond_equal, T_INT, dest);
2400 } else if (high_key - low_key == 1) {
2401 __ cmp(lir_cond_equal, value, low_key);
2402 __ branch(lir_cond_equal, T_INT, dest);
2403 __ cmp(lir_cond_equal, value, high_key);
2404 __ branch(lir_cond_equal, T_INT, dest);
|