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