Skip to content
Permalink
Browse files
8277417: C1 LIR instruction for load-klass
Reviewed-by: iveresov, mdoerr, ngasson, aph
  • Loading branch information
rkennke committed Nov 26, 2021
1 parent 00a6238 commit 99e4bda
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 49 deletions.
@@ -986,14 +986,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch
__ ldr(dest->as_register(), as_Address(from_addr));
break;
case T_ADDRESS:
// FIXME: OMG this is a horrible kludge. Any offset from an
// address that matches klass_offset_in_bytes() will be loaded
// as a word, not a long.
if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) {
__ ldrw(dest->as_register(), as_Address(from_addr));
} else {
__ ldr(dest->as_register(), as_Address(from_addr));
}
__ ldr(dest->as_register(), as_Address(from_addr));
break;
case T_INT:
__ ldrw(dest->as_register(), as_Address(from_addr));
@@ -1032,10 +1025,6 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch
// Load barrier has not yet been applied, so ZGC can't verify the oop here
__ verify_oop(dest->as_register());
}
} else if (type == T_ADDRESS && addr->disp() == oopDesc::klass_offset_in_bytes()) {
if (UseCompressedClassPointers) {
__ decode_klass_not_null(dest->as_register());
}
}
}

@@ -2593,6 +2582,22 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
__ bind(*op->stub()->continuation());
}

void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) {
Register obj = op->obj()->as_pointer_register();
Register result = op->result_opr()->as_pointer_register();

CodeEmitInfo* info = op->info();
if (info != NULL) {
add_debug_info_for_null_check_here(info);
}

if (UseCompressedClassPointers) {
__ ldrw(result, Address (obj, oopDesc::klass_offset_in_bytes()));
__ decode_klass_not_null(result);
} else {
__ ldr(result, Address (obj, oopDesc::klass_offset_in_bytes()));
}
}

void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
ciMethod* method = op->profiled_method();
@@ -720,11 +720,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type,
break;

case T_ADDRESS:
if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) {
__ ldr_u32(dest->as_pointer_register(), as_Address(addr));
} else {
__ ldr(dest->as_pointer_register(), as_Address(addr));
}
__ ldr(dest->as_pointer_register(), as_Address(addr));
break;

case T_INT:
@@ -2445,6 +2441,21 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
__ bind(*op->stub()->continuation());
}

void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) {
Register obj = op->obj()->as_pointer_register();
Register result = op->result_opr()->as_pointer_register();

CodeEmitInfo* info = op->info();
if (info != NULL) {
add_debug_info_for_null_check_here(info);
}

if (UseCompressedClassPointers) { // On 32 bit arm??
__ ldr_u32(result, Address(obj, oopDesc::klass_offset_in_bytes()));
} else {
__ ldr(result, Address(obj, oopDesc::klass_offset_in_bytes()));
}
}

void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
ciMethod* method = op->profiled_method();
@@ -812,12 +812,7 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ
case T_LONG : __ ld(to_reg->as_register_lo(), offset, base); break;
case T_METADATA: __ ld(to_reg->as_register(), offset, base); break;
case T_ADDRESS:
if (offset == oopDesc::klass_offset_in_bytes() && UseCompressedClassPointers) {
__ lwz(to_reg->as_register(), offset, base);
__ decode_klass_not_null(to_reg->as_register());
} else {
__ ld(to_reg->as_register(), offset, base);
}
__ ld(to_reg->as_register(), offset, base);
break;
case T_ARRAY : // fall through
case T_OBJECT:
@@ -2732,6 +2727,28 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
__ bind(*op->stub()->continuation());
}

void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) {
Register obj = op->obj()->as_pointer_register();
Register result = op->result_opr()->as_pointer_register();

CodeEmitInfo* info = op->info();
if (info != NULL) {
if (info != NULL) {
if (!os::zero_page_read_protected() || !ImplicitNullChecks) {
explicit_null_check(obj, info);
} else {
add_debug_info_for_null_check_here(info);
}
}
}

if (UseCompressedClassPointers) {
__ lwz(result, oopDesc::klass_offset_in_bytes(), obj);
__ decode_klass_not_null(result);
} else {
__ ld(result, oopDesc::klass_offset_in_bytes(), obj);
}
}

void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
ciMethod* method = op->profiled_method();
@@ -950,12 +950,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src_opr, LIR_Opr dest, BasicType type, LIR_P
}
break;
case T_ADDRESS:
if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) {
__ z_llgf(dest->as_register(), disp_value, disp_reg, src);
__ decode_klass_not_null(dest->as_register());
} else {
__ z_lg(dest->as_register(), disp_value, disp_reg, src);
}
__ z_lg(dest->as_register(), disp_value, disp_reg, src);
break;
case T_ARRAY : // fall through
case T_OBJECT:
@@ -2754,6 +2749,22 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
__ bind(*op->stub()->continuation());
}

void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) {
Register obj = op->obj()->as_pointer_register();
Register result = op->result_opr()->as_pointer_register();

CodeEmitInfo* info = op->info();
if (info != NULL) {
add_debug_info_for_null_check_here(info);
}

if (UseCompressedClassPointers) {
__ z_llgf(result, Address(obj, oopDesc::klass_offset_in_bytes()));
__ decode_klass_not_null(result);
} else {
__ z_lg(result, Address(obj, oopDesc::klass_offset_in_bytes()));
}
}
void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
ciMethod* method = op->profiled_method();
int bci = op->profiled_bci();
@@ -1184,7 +1184,6 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch

LIR_Address* addr = src->as_address_ptr();
Address from_addr = as_Address(addr);
Register tmp_load_klass = LP64_ONLY(rscratch1) NOT_LP64(noreg);

if (addr->base()->type() == T_OBJECT) {
__ verify_oop(addr->base()->as_pointer_register());
@@ -1257,11 +1256,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch
break;

case T_ADDRESS:
if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) {
__ movl(dest->as_register(), from_addr);
} else {
__ movptr(dest->as_register(), from_addr);
}
__ movptr(dest->as_register(), from_addr);
break;
case T_INT:
__ movl(dest->as_register(), from_addr);
@@ -1367,12 +1362,6 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch
if (!UseZGC) {
__ verify_oop(dest->as_register());
}
} else if (type == T_ADDRESS && addr->disp() == oopDesc::klass_offset_in_bytes()) {
#ifdef _LP64
if (UseCompressedClassPointers) {
__ decode_klass_not_null(dest->as_register(), tmp_load_klass);
}
#endif
}
}

@@ -3528,6 +3517,23 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) {
__ bind(*op->stub()->continuation());
}

void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) {
Register obj = op->obj()->as_pointer_register();
Register result = op->result_opr()->as_pointer_register();

CodeEmitInfo* info = op->info();
if (info != NULL) {
add_debug_info_for_null_check_here(info);
}

#ifdef _LP64
if (UseCompressedClassPointers) {
__ movl(result, Address(obj, oopDesc::klass_offset_in_bytes()));
__ decode_klass_not_null(result, rscratch1);
} else
#endif
__ movptr(result, Address(obj, oopDesc::klass_offset_in_bytes()));
}

void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
ciMethod* method = op->profiled_method();
@@ -880,6 +880,19 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
break;
}

// LIR_OpLoadKlass
case lir_load_klass:
{
LIR_OpLoadKlass* opLoadKlass = op->as_OpLoadKlass();
assert(opLoadKlass != NULL, "must be");

do_input(opLoadKlass->_obj);
do_output(opLoadKlass->_result);
if (opLoadKlass->_info) do_info(opLoadKlass->_info);
break;
}


// LIR_OpProfileCall:
case lir_profile_call: {
assert(op->as_OpProfileCall() != NULL, "must be");
@@ -1049,6 +1062,10 @@ void LIR_OpLock::emit_code(LIR_Assembler* masm) {
}
}

void LIR_OpLoadKlass::emit_code(LIR_Assembler* masm) {
masm->emit_load_klass(this);
}

#ifdef ASSERT
void LIR_OpAssert::emit_code(LIR_Assembler* masm) {
masm->emit_assert(this);
@@ -1970,6 +1987,11 @@ void LIR_OpLock::print_instr(outputStream* out) const {
out->print("[lbl:" INTPTR_FORMAT "]", p2i(stub()->entry()));
}

void LIR_OpLoadKlass::print_instr(outputStream* out) const {
obj()->print(out); out->print(" ");
result_opr()->print(out); out->print(" ");
}

#ifdef ASSERT
void LIR_OpAssert::print_instr(outputStream* out) const {
print_condition(out, condition()); out->print(" ");
@@ -895,6 +895,7 @@ class LIR_OpUpdateCRC32;
class LIR_OpLock;
class LIR_OpTypeCheck;
class LIR_OpCompareAndSwap;
class LIR_OpLoadKlass;
class LIR_OpProfileCall;
class LIR_OpProfileType;
#ifdef ASSERT
@@ -939,6 +940,7 @@ enum LIR_Code {
, lir_roundfp
, lir_safepoint
, lir_unwind
, lir_load_klass
, end_op1
, begin_op2
, lir_cmp
@@ -1148,6 +1150,7 @@ class LIR_Op: public CompilationResourceObj {
virtual LIR_OpUpdateCRC32* as_OpUpdateCRC32() { return NULL; }
virtual LIR_OpTypeCheck* as_OpTypeCheck() { return NULL; }
virtual LIR_OpCompareAndSwap* as_OpCompareAndSwap() { return NULL; }
virtual LIR_OpLoadKlass* as_OpLoadKlass() { return NULL; }
virtual LIR_OpProfileCall* as_OpProfileCall() { return NULL; }
virtual LIR_OpProfileType* as_OpProfileType() { return NULL; }
#ifdef ASSERT
@@ -1820,6 +1823,25 @@ class LIR_OpLock: public LIR_Op {
void print_instr(outputStream* out) const PRODUCT_RETURN;
};

class LIR_OpLoadKlass: public LIR_Op {
friend class LIR_OpVisitState;

private:
LIR_Opr _obj;
CodeEmitInfo* _info;
public:
LIR_OpLoadKlass(LIR_Opr obj, LIR_Opr result, CodeEmitInfo* info)
: LIR_Op(lir_load_klass, result, NULL)
, _obj(obj)
, _info(info) {}

LIR_Opr obj() const { return _obj; }
CodeEmitInfo* info() const { return _info; }

virtual LIR_OpLoadKlass* as_OpLoadKlass() { return this; }
virtual void emit_code(LIR_Assembler* masm);
void print_instr(outputStream* out) const PRODUCT_RETURN;
};

class LIR_OpDelay: public LIR_Op {
friend class LIR_OpVisitState;
@@ -2262,6 +2284,9 @@ class LIR_List: public CompilationResourceObj {

void xadd(LIR_Opr src, LIR_Opr add, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_xadd, src, add, res, tmp)); }
void xchg(LIR_Opr src, LIR_Opr set, LIR_Opr res, LIR_Opr tmp) { append(new LIR_Op2(lir_xchg, src, set, res, tmp)); }

void load_klass(LIR_Opr obj, LIR_Opr result, CodeEmitInfo* info) { append(new LIR_OpLoadKlass(obj, result, info)); }

#ifdef ASSERT
void lir_assert(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, const char* msg, bool halt) { append(new LIR_OpAssert(condition, opr1, opr2, msg, halt)); }
#endif
@@ -197,6 +197,7 @@ class LIR_Assembler: public CompilationResourceObj {
void emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, Label* failure, Label* obj_is_null);
void emit_compare_and_swap(LIR_OpCompareAndSwap* op);
void emit_lock(LIR_OpLock* op);
void emit_load_klass(LIR_OpLoadKlass* op);
void emit_call(LIR_OpJavaCall* op);
void emit_rtcall(LIR_OpRTCall* op);
void emit_profile_call(LIR_OpProfileCall* op);
@@ -1231,13 +1231,17 @@ void LIRGenerator::do_isInstance(Intrinsic* x) {
__ move(call_result, result);
}

void LIRGenerator::load_klass(LIR_Opr obj, LIR_Opr klass, CodeEmitInfo* null_check_info) {
__ load_klass(obj, klass, null_check_info);
}

// Example: object.getClass ()
void LIRGenerator::do_getClass(Intrinsic* x) {
assert(x->number_of_arguments() == 1, "wrong type");

LIRItem rcvr(x->argument_at(0), this);
rcvr.load_item();
LIR_Opr temp = new_register(T_METADATA);
LIR_Opr temp = new_register(T_ADDRESS);
LIR_Opr result = rlock_result(x);

// need to perform the null check on the rcvr
@@ -1246,10 +1250,9 @@ void LIRGenerator::do_getClass(Intrinsic* x) {
info = state_for(x);
}

// FIXME T_ADDRESS should actually be T_METADATA but it can't because the
// meaning of these two is mixed up (see JDK-8026837).
__ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), temp, info);
__ move_wide(new LIR_Address(temp, in_bytes(Klass::java_mirror_offset()), T_ADDRESS), temp);
LIR_Opr klass = new_register(T_METADATA);
load_klass(rcvr.result(), klass, info);
__ move_wide(new LIR_Address(klass, in_bytes(Klass::java_mirror_offset()), T_ADDRESS), temp);
// mirror = ((OopHandle)mirror)->resolve();
access_load(IN_NATIVE, T_OBJECT,
LIR_OprFact::address(new LIR_Address(temp, T_OBJECT)), result);
@@ -1322,7 +1325,7 @@ void LIRGenerator::do_getObjectSize(Intrinsic* x) {
value.load_item();

LIR_Opr klass = new_register(T_METADATA);
__ move(new LIR_Address(value.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, NULL);
load_klass(value.result(), klass, NULL);
LIR_Opr layout = new_register(T_INT);
__ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout);

@@ -3572,7 +3575,7 @@ LIR_Opr LIRGenerator::mask_boolean(LIR_Opr array, LIR_Opr value, CodeEmitInfo*&
__ 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);
load_klass(array, 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);
@@ -239,6 +239,8 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
void move_to_phi(PhiResolver* resolver, Value cur_val, Value sux_val);
void move_to_phi(ValueStack* cur_state);

void load_klass(LIR_Opr obj, LIR_Opr klass, CodeEmitInfo* null_check_info);

// platform dependent
LIR_Opr getThreadPointer();

1 comment on commit 99e4bda

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.