src/cpu/x86/vm/x86_32.ad
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
8068945-8u-patched Cdiff src/cpu/x86/vm/x86_32.ad
src/cpu/x86/vm/x86_32.ad
Print this page
rev 7386 : 8068945: Use RBP register as proper frame pointer in JIT compiled code on x86
Summary: Introduce the PreserveFramePointer flag to control if RBP is used as the frame pointer or as a general purpose register.
Reviewed-by: kvn, roland, dlong, enevill, shade
*** 121,174 ****
// 1) reg_class inline_cache_reg ( /* as def'd in frame section */ )
// 2) reg_class compiler_method_oop_reg ( /* as def'd in frame section */ )
// 2) reg_class interpreter_method_oop_reg ( /* as def'd in frame section */ )
// 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ )
//
// Class for all registers
! reg_class any_reg(EAX, EDX, EBP, EDI, ESI, ECX, EBX, ESP);
// Class for general registers
! reg_class int_reg(EAX, EDX, EBP, EDI, ESI, ECX, EBX);
! // Class for general registers which may be used for implicit null checks on win95
! // Also safe for use by tailjump. We don't want to allocate in rbp,
! reg_class int_reg_no_rbp(EAX, EDX, EDI, ESI, ECX, EBX);
// Class of "X" registers
reg_class int_x_reg(EBX, ECX, EDX, EAX);
// Class of registers that can appear in an address with no offset.
// EBP and ESP require an extra instruction byte for zero offset.
// Used in fast-unlock
reg_class p_reg(EDX, EDI, ESI, EBX);
! // Class for general registers not including ECX
! reg_class ncx_reg(EAX, EDX, EBP, EDI, ESI, EBX);
! // Class for general registers not including EAX
reg_class nax_reg(EDX, EDI, ESI, ECX, EBX);
! // Class for general registers not including EAX or EBX.
! reg_class nabx_reg(EDX, EDI, ESI, ECX, EBP);
// Class of EAX (for multiply and divide operations)
reg_class eax_reg(EAX);
// Class of EBX (for atomic add)
reg_class ebx_reg(EBX);
// Class of ECX (for shift and JCXZ operations and cmpLTMask)
reg_class ecx_reg(ECX);
// Class of EDX (for multiply and divide operations)
reg_class edx_reg(EDX);
// Class of EDI (for synchronization)
reg_class edi_reg(EDI);
// Class of ESI (for synchronization)
reg_class esi_reg(ESI);
! // Singleton class for interpreter's stack pointer
! reg_class ebp_reg(EBP);
// Singleton class for stack pointer
reg_class sp_reg(ESP);
// Singleton class for instruction pointer
// reg_class ip_reg(EIP);
// Class of integer register pairs
! reg_class long_reg( EAX,EDX, ECX,EBX, EBP,EDI );
// Class of integer register pairs that aligns with calling convention
reg_class eadx_reg( EAX,EDX );
reg_class ebcx_reg( ECX,EBX );
// Not AX or DX, used in divides
! reg_class nadx_reg( EBX,ECX,ESI,EDI,EBP );
// Floating point registers. Notice FPR0 is not a choice.
// FPR0 is not ever allocated; we use clever encodings to fake
// a 2-address instructions out of Intels FP stack.
reg_class fp_flt_reg( FPR1L,FPR2L,FPR3L,FPR4L,FPR5L,FPR6L,FPR7L );
--- 121,218 ----
// 1) reg_class inline_cache_reg ( /* as def'd in frame section */ )
// 2) reg_class compiler_method_oop_reg ( /* as def'd in frame section */ )
// 2) reg_class interpreter_method_oop_reg ( /* as def'd in frame section */ )
// 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ )
//
+ // Class for no registers (empty set).
+ reg_class no_reg();
+
// Class for all registers
! reg_class any_reg_with_ebp(EAX, EDX, EBP, EDI, ESI, ECX, EBX, ESP);
! // Class for all registers (excluding EBP)
! reg_class any_reg_no_ebp(EAX, EDX, EDI, ESI, ECX, EBX, ESP);
! // Dynamic register class that selects at runtime between register classes
! // any_reg and any_no_ebp_reg (depending on the value of the flag PreserveFramePointer).
! // Equivalent to: return PreserveFramePointer ? any_no_ebp_reg : any_reg;
! reg_class_dynamic any_reg(any_reg_no_ebp, any_reg_with_ebp, %{ PreserveFramePointer %});
!
// Class for general registers
! reg_class int_reg_with_ebp(EAX, EDX, EBP, EDI, ESI, ECX, EBX);
! // Class for general registers (excluding EBP).
! // This register class can be used for implicit null checks on win95.
! // It is also safe for use by tailjumps (we don't want to allocate in ebp).
! // Used also if the PreserveFramePointer flag is true.
! reg_class int_reg_no_ebp(EAX, EDX, EDI, ESI, ECX, EBX);
! // Dynamic register class that selects between int_reg and int_reg_no_ebp.
! reg_class_dynamic int_reg(int_reg_no_ebp, int_reg_with_ebp, %{ PreserveFramePointer %});
!
// Class of "X" registers
reg_class int_x_reg(EBX, ECX, EDX, EAX);
+
// Class of registers that can appear in an address with no offset.
// EBP and ESP require an extra instruction byte for zero offset.
// Used in fast-unlock
reg_class p_reg(EDX, EDI, ESI, EBX);
!
! // Class for general registers excluding ECX
! reg_class ncx_reg_with_ebp(EAX, EDX, EBP, EDI, ESI, EBX);
! // Class for general registers excluding ECX (and EBP)
! reg_class ncx_reg_no_ebp(EAX, EDX, EDI, ESI, EBX);
! // Dynamic register class that selects between ncx_reg and ncx_reg_no_ebp.
! reg_class_dynamic ncx_reg(ncx_reg_no_ebp, ncx_reg_with_ebp, %{ PreserveFramePointer %});
!
! // Class for general registers excluding EAX
reg_class nax_reg(EDX, EDI, ESI, ECX, EBX);
!
! // Class for general registers excluding EAX and EBX.
! reg_class nabx_reg_with_ebp(EDX, EDI, ESI, ECX, EBP);
! // Class for general registers excluding EAX and EBX (and EBP)
! reg_class nabx_reg_no_ebp(EDX, EDI, ESI, ECX);
! // Dynamic register class that selects between nabx_reg and nabx_reg_no_ebp.
! reg_class_dynamic nabx_reg(nabx_reg_no_ebp, nabx_reg_with_ebp, %{ PreserveFramePointer %});
!
// Class of EAX (for multiply and divide operations)
reg_class eax_reg(EAX);
+
// Class of EBX (for atomic add)
reg_class ebx_reg(EBX);
+
// Class of ECX (for shift and JCXZ operations and cmpLTMask)
reg_class ecx_reg(ECX);
+
// Class of EDX (for multiply and divide operations)
reg_class edx_reg(EDX);
+
// Class of EDI (for synchronization)
reg_class edi_reg(EDI);
+
// Class of ESI (for synchronization)
reg_class esi_reg(ESI);
!
// Singleton class for stack pointer
reg_class sp_reg(ESP);
+
// Singleton class for instruction pointer
// reg_class ip_reg(EIP);
+
// Class of integer register pairs
! reg_class long_reg_with_ebp( EAX,EDX, ECX,EBX, EBP,EDI );
! // Class of integer register pairs (excluding EBP and EDI);
! reg_class long_reg_no_ebp( EAX,EDX, ECX,EBX );
! // Dynamic register class that selects between long_reg and long_reg_no_ebp.
! reg_class_dynamic long_reg(long_reg_no_ebp, long_reg_with_ebp, %{ PreserveFramePointer %});
!
// Class of integer register pairs that aligns with calling convention
reg_class eadx_reg( EAX,EDX );
reg_class ebcx_reg( ECX,EBX );
+
// Not AX or DX, used in divides
! reg_class nadx_reg_with_ebp(EBX, ECX, ESI, EDI, EBP);
! // Not AX or DX (and neither EBP), used in divides
! reg_class nadx_reg_no_ebp(EBX, ECX, ESI, EDI);
! // Dynamic register class that selects between nadx_reg and nadx_reg_no_ebp.
! reg_class_dynamic nadx_reg(nadx_reg_no_ebp, nadx_reg_with_ebp, %{ PreserveFramePointer %});
// Floating point registers. Notice FPR0 is not a choice.
// FPR0 is not ever allocated; we use clever encodings to fake
// a 2-address instructions out of Intels FP stack.
reg_class fp_flt_reg( FPR1L,FPR2L,FPR3L,FPR4L,FPR5L,FPR6L,FPR7L );
*** 238,259 ****
size += 3; // vzeroupper
}
return size;
}
- static int preserve_SP_size() {
- return 2; // op, rm(reg/reg)
- }
-
// !!!!! Special hack to get all type of calls to specify the byte offset
// from the start of the call to the point where the return address
// will point.
int MachCallStaticJavaNode::ret_addr_offset() {
! int offset = 5 + pre_call_resets_size(); // 5 bytes from start of call to where return address points
! if (_method_handle_invoke)
! offset += preserve_SP_size();
! return offset;
}
int MachCallDynamicJavaNode::ret_addr_offset() {
return 10 + pre_call_resets_size(); // 10 bytes from start of call to where return address points
}
--- 282,296 ----
size += 3; // vzeroupper
}
return size;
}
// !!!!! Special hack to get all type of calls to specify the byte offset
// from the start of the call to the point where the return address
// will point.
int MachCallStaticJavaNode::ret_addr_offset() {
! return 5 + pre_call_resets_size(); // 5 bytes from start of call to where return address points
}
int MachCallDynamicJavaNode::ret_addr_offset() {
return 10 + pre_call_resets_size(); // 10 bytes from start of call to where return address points
}
*** 283,301 ****
return round_to(current_offset, alignment_required()) - current_offset;
}
// The address of the call instruction needs to be 4-byte aligned to
// ensure that it does not span a cache line so that it can be patched.
- int CallStaticJavaHandleNode::compute_padding(int current_offset) const {
- current_offset += pre_call_resets_size(); // skip fldcw, if any
- current_offset += preserve_SP_size(); // skip mov rbp, rsp
- current_offset += 1; // skip call opcode byte
- return round_to(current_offset, alignment_required()) - current_offset;
- }
-
- // The address of the call instruction needs to be 4-byte aligned to
- // ensure that it does not span a cache line so that it can be patched.
int CallDynamicJavaDirectNode::compute_padding(int current_offset) const {
current_offset += pre_call_resets_size(); // skip fldcw, if any
current_offset += 5; // skip MOV instruction
current_offset += 1; // skip call opcode byte
return round_to(current_offset, alignment_required()) - current_offset;
--- 320,329 ----
*** 521,539 ****
--- 549,575 ----
if (C->need_stack_bang(bangsize)) {
framesize -= wordSize;
st->print("# stack bang (%d bytes)", bangsize);
st->print("\n\t");
st->print("PUSH EBP\t# Save EBP");
+ if (PreserveFramePointer) {
+ st->print("\n\t");
+ st->print("MOV EBP, ESP\t# Save the caller's SP into EBP");
+ }
if (framesize) {
st->print("\n\t");
st->print("SUB ESP, #%d\t# Create frame",framesize);
}
} else {
st->print("SUB ESP, #%d\t# Create frame",framesize);
st->print("\n\t");
framesize -= wordSize;
st->print("MOV [ESP + #%d], EBP\t# Save EBP",framesize);
+ if (PreserveFramePointer) {
+ st->print("\n\t");
+ st->print("MOV EBP, [ESP + #%d]\t# Save the caller's SP into EBP", (framesize + wordSize));
+ }
}
if (VerifyStackAtCalls) {
st->print("\n\t");
framesize -= wordSize;
*** 1486,1496 ****
ShouldNotReachHere();
return RegMask();
}
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
! return EBP_REG_mask();
}
// Returns true if the high 32 bits of the value is known to be zero.
bool is_operand_hi32_zero(Node* n) {
int opc = n->Opcode();
--- 1522,1532 ----
ShouldNotReachHere();
return RegMask();
}
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
! return NO_REG_mask();
}
// Returns true if the high 32 bits of the value is known to be zero.
bool is_operand_hi32_zero(Node* n) {
int opc = n->Opcode();
*** 3732,3742 ****
interface(REG_INTER);
%}
// On windows95, EBP is not safe to use for implicit null tests.
operand eRegP_no_EBP() %{
! constraint(ALLOC_IN_RC(int_reg_no_rbp));
match(RegP);
match(eAXRegP);
match(eBXRegP);
match(eCXRegP);
match(eDIRegP);
--- 3768,3778 ----
interface(REG_INTER);
%}
// On windows95, EBP is not safe to use for implicit null tests.
operand eRegP_no_EBP() %{
! constraint(ALLOC_IN_RC(int_reg_no_ebp));
match(RegP);
match(eAXRegP);
match(eBXRegP);
match(eCXRegP);
match(eDIRegP);
*** 3821,3837 ****
match(reg);
format %{ "EDI" %}
interface(REG_INTER);
%}
- operand eBPRegP() %{
- constraint(ALLOC_IN_RC(ebp_reg));
- match(RegP);
- format %{ "EBP" %}
- interface(REG_INTER);
- %}
-
operand eRegL() %{
constraint(ALLOC_IN_RC(long_reg));
match(RegL);
match(eADXRegL);
--- 3857,3866 ----
*** 12706,12716 ****
// Call Java Static Instruction
// Note: If this code changes, the corresponding ret_addr_offset() and
// compute_padding() functions will have to be adjusted.
instruct CallStaticJavaDirect(method meth) %{
match(CallStaticJava);
- predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
effect(USE meth);
ins_cost(300);
format %{ "CALL,static " %}
opcode(0xE8); /* E8 cd */
--- 12735,12744 ----
*** 12719,12751 ****
call_epilog,
post_call_FPU );
ins_pipe( pipe_slow );
ins_alignment(4);
%}
-
- // Call Java Static Instruction (method handle version)
- // Note: If this code changes, the corresponding ret_addr_offset() and
- // compute_padding() functions will have to be adjusted.
- instruct CallStaticJavaHandle(method meth, eBPRegP ebp_mh_SP_save) %{
- match(CallStaticJava);
- predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
- effect(USE meth);
- // EBP is saved by all callees (for interpreter stack correction).
- // We use it here for a similar purpose, in {preserve,restore}_SP.
-
- ins_cost(300);
- format %{ "CALL,static/MethodHandle " %}
- opcode(0xE8); /* E8 cd */
- ins_encode( pre_call_resets,
- preserve_SP,
- Java_Static_Call( meth ),
- restore_SP,
- call_epilog,
- post_call_FPU );
- ins_pipe( pipe_slow );
- ins_alignment(4);
- %}
// Call Java Dynamic Instruction
// Note: If this code changes, the corresponding ret_addr_offset() and
// compute_padding() functions will have to be adjusted.
instruct CallDynamicJavaDirect(method meth) %{
--- 12747,12756 ----
src/cpu/x86/vm/x86_32.ad
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File