< prev index next > src/hotspot/share/c1/c1_LIRGenerator.cpp
BarrierSetC1
#include "ci/ciArrayKlass.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciObjArray.hpp"
#include "ci/ciUtilities.hpp"
#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableBarrierSet.hpp"
-#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/c1/cardTableBarrierSetC1.hpp"
+#include "gc/shared/c1/barrierSetC1.hpp"
+#include "gc/shared/c1/modRefBarrierSetC1.hpp"
#include "runtime/arguments.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/vm_version.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1ThreadLocalData.hpp"
-#include "gc/g1/heapRegion.hpp"
-#endif // INCLUDE_ALL_GCS
#ifdef TRACE_HAVE_INTRINSICS
#include "trace/traceMacros.hpp"
#endif
#ifdef ASSERT
//--------------------------------------------------------------
-void LIRGenerator::init() {
- _bs = BarrierSet::barrier_set();
-}
-
-
void LIRGenerator::block_do_prolog(BlockBegin* block) {
#ifndef PRODUCT
if (PrintIRWithLIR) {
block->print();
}
CodeEmitInfo* info = NULL;
if (x->needs_null_check()) {
info = state_for(x);
}
- LIR_Address* referent_field_adr =
- new LIR_Address(reference.result(), referent_offset, T_OBJECT);
-
- LIR_Opr result = rlock_result(x);
-
- __ load(referent_field_adr, result, info);
-
- // Register the value in the referent field with the pre-barrier
- pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */,
- result /* pre_val */,
- false /* do_load */,
- false /* patch */,
- NULL /* info */);
+ LIR_Opr result = rlock_result(x, T_OBJECT);
+ access_load_at(IN_HEAP | ON_WEAK_OOP_REF, T_OBJECT,
+ reference, LIR_OprFact::intConst(referent_offset), result,
+ NULL, NULL);
}
// Example: clazz.isInstance(object)
void LIRGenerator::do_isInstance(Intrinsic* x) {
assert(x->number_of_arguments() == 2, "wrong type");
_constants.append(c);
_reg_for_constants.append(result);
return result;
}
-// Various barriers
-
-void LIRGenerator::pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val,
- bool do_load, bool patch, CodeEmitInfo* info) {
- // Do the pre-write barrier, if any.
- switch (_bs->kind()) {
-#if INCLUDE_ALL_GCS
- case BarrierSet::G1BarrierSet:
- G1BarrierSet_pre_barrier(addr_opr, pre_val, do_load, patch, info);
- break;
-#endif // INCLUDE_ALL_GCS
- case BarrierSet::CardTableBarrierSet:
- // No pre barriers
- break;
- default :
- ShouldNotReachHere();
-
- }
-}
-
-void LIRGenerator::post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) {
- switch (_bs->kind()) {
-#if INCLUDE_ALL_GCS
- case BarrierSet::G1BarrierSet:
- G1BarrierSet_post_barrier(addr, new_val);
- break;
-#endif // INCLUDE_ALL_GCS
- case BarrierSet::CardTableBarrierSet:
- CardTableBarrierSet_post_barrier(addr, new_val);
- break;
- default :
- ShouldNotReachHere();
- }
-}
-
-////////////////////////////////////////////////////////////////////////
-#if INCLUDE_ALL_GCS
-
-void LIRGenerator::G1BarrierSet_pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val,
- bool do_load, bool patch, CodeEmitInfo* info) {
- // First we test whether marking is in progress.
- BasicType flag_type;
- if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
- flag_type = T_INT;
- } else {
- guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1,
- "Assumption");
- // Use unsigned type T_BOOLEAN here rather than signed T_BYTE since some platforms, eg. ARM,
- // need to use unsigned instructions to use the large offset to load the satb_mark_queue.
- flag_type = T_BOOLEAN;
- }
- LIR_Opr thrd = getThreadPointer();
- LIR_Address* mark_active_flag_addr =
- new LIR_Address(thrd, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), flag_type);
- // Read the marking-in-progress flag.
- LIR_Opr flag_val = new_register(T_INT);
- __ load(mark_active_flag_addr, flag_val);
- __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
-
- LIR_PatchCode pre_val_patch_code = lir_patch_none;
-
- CodeStub* slow;
-
- if (do_load) {
- assert(pre_val == LIR_OprFact::illegalOpr, "sanity");
- assert(addr_opr != LIR_OprFact::illegalOpr, "sanity");
-
- if (patch)
- pre_val_patch_code = lir_patch_normal;
-
- pre_val = new_register(T_OBJECT);
-
- if (!addr_opr->is_address()) {
- assert(addr_opr->is_register(), "must be");
- addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, T_OBJECT));
- }
- slow = new G1PreBarrierStub(addr_opr, pre_val, pre_val_patch_code, info);
- } else {
- assert(addr_opr == LIR_OprFact::illegalOpr, "sanity");
- assert(pre_val->is_register(), "must be");
- assert(pre_val->type() == T_OBJECT, "must be an object");
- assert(info == NULL, "sanity");
-
- slow = new G1PreBarrierStub(pre_val);
- }
-
- __ branch(lir_cond_notEqual, T_INT, slow);
- __ branch_destination(slow->continuation());
-}
-
-void LIRGenerator::G1BarrierSet_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) {
- // If the "new_val" is a constant NULL, no barrier is necessary.
- if (new_val->is_constant() &&
- new_val->as_constant_ptr()->as_jobject() == NULL) return;
-
- if (!new_val->is_register()) {
- LIR_Opr new_val_reg = new_register(T_OBJECT);
- if (new_val->is_constant()) {
- __ move(new_val, new_val_reg);
- } else {
- __ leal(new_val, new_val_reg);
- }
- new_val = new_val_reg;
- }
- assert(new_val->is_register(), "must be a register at this point");
-
- if (addr->is_address()) {
- LIR_Address* address = addr->as_address_ptr();
- LIR_Opr ptr = new_pointer_register();
- if (!address->index()->is_valid() && address->disp() == 0) {
- __ move(address->base(), ptr);
- } else {
- assert(address->disp() != max_jint, "lea doesn't support patched addresses!");
- __ leal(addr, ptr);
- }
- addr = ptr;
- }
- assert(addr->is_register(), "must be a register at this point");
-
- LIR_Opr xor_res = new_pointer_register();
- LIR_Opr xor_shift_res = new_pointer_register();
- if (TwoOperandLIRForm ) {
- __ move(addr, xor_res);
- __ logical_xor(xor_res, new_val, xor_res);
- __ move(xor_res, xor_shift_res);
- __ unsigned_shift_right(xor_shift_res,
- LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes),
- xor_shift_res,
- LIR_OprDesc::illegalOpr());
- } else {
- __ logical_xor(addr, new_val, xor_res);
- __ unsigned_shift_right(xor_res,
- LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes),
- xor_shift_res,
- LIR_OprDesc::illegalOpr());
- }
-
- if (!new_val->is_register()) {
- LIR_Opr new_val_reg = new_register(T_OBJECT);
- __ leal(new_val, new_val_reg);
- new_val = new_val_reg;
- }
- assert(new_val->is_register(), "must be a register at this point");
-
- __ cmp(lir_cond_notEqual, xor_shift_res, LIR_OprFact::intptrConst(NULL_WORD));
-
- CodeStub* slow = new G1PostBarrierStub(addr, new_val);
- __ branch(lir_cond_notEqual, LP64_ONLY(T_LONG) NOT_LP64(T_INT), slow);
- __ branch_destination(slow->continuation());
-}
-
-#endif // INCLUDE_ALL_GCS
-////////////////////////////////////////////////////////////////////////
-
-void LIRGenerator::CardTableBarrierSet_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) {
- LIR_Const* card_table_base = new LIR_Const(ci_card_table_address());
- if (addr->is_address()) {
- LIR_Address* address = addr->as_address_ptr();
- // ptr cannot be an object because we use this barrier for array card marks
- // and addr can point in the middle of an array.
- LIR_Opr ptr = new_pointer_register();
- if (!address->index()->is_valid() && address->disp() == 0) {
- __ move(address->base(), ptr);
- } else {
- assert(address->disp() != max_jint, "lea doesn't support patched addresses!");
- __ leal(addr, ptr);
- }
- addr = ptr;
- }
- assert(addr->is_register(), "must be a register at this point");
-
-#ifdef CARDTABLEBARRIERSET_POST_BARRIER_HELPER
- CardTableBarrierSet_post_barrier_helper(addr, card_table_base);
-#else
- LIR_Opr tmp = new_pointer_register();
- if (TwoOperandLIRForm) {
- __ move(addr, tmp);
- __ unsigned_shift_right(tmp, CardTable::card_shift, tmp);
- } else {
- __ unsigned_shift_right(addr, CardTable::card_shift, tmp);
- }
-
- LIR_Address* card_addr;
- if (can_inline_as_constant(card_table_base)) {
- card_addr = new LIR_Address(tmp, card_table_base->as_jint(), T_BYTE);
- } else {
- card_addr = new LIR_Address(tmp, load_constant(card_table_base), T_BYTE);
- }
-
- LIR_Opr dirty = LIR_OprFact::intConst(CardTable::dirty_card_val());
- if (UseCondCardMark) {
- LIR_Opr cur_value = new_register(T_INT);
- if (UseConcMarkSweepGC) {
- __ membar_storeload();
- }
- __ move(card_addr, cur_value);
+//------------------------field access--------------------------------------
- LabelObj* L_already_dirty = new LabelObj();
- __ cmp(lir_cond_equal, cur_value, dirty);
- __ branch(lir_cond_equal, T_BYTE, L_already_dirty->label());
- __ move(dirty, card_addr);
- __ branch_destination(L_already_dirty->label());
- } else {
-#if INCLUDE_ALL_GCS
- if (UseConcMarkSweepGC && CMSPrecleaningEnabled) {
- __ membar_storestore();
- }
-#endif
- __ move(dirty, card_addr);
- }
-#endif
+void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
+ assert(x->number_of_arguments() == 4, "wrong type");
+ LIRItem obj (x->argument_at(0), this); // object
+ LIRItem offset(x->argument_at(1), this); // offset of field
+ LIRItem cmp (x->argument_at(2), this); // value to compare with field
+ LIRItem val (x->argument_at(3), this); // replace field with val if matches cmp
+ assert(obj.type()->tag() == objectTag, "invalid type");
+
+ // In 64bit the type can be long, sparc doesn't have this assert
+ // assert(offset.type()->tag() == intTag, "invalid type");
+
+ assert(cmp.type()->tag() == type->tag(), "invalid type");
+ assert(val.type()->tag() == type->tag(), "invalid type");
+
+ DecoratorSet decorators = IN_HEAP | MO_SEQ_CST;
+ LIR_Opr result = access_atomic_cmpxchg_at(decorators, as_BasicType(type),
+ obj, offset, cmp, val);
+ set_result(x, result);
}
-
-//------------------------field access--------------------------------------
-
// Comment copied form templateTable_i486.cpp
// ----------------------------------------------------------------------------
// Volatile variables demand their effects be made known to all CPU's in
// order. Store buffers on most chips allow reads & writes to reorder; the
// JMM's ReadAfterWrite.java test fails in -Xint mode without some kind of
void LIRGenerator::do_StoreField(StoreField* x) {
bool needs_patching = x->needs_patching();
bool is_volatile = x->field()->is_volatile();
BasicType field_type = x->field_type();
- bool is_oop = (field_type == T_ARRAY || field_type == T_OBJECT);
CodeEmitInfo* info = NULL;
if (needs_patching) {
assert(x->explicit_null_check() == NULL, "can't fold null check into patching field access");
info = state_for(x, x->state_before());
} else {
info = state_for(nc);
}
}
-
LIRItem object(x->obj(), this);
LIRItem value(x->value(), this);
object.load_item();
// If the class is not loaded and the object is NULL, we need to deoptimize to throw a
// NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code.
__ null_check(object.result(), new CodeEmitInfo(info), /* deoptimize */ needs_patching);
}
- LIR_Address* address;
+ DecoratorSet decorators = IN_HEAP;
+ if (is_volatile) {
+ decorators |= MO_SEQ_CST;
+ }
if (needs_patching) {
- // we need to patch the offset in the instruction so don't allow
- // generate_address to try to be smart about emitting the -1.
- // Otherwise the patching code won't know how to find the
- // instruction to patch.
- address = new LIR_Address(object.result(), PATCHED_ADDR, field_type);
+ decorators |= C1_NEEDS_PATCHING;
+ }
+
+ access_store_at(decorators, field_type, object, LIR_OprFact::intConst(x->offset()), value.result(), info ? new CodeEmitInfo(info) : NULL, info);
+}
+
+void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
+ assert(x->is_pinned(),"");
+ bool needs_range_check = x->compute_needs_range_check();
+ bool use_length = x->length() != NULL;
+ bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
+ bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
+ !get_jobject_constant(x->value())->is_null_object() ||
+ x->should_profile());
+
+ LIRItem array(x->array(), this);
+ LIRItem index(x->index(), this);
+ LIRItem value(x->value(), this);
+ LIRItem length(this);
+
+ array.load_item();
+ index.load_nonconstant();
+
+ if (use_length && needs_range_check) {
+ length.set_instruction(x->length());
+ length.load_item();
+
+ }
+ if (needs_store_check || x->check_boolean()) {
+ value.load_item();
} else {
- address = generate_address(object.result(), x->offset(), field_type);
+ value.load_for_store(x->elt_type());
}
- if (is_volatile && os::is_MP()) {
- __ membar_release();
+ set_no_result(x);
+
+ // the CodeEmitInfo must be duplicated for each different
+ // LIR-instruction because spilling can occur anywhere between two
+ // instructions and so the debug information must be different
+ CodeEmitInfo* range_check_info = state_for(x);
+ CodeEmitInfo* null_check_info = NULL;
+ if (x->needs_null_check()) {
+ null_check_info = new CodeEmitInfo(range_check_info);
}
- if (is_oop) {
- // Do the pre-write barrier, if any.
- pre_barrier(LIR_OprFact::address(address),
- LIR_OprFact::illegalOpr /* pre_val */,
- true /* do_load*/,
- needs_patching,
- (info ? new CodeEmitInfo(info) : NULL));
+ if (GenerateRangeChecks && needs_range_check) {
+ if (use_length) {
+ __ cmp(lir_cond_belowEqual, length.result(), index.result());
+ __ branch(lir_cond_belowEqual, T_INT, new RangeCheckStub(range_check_info, index.result()));
+ } else {
+ array_range_check(array.result(), index.result(), null_check_info, range_check_info);
+ // range_check also does the null check
+ null_check_info = NULL;
+ }
}
- bool needs_atomic_access = is_volatile || AlwaysAtomicAccesses;
- if (needs_atomic_access && !needs_patching) {
- volatile_field_store(value.result(), address, info);
+ if (GenerateArrayStoreCheck && needs_store_check) {
+ CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info);
+ array_store_check(value.result(), array.result(), store_check_info, x->profiled_method(), x->profiled_bci());
+ }
+
+ DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+ if (x->check_boolean()) {
+ decorators |= C1_MASK_BOOLEAN;
+ }
+
+ access_store_at(decorators, x->elt_type(), array, index.result(), value.result(), NULL, null_check_info);
+}
+
+void LIRGenerator::access_load_at(DecoratorSet decorators, BasicType type,
+ LIRItem& base, LIR_Opr offset, LIR_Opr result,
+ CodeEmitInfo* patch_info, CodeEmitInfo* load_emit_info) {
+ BarrierSetC1 *bs = BarrierSet::barrier_set()->barrier_set_c1();
+ bool as_raw = (decorators & AS_RAW) != 0;
+ if (as_raw) {
+ bs->BarrierSetC1::load_at(this, decorators, type,
+ base, offset, result, patch_info, load_emit_info);
} else {
- LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none;
- __ store(value.result(), address, info, patch_code);
+ bs->load_at(this, decorators, type,
+ base, offset, result, patch_info, load_emit_info);
}
+}
- if (is_oop) {
- // Store to object so mark the card of the header
- post_barrier(object.result(), value.result());
+void LIRGenerator::access_store_at(DecoratorSet decorators, BasicType type,
+ LIRItem& base, LIR_Opr offset, LIR_Opr value,
+ CodeEmitInfo* patch_info, CodeEmitInfo* store_emit_info) {
+ BarrierSetC1 *bs = BarrierSet::barrier_set()->barrier_set_c1();
+ bool as_raw = (decorators & AS_RAW) != 0;
+ if (as_raw) {
+ bs->BarrierSetC1::store_at(this, decorators, type,
+ base, offset, value, patch_info, store_emit_info);
+ } else {
+ bs->store_at(this, decorators, type,
+ base, offset, value, patch_info, store_emit_info);
}
+}
- if (!support_IRIW_for_not_multiple_copy_atomic_cpu && is_volatile && os::is_MP()) {
- __ membar();
+LIR_Opr LIRGenerator::access_atomic_cmpxchg_at(DecoratorSet decorators, BasicType type,
+ LIRItem& base, LIRItem& offset, LIRItem& cmp_value, LIRItem& new_value) {
+ BarrierSetC1 *bs = BarrierSet::barrier_set()->barrier_set_c1();
+ bool as_raw = (decorators & AS_RAW) != 0;
+ if (as_raw) {
+ return bs->BarrierSetC1::atomic_cmpxchg_at(this, decorators, type,
+ base, offset, cmp_value, new_value);
+ } else {
+ return bs->atomic_cmpxchg_at(this, decorators, type,
+ base, offset, cmp_value, new_value);
}
}
+LIR_Opr LIRGenerator::access_atomic_xchg_at(DecoratorSet decorators, BasicType type,
+ LIRItem& base, LIRItem& offset, LIRItem& value) {
+ BarrierSetC1 *bs = BarrierSet::barrier_set()->barrier_set_c1();
+ bool as_raw = (decorators & AS_RAW) != 0;
+ if (as_raw) {
+ return bs->BarrierSetC1::atomic_xchg(this, decorators, type,
+ base, offset, value);
+ } else {
+ return bs->atomic_xchg(this, decorators, type,
+ base, offset, value);
+ }
+}
+
+LIR_Opr LIRGenerator::access_atomic_add_at(DecoratorSet decorators, BasicType type,
+ LIRItem& base, LIRItem& offset, LIRItem& value) {
+ BarrierSetC1 *bs = BarrierSet::barrier_set()->barrier_set_c1();
+ bool as_raw = (decorators & AS_RAW) != 0;
+ if (as_raw) {
+ return bs->BarrierSetC1::atomic_add_at(this, decorators, type,
+ base, offset, value);
+ } else {
+ return bs->atomic_add_at(this, decorators, type,
+ base, offset, value);
+ }
+}
void LIRGenerator::do_LoadField(LoadField* x) {
bool needs_patching = x->needs_patching();
bool is_volatile = x->field()->is_volatile();
BasicType field_type = x->field_type();
// If the class is not loaded and the object is NULL, we need to deoptimize to throw a
// NoClassDefFoundError in the interpreter instead of an implicit NPE from compiled code.
__ null_check(obj, new CodeEmitInfo(info), /* deoptimize */ needs_patching);
}
- LIR_Opr reg = rlock_result(x, field_type);
- LIR_Address* address;
- if (needs_patching) {
- // we need to patch the offset in the instruction so don't allow
- // generate_address to try to be smart about emitting the -1.
- // Otherwise the patching code won't know how to find the
- // instruction to patch.
- address = new LIR_Address(object.result(), PATCHED_ADDR, field_type);
- } else {
- address = generate_address(object.result(), x->offset(), field_type);
- }
-
- if (support_IRIW_for_not_multiple_copy_atomic_cpu && is_volatile && os::is_MP()) {
- __ membar();
+ DecoratorSet decorators = IN_HEAP;
+ if (is_volatile) {
+ decorators |= MO_SEQ_CST;
}
-
- bool needs_atomic_access = is_volatile || AlwaysAtomicAccesses;
- if (needs_atomic_access && !needs_patching) {
- volatile_field_load(address, reg, info);
- } else {
- LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none;
- __ load(address, reg, info, patch_code);
+ if (needs_patching) {
+ decorators |= C1_NEEDS_PATCHING;
}
- if (is_volatile && os::is_MP()) {
- __ membar_acquire();
- }
+ LIR_Opr result = rlock_result(x, field_type);
+ access_load_at(decorators, field_type,
+ object, LIR_OprFact::intConst(x->offset()), result,
+ info ? new CodeEmitInfo(info) : NULL, info);
}
//------------------------java.nio.Buffer.checkIndex------------------------
__ move(LIR_OprFact::oopConst(NULL), obj);
__ null_check(obj, new CodeEmitInfo(null_check_info));
}
}
- // emit array address setup early so it schedules better
- LIR_Address* array_addr = emit_array_address(array.result(), index.result(), x->elt_type(), false);
-
if (GenerateRangeChecks && needs_range_check) {
if (StressLoopInvariantCodeMotion && range_check_info->deoptimize_on_exception()) {
__ branch(lir_cond_always, T_ILLEGAL, new RangeCheckStub(range_check_info, index.result()));
} else if (use_length) {
// TODO: use a (modified) version of array_range_check that does not require a
// The range check performs the null check, so clear it out for the load
null_check_info = NULL;
}
}
- __ move(array_addr, rlock_result(x, x->elt_type()), null_check_info);
+ DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+
+ LIR_Opr result = rlock_result(x, x->elt_type());
+ access_load_at(decorators, x->elt_type(),
+ array, index.result(), result,
+ NULL, null_check_info);
}
void LIRGenerator::do_NullCheck(NullCheck* x) {
if (x->can_trap()) {
LIRItem off(x->offset(), this);
off.load_item();
src.load_item();
- LIR_Opr value = rlock_result(x, x->basic_type());
+ DecoratorSet decorators = IN_HEAP;
- if (support_IRIW_for_not_multiple_copy_atomic_cpu && x->is_volatile() && os::is_MP()) {
- __ membar();
+ if (x->is_volatile()) {
+ decorators |= MO_SEQ_CST;
}
-
- get_Object_unsafe(value, src.result(), off.result(), type, x->is_volatile());
-
-#if INCLUDE_ALL_GCS
- // We might be reading the value of the referent field of a
- // Reference object in order to attach it back to the live
- // object graph. If G1 is enabled then we need to record
- // the value that is being returned in an SATB log buffer.
- //
- // We need to generate code similar to the following...
- //
- // if (offset == java_lang_ref_Reference::referent_offset) {
- // if (src != NULL) {
- // if (klass(src)->reference_type() != REF_NONE) {
- // pre_barrier(..., value, ...);
- // }
- // }
- // }
-
- if (UseG1GC && type == T_OBJECT) {
- bool gen_pre_barrier = true; // Assume we need to generate pre_barrier.
- bool gen_offset_check = true; // Assume we need to generate the offset guard.
- bool gen_source_check = true; // Assume we need to check the src object for null.
- bool gen_type_check = true; // Assume we need to check the reference_type.
-
- if (off.is_constant()) {
- jlong off_con = (off.type()->is_int() ?
- (jlong) off.get_jint_constant() :
- off.get_jlong_constant());
-
-
- if (off_con != (jlong) java_lang_ref_Reference::referent_offset) {
- // The constant offset is something other than referent_offset.
- // We can skip generating/checking the remaining guards and
- // skip generation of the code stub.
- gen_pre_barrier = false;
- } else {
- // The constant offset is the same as referent_offset -
- // we do not need to generate a runtime offset check.
- gen_offset_check = false;
- }
- }
-
- // We don't need to generate stub if the source object is an array
- if (gen_pre_barrier && src.type()->is_array()) {
- gen_pre_barrier = false;
- }
-
- if (gen_pre_barrier) {
- // We still need to continue with the checks.
- if (src.is_constant()) {
- ciObject* src_con = src.get_jobject_constant();
- guarantee(src_con != NULL, "no source constant");
-
- if (src_con->is_null_object()) {
- // The constant src object is null - We can skip
- // generating the code stub.
- gen_pre_barrier = false;
- } else {
- // Non-null constant source object. We still have to generate
- // the slow stub - but we don't need to generate the runtime
- // null object check.
- gen_source_check = false;
- }
- }
- }
- if (gen_pre_barrier && !PatchALot) {
- // Can the klass of object be statically determined to be
- // a sub-class of Reference?
- ciType* type = src.value()->declared_type();
- if ((type != NULL) && type->is_loaded()) {
- if (type->is_subtype_of(compilation()->env()->Reference_klass())) {
- gen_type_check = false;
- } else if (type->is_klass() &&
- !compilation()->env()->Object_klass()->is_subtype_of(type->as_klass())) {
- // Not Reference and not Object klass.
- gen_pre_barrier = false;
- }
- }
- }
-
- if (gen_pre_barrier) {
- LabelObj* Lcont = new LabelObj();
-
- // We can have generate one runtime check here. Let's start with
- // the offset check.
- if (gen_offset_check) {
- // if (offset != referent_offset) -> continue
- // If offset is an int then we can do the comparison with the
- // referent_offset constant; otherwise we need to move
- // referent_offset into a temporary register and generate
- // a reg-reg compare.
-
- LIR_Opr referent_off;
-
- if (off.type()->is_int()) {
- referent_off = LIR_OprFact::intConst(java_lang_ref_Reference::referent_offset);
- } else {
- assert(off.type()->is_long(), "what else?");
- referent_off = new_register(T_LONG);
- __ move(LIR_OprFact::longConst(java_lang_ref_Reference::referent_offset), referent_off);
- }
- __ cmp(lir_cond_notEqual, off.result(), referent_off);
- __ branch(lir_cond_notEqual, as_BasicType(off.type()), Lcont->label());
- }
- if (gen_source_check) {
- // offset is a const and equals referent offset
- // if (source == null) -> continue
- __ cmp(lir_cond_equal, src.result(), LIR_OprFact::oopConst(NULL));
- __ branch(lir_cond_equal, T_OBJECT, Lcont->label());
- }
- LIR_Opr src_klass = new_register(T_OBJECT);
- if (gen_type_check) {
- // We have determined that offset == referent_offset && src != null.
- // if (src->_klass->_reference_type == REF_NONE) -> continue
- __ move(new LIR_Address(src.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), src_klass);
- LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(InstanceKlass::reference_type_offset()), T_BYTE);
- LIR_Opr reference_type = new_register(T_INT);
- __ move(reference_type_addr, reference_type);
- __ cmp(lir_cond_equal, reference_type, LIR_OprFact::intConst(REF_NONE));
- __ branch(lir_cond_equal, T_INT, Lcont->label());
- }
- {
- // We have determined that src->_klass->_reference_type != REF_NONE
- // so register the value in the referent field with the pre-barrier.
- pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */,
- value /* pre_val */,
- false /* do_load */,
- false /* patch */,
- NULL /* info */);
- }
- __ branch_destination(Lcont->label());
- }
- }
-#endif // INCLUDE_ALL_GCS
-
- if (x->is_volatile() && os::is_MP()) __ membar_acquire();
-
- /* Normalize boolean value returned by unsafe operation, i.e., value != 0 ? value = true : value false. */
if (type == T_BOOLEAN) {
- LabelObj* equalZeroLabel = new LabelObj();
- __ cmp(lir_cond_equal, value, 0);
- __ branch(lir_cond_equal, T_BOOLEAN, equalZeroLabel->label());
- __ move(LIR_OprFact::intConst(1), value);
- __ branch_destination(equalZeroLabel->label());
+ decorators |= C1_MASK_BOOLEAN;
+ }
+ if (type == T_ARRAY || type == T_OBJECT) {
+ decorators |= ON_UNKNOWN_OOP_REF;
}
+
+ LIR_Opr result = rlock_result(x, type);
+ access_load_at(decorators, type,
+ src, off.result(), result,
+ NULL, NULL);
}
void LIRGenerator::do_UnsafePutObject(UnsafePutObject* x) {
BasicType type = x->basic_type();
}
off.load_item();
set_no_result(x);
- if (x->is_volatile() && os::is_MP()) __ membar_release();
- put_Object_unsafe(src.result(), off.result(), data.result(), type, x->is_volatile());
- if (!support_IRIW_for_not_multiple_copy_atomic_cpu && x->is_volatile() && os::is_MP()) __ membar();
+ DecoratorSet decorators = IN_HEAP;
+ if (type == T_ARRAY || type == T_OBJECT) {
+ decorators |= ON_UNKNOWN_OOP_REF;
+ }
+ if (x->is_volatile()) {
+ decorators |= MO_SEQ_CST;
+ }
+ access_store_at(decorators, type, src, off.result(), data.result(), NULL, NULL);
}
+void LIRGenerator::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {
+ BasicType type = x->basic_type();
+ LIRItem src(x->object(), this);
+ LIRItem off(x->offset(), this);
+ LIRItem value(x->value(), this);
+
+ DecoratorSet decorators = IN_HEAP | MO_SEQ_CST;
+
+ if (type == T_ARRAY || type == T_OBJECT) {
+ decorators |= ON_UNKNOWN_OOP_REF;
+ }
+
+ LIR_Opr result;
+ if (x->is_add()) {
+ result = access_atomic_add_at(decorators, type, src, off, value);
+ } else {
+ result = access_atomic_xchg_at(decorators, type, src, off, value);
+ }
+ set_result(x, result);
+}
void LIRGenerator::do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux) {
int lng = x->length();
for (int i = 0; i < lng; i++) {
default : ShouldNotReachHere(); break;
}
}
}
+LIR_Opr LIRGenerator::mask_boolean(LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info) {
+ LIR_Opr value_fixed = rlock_byte(T_BYTE);
+ if (TwoOperandLIRForm) {
+ __ move(value, value_fixed);
+ __ logical_and(value_fixed, LIR_OprFact::intConst(1), value_fixed);
+ } else {
+ __ logical_and(value, LIR_OprFact::intConst(1), value_fixed);
+ }
+ LIR_Opr klass = new_register(T_METADATA);
+ __ move(new LIR_Address(array, oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, null_check_info);
+ null_check_info = NULL;
+ LIR_Opr layout = new_register(T_INT);
+ __ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout);
+ int diffbit = Klass::layout_helper_boolean_diffbit();
+ __ logical_and(layout, LIR_OprFact::intConst(diffbit), layout);
+ __ cmp(lir_cond_notEqual, layout, LIR_OprFact::intConst(0));
+ __ cmove(lir_cond_notEqual, value_fixed, value, value_fixed, T_BYTE);
+ value = value_fixed;
+ return value;
+}
+
LIR_Opr LIRGenerator::maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info) {
if (x->check_boolean()) {
- LIR_Opr value_fixed = rlock_byte(T_BYTE);
- if (TwoOperandLIRForm) {
- __ move(value, value_fixed);
- __ logical_and(value_fixed, LIR_OprFact::intConst(1), value_fixed);
- } else {
- __ logical_and(value, LIR_OprFact::intConst(1), value_fixed);
- }
- LIR_Opr klass = new_register(T_METADATA);
- __ move(new LIR_Address(array, oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, null_check_info);
- null_check_info = NULL;
- LIR_Opr layout = new_register(T_INT);
- __ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout);
- int diffbit = Klass::layout_helper_boolean_diffbit();
- __ logical_and(layout, LIR_OprFact::intConst(diffbit), layout);
- __ cmp(lir_cond_notEqual, layout, LIR_OprFact::intConst(0));
- __ cmove(lir_cond_notEqual, value_fixed, value, value_fixed, T_BYTE);
- value = value_fixed;
+ value = mask_boolean(array, value, null_check_info);
}
return value;
}
< prev index next >