src/share/vm/c1/c1_LIRGenerator.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/c1/c1_LIRGenerator.cpp Fri Apr 17 16:13:46 2015
--- new/src/share/vm/c1/c1_LIRGenerator.cpp Fri Apr 17 16:13:46 2015
*** 2023,2202 ****
--- 2023,2240 ----
__ roundfp(input_opr, LIR_OprFact::illegalOpr, result);
set_result(x, result);
}
}
// Here UnsafeGetRaw may have x->base() and x->index() be int or long
// on both 64 and 32 bits. Expecting x->base() to be always long on 64bit.
+ // The LIRGenerator::do_UnsafeGetRaw method expects that:
+ // - x->base() is of type int or long on 32-bit architectures;
+ // - x->base() is of type long on 64-bit architectures;
+ // - x->index() of type int or of type long on both 64-bit and 32-bit architectures.
+ //
+ // This method allows x->index() to be a constant. If x->index() is
+ // a constant int, the method generates a memory access instruction
+ // with index embedded into it as an offset.
void LIRGenerator::do_UnsafeGetRaw(UnsafeGetRaw* x) {
LIRItem base(x->base(), this);
! LIRItem idx(this);
! LIRItem index(this);
base.load_item();
if (x->has_index()) {
! idx.set_instruction(x->index());
! idx.load_nonconstant();
! index.set_instruction(x->index());
! index.load_nonconstant(); // index can be constant
}
LIR_Opr reg = rlock_result(x, x->basic_type());
+ assert(!x->has_index() || index.value() == x->index(), "index values must match");
int log2_scale = 0;
if (x->has_index()) {
log2_scale = x->log2_scale();
}
assert(!x->has_index() || idx.value() == x->index(), "should match");
+ // Prepare register to 'get' result into.
+ BasicType type = x->basic_type();
+ LIR_Opr reg = rlock_result(x, type);
LIR_Opr base_op = base.result();
! LIR_Opr index_op = idx.result();
! LIR_Opr index_op = index.result();
#ifndef _LP64
if (base_op->type() == T_LONG) {
! base_op = new_register(T_INT);
! __ convert(Bytecodes::_l2i, base.result(), base_op);
! LIR_Opr tmp = new_register(T_INT);
! __ convert(Bytecodes::_l2i, base_op, tmp);
+ base_op = tmp;
}
if (x->has_index()) {
if (index_op->type() == T_LONG) {
LIR_Opr long_index_op = index_op;
if (index_op->is_constant()) {
! long_index_op = new_register(T_LONG);
! __ move(index_op, long_index_op);
}
index_op = new_register(T_INT);
! __ convert(Bytecodes::_l2i, long_index_op, index_op);
} else {
! assert(x->index()->type()->tag() == intTag, "must be");
}
}
// At this point base and index should be all ints.
assert(base_op->type() == T_INT && !base_op->is_constant(), "base should be an non-constant int");
assert(!x->has_index() || index_op->type() == T_INT, "index should be an int");
#else
! LIR_Opr tmp1 = new_register(T_LONG);
! __ move(index_op, tmp1);
+ index_op = tmp1;
+ }
! LIR_Opr tmp2 = new_register(T_INT);
+ __ convert(Bytecodes::_l2i, index_op, tmp2);
! index_op = tmp2;
+ } else {
+ assert(index_op->type() == T_INT, "index must by of type int (constant or non-constant)");
+ }
+ }
+ // At this point the following holds:
+ // - base is a non-constant int;
+ // - index is an int (either constant or not constant).
+ assert(base_op->type() == T_INT && !base_op->is_constant(), "base must be a non-constant int");
+ assert(!x->has_index()
+ || index_op->type() == T_INT,
+ "if index is available, it must be an int (constant or non-constant)");
+ #else // _LP64
if (x->has_index()) {
if (index_op->type() == T_INT) {
if (!index_op->is_constant()) {
! index_op = new_register(T_LONG);
! __ convert(Bytecodes::_i2l, idx.result(), index_op);
}
! LIR_Opr tmp = new_register(T_LONG);
! __ convert(Bytecodes::_i2l, index_op, tmp);
+ index_op = tmp;
+ }
+ // If index is a non-constant int, we keep its type, because that allows
+ // embedding the index as an immediate offset into the final address expression.
+ // If we would convert index to long, the index would have to be moved into
+ // a register before using it in a memory access instruction.
} else {
! assert(index_op->type() == T_LONG, "index_op must be of type long");
if (index_op->is_constant()) {
! index_op = new_register(T_LONG);
! __ move(idx.result(), index_op);
! LIR_Opr tmp = new_register(T_LONG);
! __ move(index_op, tmp);
+ index_op = tmp;
}
}
}
! // At this point base is a long non-constant
// Index is a long register or a int constant.
// We allow the constant to stay an int because that would allow us a more compact encoding by
// embedding an immediate offset in the address expression. If we have a long constant, we have to
// move it into a register first.
assert(base_op->type() == T_LONG && !base_op->is_constant(), "base must be a long non-constant");
assert(!x->has_index() || (index_op->type() == T_INT && index_op->is_constant()) ||
! (index_op->type() == T_LONG && !index_op->is_constant()), "unexpected index type");
! #endif
BasicType dst_type = x->basic_type();
! // At this point the following holds:
+ // - base is a long non-constant;
+ // - index is a long register or an int constant.
+ assert(base_op->type() == T_LONG && !base_op->is_constant(), "base must be a non-constant long");
+ assert(!x->has_index()
+ || (index_op->type() == T_INT && index_op->is_constant())
+ || (index_op->type() == T_LONG && !index_op->is_constant()),
! "if index is available, it must be a constant int or a non-constant long");
! #endif // _LP64
LIR_Address* addr;
if (index_op->is_constant()) {
assert(log2_scale == 0, "must not have a scale");
! assert(index_op->type() == T_INT, "only int constants supported");
- addr = new LIR_Address(base_op, index_op->as_jint(), dst_type);
! assert(index_op->type() == T_INT, "only int constants can used as an address index");
! addr = new LIR_Address(base_op, index_op->as_jint(), type);
} else {
#ifdef X86
- addr = new LIR_Address(base_op, index_op, LIR_Address::Scale(log2_scale), 0, dst_type);
#elif defined(GENERATE_ADDRESS_IS_PREFERRED)
- addr = generate_address(base_op, index_op, log2_scale, 0, dst_type);
#else
if (index_op->is_illegal() || log2_scale == 0) {
- addr = new LIR_Address(base_op, index_op, dst_type);
} else {
LIR_Opr tmp = new_pointer_register();
__ shift_left(index_op, log2_scale, tmp);
- addr = new LIR_Address(base_op, tmp, dst_type);
}
! #endif // !X86 && !defined(GENERATE_ADDRESS_IS_PREFERRED)
}
! if (x->may_be_unaligned() && (dst_type == T_LONG || dst_type == T_DOUBLE)) {
__ unaligned_move(addr, reg);
} else {
- if (dst_type == T_OBJECT && x->is_wide()) {
__ move_wide(addr, reg);
} else {
__ move(addr, reg);
}
}
}
+ // Similar to LIRGenerator::do_UnsafeGetRaw, the LIRGenerator::do_UnsafePutRaw
+ // method expects that:
+ // - x->base() is of type int or long on 32-bit architectures;
+ // - x->base() is of type long on 64-bit architectures;
+ // - x->index() of type int or of type long on both 64-bit and 32-bit architectures.
+ //
+ // This method differs from LIRGenerator::do_UnsafeGetRaw in that it expects that
+ // x->index() is non-constant.
void LIRGenerator::do_UnsafePutRaw(UnsafePutRaw* x) {
int log2_scale = 0;
BasicType type = x->basic_type();
if (x->has_index()) {
log2_scale = x->log2_scale();
}
LIRItem base(x->base(), this);
+ LIRItem index(this);
LIRItem value(x->value(), this);
LIRItem idx(this);
base.load_item();
if (x->has_index()) {
! idx.set_instruction(x->index());
! idx.load_item();
! index.set_instruction(x->index());
! index.load_item(); // index cannot be a constant
}
+ assert(!x->has_index() || index.value() == x->index(), "index values must match");
+ assert(!index.result()->is_constant(), "the result of index must not be constant");
+ int log2_scale = 0;
+ if (x->has_index()) {
+ log2_scale = x->log2_scale();
+ }
+
+ // Load value to be 'put' into memory.
+ BasicType type = x->basic_type();
if (type == T_BYTE || type == T_BOOLEAN) {
value.load_byte_item();
} else {
value.load_item();
}
set_no_result(x);
LIR_Opr base_op = base.result();
! LIR_Opr index_op = idx.result();
#ifdef GENERATE_ADDRESS_IS_PREFERRED
LIR_Address* addr = generate_address(base_op, index_op, log2_scale, 0, x->basic_type());
#else
! LIR_Opr index_op = index.result();
#ifndef _LP64
if (base_op->type() == T_LONG) {
! base_op = new_register(T_INT);
! __ convert(Bytecodes::_l2i, base.result(), base_op);
! LIR_Opr tmp = new_register(T_INT);
! __ convert(Bytecodes::_l2i, base_op, tmp);
+ base_op = tmp;
}
if (x->has_index()) {
if (index_op->type() == T_LONG) {
! index_op = new_register(T_INT);
! __ convert(Bytecodes::_l2i, idx.result(), index_op);
! LIR_Opr tmp = new_register(T_INT);
! __ convert(Bytecodes::_l2i, index_op, tmp);
+ index_op = tmp;
+ } else {
+ assert(index_op->type() == T_INT, "index_op must be of type int");
}
}
! // At this point base and index should be all ints and not constants
! assert(base_op->type() == T_INT && !base_op->is_constant(), "base should be an non-constant int");
- assert(!x->has_index() || (index_op->type() == T_INT && !index_op->is_constant()), "index should be an non-constant int");
#else
! // At this point both base and index are a non-constant int.
! assert(base_op->type() == T_INT && !base_op->is_constant(), "base must be a non-constant int");
! assert(!x->has_index()
+ || (index_op->type() == T_INT && !index_op->is_constant()),
+ "if index is available, it must be a non-constant int");
+ #else // _LP64
if (x->has_index()) {
if (index_op->type() == T_INT) {
! index_op = new_register(T_LONG);
! __ convert(Bytecodes::_i2l, idx.result(), index_op);
! LIR_Opr tmp = new_register(T_LONG);
! __ convert(Bytecodes::_i2l, index_op, tmp);
+ index_op = tmp;
+ } else {
+ assert(index_op->type() == T_LONG, "index_op must be of type long");
}
}
// At this point base and index are long and non-constant
assert(base_op->type() == T_LONG && !base_op->is_constant(), "base must be a non-constant long");
- assert(!x->has_index() || (index_op->type() == T_LONG && !index_op->is_constant()), "index must be a non-constant long");
#endif
+ || (index_op->type() == T_LONG && !index_op->is_constant()),
+ "if index is available, index must be a non-constant long");
+ #endif // _LP64
if (log2_scale != 0) {
// temporary fix (platform dependent code without shift on Intel would be better)
// TODO: ARM also allows embedded shift in the address
__ shift_left(index_op, log2_scale, index_op);
+ LIR_Address* addr; // The destination address of the 'put' operation.
+ #ifdef X86
+ addr = new LIR_Address(base_op, index_op, LIR_Address::Scale(log2_scale), 0, type);
+ #elif defined(GENERATE_ADDRESS_IS_PREFERRED)
+ addr = generate_address(base_op, index_op, log2_scale, 0, type);
+ #else
+ if (log2_scale == 0) {
+ addr = new LIR_Address(base_op, index_op, type);
+ } else {
+ LIR_Opr tmp = new_pointer_register();
+ __ shift_left(index_op, log2_scale, tmp);
+ addr = new LIR_Address(base_op, tmp, type);
}
+ #endif // !X86 && !defined(GENERATE_ADDRESS_IS_PREFERRED)
LIR_Address* addr = new LIR_Address(base_op, index_op, x->basic_type());
#endif // !GENERATE_ADDRESS_IS_PREFERRED
__ move(value.result(), addr);
}
void LIRGenerator::do_UnsafeGetObject(UnsafeGetObject* x) {
src/share/vm/c1/c1_LIRGenerator.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File