8233081: C1: PatchingStub for field access copies too much
Reviewed-by: thartmann, dlong
This commit is contained in:
parent
3ca7e3f6ff
commit
c15dfbfd60
@ -287,8 +287,6 @@ void NativeMovConstReg::print() {
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
address NativeMovRegMem::instruction_address() const { return addr_at(instruction_offset); }
|
||||
|
||||
int NativeMovRegMem::offset() const {
|
||||
address pc = instruction_address();
|
||||
unsigned insn = *(unsigned*)pc;
|
||||
|
@ -381,11 +381,11 @@ class NativeMovRegMem: public NativeInstruction {
|
||||
|
||||
public:
|
||||
// helper
|
||||
int instruction_start() const;
|
||||
int instruction_start() const { return instruction_offset; }
|
||||
|
||||
address instruction_address() const;
|
||||
address instruction_address() const { return addr_at(instruction_offset); }
|
||||
|
||||
address next_instruction_address() const;
|
||||
int num_bytes_to_end_of_patch() const { return instruction_offset + instruction_size; }
|
||||
|
||||
int offset() const;
|
||||
|
||||
|
@ -349,6 +349,11 @@ NativeCall* rawNativeCall_before(address return_address);
|
||||
// (field access patching is handled differently in that case)
|
||||
class NativeMovRegMem: public NativeInstruction {
|
||||
public:
|
||||
enum arm_specific_constants {
|
||||
instruction_size = 8
|
||||
};
|
||||
|
||||
int num_bytes_to_end_of_patch() const { return instruction_size; }
|
||||
|
||||
int offset() const;
|
||||
void set_offset(int x);
|
||||
|
@ -462,6 +462,8 @@ class NativeMovRegMem: public NativeInstruction {
|
||||
|
||||
address instruction_address() const { return addr_at(0); }
|
||||
|
||||
int num_bytes_to_end_of_patch() const { return instruction_size; }
|
||||
|
||||
intptr_t offset() const {
|
||||
#ifdef VM_LITTLE_ENDIAN
|
||||
short *hi_ptr = (short*)(addr_at(0));
|
||||
|
@ -535,6 +535,12 @@ class NativeMovRegMem;
|
||||
inline NativeMovRegMem* nativeMovRegMem_at (address address);
|
||||
class NativeMovRegMem: public NativeInstruction {
|
||||
public:
|
||||
enum z_specific_constants {
|
||||
instruction_size = 12 // load_const used with access_field_id
|
||||
};
|
||||
|
||||
int num_bytes_to_end_of_patch() const { return instruction_size; }
|
||||
|
||||
intptr_t offset() const {
|
||||
return nativeMovConstReg_at(addr_at(0))->data();
|
||||
}
|
||||
|
@ -574,15 +574,6 @@ void NativeMovConstRegPatching::test() {
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
|
||||
void NativeMovRegMem::copy_instruction_to(address new_instruction_address) {
|
||||
Untested("copy_instruction_to");
|
||||
int instruction_size = next_instruction_address() - instruction_address();
|
||||
for (int i = 0; i < instruction_size; i += BytesPerInstWord) {
|
||||
*(int*)(new_instruction_address + i) = *(int*)(address(this) + i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NativeMovRegMem::verify() {
|
||||
NativeInstruction::verify();
|
||||
// make sure code pattern is actually a "ld" or "st" of some sort.
|
||||
|
@ -576,7 +576,8 @@ class NativeMovConstReg: public NativeInstruction {
|
||||
// sethi and the add. The nop is required to be in the delay slot of the call instruction
|
||||
// which overwrites the sethi during patching.
|
||||
class NativeMovConstRegPatching;
|
||||
inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address);class NativeMovConstRegPatching: public NativeInstruction {
|
||||
inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address);
|
||||
class NativeMovConstRegPatching: public NativeInstruction {
|
||||
public:
|
||||
enum Sparc_specific_constants {
|
||||
sethi_offset = 0,
|
||||
@ -664,10 +665,13 @@ class NativeMovRegMem: public NativeInstruction {
|
||||
return (is_op(i0, Assembler::ldst_op));
|
||||
}
|
||||
|
||||
address instruction_address() const { return addr_at(0); }
|
||||
address next_instruction_address() const {
|
||||
return addr_at(is_immediate() ? 4 : (7 * BytesPerInstWord));
|
||||
address instruction_address() const { return addr_at(0); }
|
||||
|
||||
int num_bytes_to_end_of_patch() const {
|
||||
return is_immediate()? BytesPerInstWord :
|
||||
NativeMovConstReg::instruction_size;
|
||||
}
|
||||
|
||||
intptr_t offset() const {
|
||||
return is_immediate()? inv_simm(long_at(0), offset_width) :
|
||||
nativeMovConstReg_at(addr_at(0))->data();
|
||||
@ -684,8 +688,6 @@ class NativeMovRegMem: public NativeInstruction {
|
||||
set_offset (offset() + radd_offset);
|
||||
}
|
||||
|
||||
void copy_instruction_to(address new_instruction_address);
|
||||
|
||||
void verify();
|
||||
void print ();
|
||||
|
||||
|
@ -355,60 +355,7 @@ int NativeMovRegMem::instruction_start() const {
|
||||
return off;
|
||||
}
|
||||
|
||||
address NativeMovRegMem::instruction_address() const {
|
||||
return addr_at(instruction_start());
|
||||
}
|
||||
|
||||
address NativeMovRegMem::next_instruction_address() const {
|
||||
address ret = instruction_address() + instruction_size;
|
||||
u_char instr_0 = *(u_char*) instruction_address();
|
||||
switch (instr_0) {
|
||||
case instruction_operandsize_prefix:
|
||||
|
||||
fatal("should have skipped instruction_operandsize_prefix");
|
||||
break;
|
||||
|
||||
case instruction_extended_prefix:
|
||||
fatal("should have skipped instruction_extended_prefix");
|
||||
break;
|
||||
|
||||
case instruction_code_mem2reg_movslq: // 0x63
|
||||
case instruction_code_mem2reg_movzxb: // 0xB6
|
||||
case instruction_code_mem2reg_movsxb: // 0xBE
|
||||
case instruction_code_mem2reg_movzxw: // 0xB7
|
||||
case instruction_code_mem2reg_movsxw: // 0xBF
|
||||
case instruction_code_reg2mem: // 0x89 (q/l)
|
||||
case instruction_code_mem2reg: // 0x8B (q/l)
|
||||
case instruction_code_reg2memb: // 0x88
|
||||
case instruction_code_mem2regb: // 0x8a
|
||||
|
||||
case instruction_code_lea: // 0x8d
|
||||
|
||||
case instruction_code_float_s: // 0xd9 fld_s a
|
||||
case instruction_code_float_d: // 0xdd fld_d a
|
||||
|
||||
case instruction_code_xmm_load: // 0x10
|
||||
case instruction_code_xmm_store: // 0x11
|
||||
case instruction_code_xmm_lpd: // 0x12
|
||||
{
|
||||
// If there is an SIB then instruction is longer than expected
|
||||
u_char mod_rm = *(u_char*)(instruction_address() + 1);
|
||||
if ((mod_rm & 7) == 0x4) {
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
case instruction_code_xor:
|
||||
fatal("should have skipped xor lead in");
|
||||
break;
|
||||
|
||||
default:
|
||||
fatal("not a NativeMovRegMem");
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int NativeMovRegMem::offset() const{
|
||||
int NativeMovRegMem::patch_offset() const {
|
||||
int off = data_offset + instruction_start();
|
||||
u_char mod_rm = *(u_char*)(instruction_address() + 1);
|
||||
// nnnn(r12|rsp) isn't coded as simple mod/rm since that is
|
||||
@ -417,19 +364,7 @@ int NativeMovRegMem::offset() const{
|
||||
if ((mod_rm & 7) == 0x4) {
|
||||
off++;
|
||||
}
|
||||
return int_at(off);
|
||||
}
|
||||
|
||||
void NativeMovRegMem::set_offset(int x) {
|
||||
int off = data_offset + instruction_start();
|
||||
u_char mod_rm = *(u_char*)(instruction_address() + 1);
|
||||
// nnnn(r12|rsp) isn't coded as simple mod/rm since that is
|
||||
// the encoding to use an SIB byte. Which will have the nnnn
|
||||
// field off by one byte
|
||||
if ((mod_rm & 7) == 0x4) {
|
||||
off++;
|
||||
}
|
||||
set_int_at(off, x);
|
||||
return off;
|
||||
}
|
||||
|
||||
void NativeMovRegMem::verify() {
|
||||
|
@ -361,7 +361,6 @@ class NativeMovRegMem: public NativeInstruction {
|
||||
instruction_VEX_prefix_3bytes = Assembler::VEX_3bytes,
|
||||
instruction_EVEX_prefix_4bytes = Assembler::EVEX_4bytes,
|
||||
|
||||
instruction_size = 4,
|
||||
instruction_offset = 0,
|
||||
data_offset = 2,
|
||||
next_instruction_offset = 4
|
||||
@ -370,15 +369,26 @@ class NativeMovRegMem: public NativeInstruction {
|
||||
// helper
|
||||
int instruction_start() const;
|
||||
|
||||
address instruction_address() const;
|
||||
address instruction_address() const {
|
||||
return addr_at(instruction_start());
|
||||
}
|
||||
|
||||
address next_instruction_address() const;
|
||||
int num_bytes_to_end_of_patch() const {
|
||||
return patch_offset() + sizeof(jint);
|
||||
}
|
||||
|
||||
int offset() const;
|
||||
int offset() const {
|
||||
return int_at(patch_offset());
|
||||
}
|
||||
|
||||
void set_offset(int x);
|
||||
void set_offset(int x) {
|
||||
set_int_at(patch_offset(), x);
|
||||
}
|
||||
|
||||
void add_offset_in_bytes(int add_offset) { set_offset ( ( offset() + add_offset ) ); }
|
||||
void add_offset_in_bytes(int add_offset) {
|
||||
int patch_off = patch_offset();
|
||||
set_int_at(patch_off, int_at(patch_off) + add_offset);
|
||||
}
|
||||
|
||||
void verify();
|
||||
void print ();
|
||||
@ -387,6 +397,7 @@ class NativeMovRegMem: public NativeInstruction {
|
||||
static void test() {}
|
||||
|
||||
private:
|
||||
int patch_offset() const;
|
||||
inline friend NativeMovRegMem* nativeMovRegMem_at (address address);
|
||||
};
|
||||
|
||||
|
@ -409,7 +409,7 @@ class PatchingStub: public CodeStub {
|
||||
if (_id == PatchingStub::access_field_id) {
|
||||
// embed a fixed offset to handle long patches which need to be offset by a word.
|
||||
// the patching code will just add the field offset field to this offset so
|
||||
// that we can refernce either the high or low word of a double word field.
|
||||
// that we can reference either the high or low word of a double word field.
|
||||
int field_offset = 0;
|
||||
switch (patch_code) {
|
||||
case lir_patch_low: field_offset = lo_word_offset_in_bytes; break;
|
||||
@ -419,6 +419,8 @@ class PatchingStub: public CodeStub {
|
||||
}
|
||||
NativeMovRegMem* n_move = nativeMovRegMem_at(pc_start());
|
||||
n_move->set_offset(field_offset);
|
||||
// Copy will never get executed, so only copy the part which is required for patching.
|
||||
_bytes_to_copy = MAX2(n_move->num_bytes_to_end_of_patch(), (int)NativeGeneralJump::instruction_size);
|
||||
} else if (_id == load_klass_id || _id == load_mirror_id || _id == load_appendix_id) {
|
||||
assert(_obj != noreg, "must have register object for load_klass/load_mirror");
|
||||
#ifdef ASSERT
|
||||
|
Loading…
x
Reference in New Issue
Block a user