7145346: VerifyStackAtCalls is broken
Replace call_epilog() encoding with macroassembler use. Moved duplicated code to x86.ad. Fixed return_addr() definition. Reviewed-by: never
This commit is contained in:
parent
9e339b8ded
commit
867f3ba889
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -37,10 +37,87 @@ source %{
|
||||
static address double_signmask() { return (address)double_signmask_pool; }
|
||||
static address double_signflip() { return (address)double_signflip_pool; }
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
void MachNopNode::format(PhaseRegAlloc*, outputStream* st) const {
|
||||
st->print("nop \t# %d bytes pad for loops and calls", _count);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc*) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
__ nop(_count);
|
||||
}
|
||||
|
||||
uint MachNopNode::size(PhaseRegAlloc*) const {
|
||||
return _count;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void MachBreakpointNode::format(PhaseRegAlloc*, outputStream* st) const {
|
||||
st->print("# breakpoint");
|
||||
}
|
||||
#endif
|
||||
|
||||
void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc* ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
__ int3();
|
||||
}
|
||||
|
||||
uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const {
|
||||
return MachNode::size(ra_);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
encode %{
|
||||
|
||||
enc_class preserve_SP %{
|
||||
debug_only(int off0 = cbuf.insts_size());
|
||||
MacroAssembler _masm(&cbuf);
|
||||
// RBP is preserved across all calls, even compiled calls.
|
||||
// Use it to preserve RSP in places where the callee might change the SP.
|
||||
__ movptr(rbp_mh_SP_save, rsp);
|
||||
debug_only(int off1 = cbuf.insts_size());
|
||||
assert(off1 - off0 == preserve_SP_size(), "correct size prediction");
|
||||
%}
|
||||
|
||||
enc_class restore_SP %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
__ movptr(rsp, rbp_mh_SP_save);
|
||||
%}
|
||||
|
||||
enc_class call_epilog %{
|
||||
if (VerifyStackAtCalls) {
|
||||
// Check that stack depth is unchanged: find majik cookie on stack
|
||||
int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word));
|
||||
MacroAssembler _masm(&cbuf);
|
||||
Label L;
|
||||
__ cmpptr(Address(rsp, framesize), (int32_t)0xbadb100d);
|
||||
__ jccb(Assembler::equal, L);
|
||||
// Die if stack mismatch
|
||||
__ int3();
|
||||
__ bind(L);
|
||||
}
|
||||
%}
|
||||
|
||||
%}
|
||||
|
||||
// INSTRUCTIONS -- Platform independent definitions (same for 32- and 64-bit)
|
||||
|
||||
// ============================================================================
|
||||
|
||||
instruct ShouldNotReachHere() %{
|
||||
match(Halt);
|
||||
format %{ "int3\t# ShouldNotReachHere" %}
|
||||
ins_encode %{
|
||||
__ int3();
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
instruct addF_reg(regF dst, regF src) %{
|
||||
predicate((UseSSE>=1) && (UseAVX == 0));
|
||||
match(Set dst (AddF dst src));
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -341,12 +341,6 @@ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const {
|
||||
return round_to(current_offset, alignment_required()) - current_offset;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void MachBreakpointNode::format( PhaseRegAlloc *, outputStream* st ) const {
|
||||
st->print("INT3");
|
||||
}
|
||||
#endif
|
||||
|
||||
// EMIT_RM()
|
||||
void emit_rm(CodeBuffer &cbuf, int f1, int f2, int f3) {
|
||||
unsigned char c = (unsigned char)((f1 << 6) | (f2 << 3) | f3);
|
||||
@ -1130,22 +1124,6 @@ uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
|
||||
return implementation( NULL, ra_, true, NULL );
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
#ifndef PRODUCT
|
||||
void MachNopNode::format( PhaseRegAlloc *, outputStream* st ) const {
|
||||
st->print("NOP \t# %d bytes pad for loops and calls", _count);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
__ nop(_count);
|
||||
}
|
||||
|
||||
uint MachNopNode::size(PhaseRegAlloc *) const {
|
||||
return _count;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
#ifndef PRODUCT
|
||||
@ -1831,21 +1809,6 @@ encode %{
|
||||
}
|
||||
%}
|
||||
|
||||
enc_class preserve_SP %{
|
||||
debug_only(int off0 = cbuf.insts_size());
|
||||
MacroAssembler _masm(&cbuf);
|
||||
// RBP is preserved across all calls, even compiled calls.
|
||||
// Use it to preserve RSP in places where the callee might change the SP.
|
||||
__ movptr(rbp_mh_SP_save, rsp);
|
||||
debug_only(int off1 = cbuf.insts_size());
|
||||
assert(off1 - off0 == preserve_SP_size(), "correct size prediction");
|
||||
%}
|
||||
|
||||
enc_class restore_SP %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
__ movptr(rsp, rbp_mh_SP_save);
|
||||
%}
|
||||
|
||||
enc_class Java_Static_Call (method meth) %{ // JAVA STATIC CALL
|
||||
// CALL to fixup routine. Fixup routine uses ScopeDesc info to determine
|
||||
// who we intended to call.
|
||||
@ -3794,9 +3757,9 @@ frame %{
|
||||
// Ret Addr is on stack in slot 0 if no locks or verification or alignment.
|
||||
// Otherwise, it is above the locks and verification slot and alignment word
|
||||
return_addr(STACK - 1 +
|
||||
round_to(1+VerifyStackAtCalls+
|
||||
Compile::current()->fixed_slots(),
|
||||
(StackAlignmentInBytes/wordSize)));
|
||||
round_to((Compile::current()->in_preserve_stack_slots() +
|
||||
Compile::current()->fixed_slots()),
|
||||
stack_alignment_in_slots()));
|
||||
|
||||
// Body of function which returns an integer array locating
|
||||
// arguments either in registers or in stack slots. Passed an array
|
||||
@ -13424,6 +13387,25 @@ instruct safePoint_poll(eFlagsReg cr) %{
|
||||
ins_pipe( ialu_reg_mem );
|
||||
%}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// This name is KNOWN by the ADLC and cannot be changed.
|
||||
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
|
||||
// for this guy.
|
||||
instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{
|
||||
match(Set dst (ThreadLocal));
|
||||
effect(DEF dst, KILL cr);
|
||||
|
||||
format %{ "MOV $dst, Thread::current()" %}
|
||||
ins_encode %{
|
||||
Register dstReg = as_Register($dst$$reg);
|
||||
__ get_thread(dstReg);
|
||||
%}
|
||||
ins_pipe( ialu_reg_fat );
|
||||
%}
|
||||
|
||||
|
||||
|
||||
//----------PEEPHOLE RULES-----------------------------------------------------
|
||||
// These must follow all instruction definitions as they use the names
|
||||
// defined in the instructions definitions.
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -610,13 +610,6 @@ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
|
||||
return round_to(current_offset, alignment_required()) - current_offset;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void MachBreakpointNode::format(PhaseRegAlloc*, outputStream* st) const
|
||||
{
|
||||
st->print("INT3");
|
||||
}
|
||||
#endif
|
||||
|
||||
// EMIT_RM()
|
||||
void emit_rm(CodeBuffer &cbuf, int f1, int f2, int f3) {
|
||||
unsigned char c = (unsigned char) ((f1 << 6) | (f2 << 3) | f3);
|
||||
@ -1528,26 +1521,6 @@ uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const
|
||||
return implementation(NULL, ra_, true, NULL);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
#ifndef PRODUCT
|
||||
void MachNopNode::format(PhaseRegAlloc*, outputStream* st) const
|
||||
{
|
||||
st->print("nop \t# %d bytes pad for loops and calls", _count);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc*) const
|
||||
{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
__ nop(_count);
|
||||
}
|
||||
|
||||
uint MachNopNode::size(PhaseRegAlloc*) const
|
||||
{
|
||||
return _count;
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
#ifndef PRODUCT
|
||||
void BoxLockNode::format(PhaseRegAlloc* ra_, outputStream* st) const
|
||||
@ -2255,21 +2228,6 @@ encode %{
|
||||
RELOC_DISP32);
|
||||
%}
|
||||
|
||||
enc_class preserve_SP %{
|
||||
debug_only(int off0 = cbuf.insts_size());
|
||||
MacroAssembler _masm(&cbuf);
|
||||
// RBP is preserved across all calls, even compiled calls.
|
||||
// Use it to preserve RSP in places where the callee might change the SP.
|
||||
__ movptr(rbp_mh_SP_save, rsp);
|
||||
debug_only(int off1 = cbuf.insts_size());
|
||||
assert(off1 - off0 == preserve_SP_size(), "correct size prediction");
|
||||
%}
|
||||
|
||||
enc_class restore_SP %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
__ movptr(rsp, rbp_mh_SP_save);
|
||||
%}
|
||||
|
||||
enc_class Java_Static_Call(method meth)
|
||||
%{
|
||||
// JAVA STATIC CALL
|
||||
@ -3208,9 +3166,9 @@ frame
|
||||
// Ret Addr is on stack in slot 0 if no locks or verification or alignment.
|
||||
// Otherwise, it is above the locks and verification slot and alignment word
|
||||
return_addr(STACK - 2 +
|
||||
round_to(2 + 2 * VerifyStackAtCalls +
|
||||
Compile::current()->fixed_slots(),
|
||||
WordsPerLong * 2));
|
||||
round_to((Compile::current()->in_preserve_stack_slots() +
|
||||
Compile::current()->fixed_slots()),
|
||||
stack_alignment_in_slots()));
|
||||
|
||||
// Body of function which returns an integer array locating
|
||||
// arguments either in registers or in stack slots. Passed an array
|
||||
@ -11668,6 +11626,21 @@ instruct RethrowException()
|
||||
%}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// This name is KNOWN by the ADLC and cannot be changed.
|
||||
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
|
||||
// for this guy.
|
||||
instruct tlsLoadP(r15_RegP dst) %{
|
||||
match(Set dst (ThreadLocal));
|
||||
effect(DEF dst);
|
||||
|
||||
size(0);
|
||||
format %{ "# TLS is in R15" %}
|
||||
ins_encode( /*empty encoding*/ );
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
|
||||
|
||||
//----------PEEPHOLE RULES-----------------------------------------------------
|
||||
// These must follow all instruction definitions as they use the names
|
||||
// defined in the instructions definitions.
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,137 +24,3 @@
|
||||
|
||||
// X86 Bsd Architecture Description File
|
||||
|
||||
//----------OS-DEPENDENT ENCODING BLOCK-----------------------------------------------------
|
||||
// This block specifies the encoding classes used by the compiler to output
|
||||
// byte streams. Encoding classes generate functions which are called by
|
||||
// Machine Instruction Nodes in order to generate the bit encoding of the
|
||||
// instruction. Operands specify their base encoding interface with the
|
||||
// interface keyword. There are currently supported four interfaces,
|
||||
// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an
|
||||
// operand to generate a function which returns its register number when
|
||||
// queried. CONST_INTER causes an operand to generate a function which
|
||||
// returns the value of the constant when queried. MEMORY_INTER causes an
|
||||
// operand to generate four functions which return the Base Register, the
|
||||
// Index Register, the Scale Value, and the Offset Value of the operand when
|
||||
// queried. COND_INTER causes an operand to generate six functions which
|
||||
// return the encoding code (ie - encoding bits for the instruction)
|
||||
// associated with each basic boolean condition for a conditional instruction.
|
||||
// Instructions specify two basic values for encoding. They use the
|
||||
// ins_encode keyword to specify their encoding class (which must be one of
|
||||
// the class names specified in the encoding block), and they use the
|
||||
// opcode keyword to specify, in order, their primary, secondary, and
|
||||
// tertiary opcode. Only the opcode sections which a particular instruction
|
||||
// needs for encoding need to be specified.
|
||||
encode %{
|
||||
// Build emit functions for each basic byte or larger field in the intel
|
||||
// encoding scheme (opcode, rm, sib, immediate), and call them from C++
|
||||
// code in the enc_class source block. Emit functions will live in the
|
||||
// main source block for now. In future, we can generalize this by
|
||||
// adding a syntax that specifies the sizes of fields in an order,
|
||||
// so that the adlc can build the emit functions automagically
|
||||
|
||||
enc_class bsd_tlsencode (eRegP dst) %{
|
||||
Register dstReg = as_Register($dst$$reg);
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->get_thread(dstReg);
|
||||
%}
|
||||
|
||||
enc_class bsd_breakpoint %{
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
|
||||
%}
|
||||
|
||||
enc_class call_epilog %{
|
||||
if( VerifyStackAtCalls ) {
|
||||
// Check that stack depth is unchanged: find majik cookie on stack
|
||||
int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP,-3*VMRegImpl::slots_per_word));
|
||||
if(framesize >= 128) {
|
||||
emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood
|
||||
emit_d8(cbuf,0xBC);
|
||||
emit_d8(cbuf,0x24);
|
||||
emit_d32(cbuf,framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
}
|
||||
else {
|
||||
emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood
|
||||
emit_d8(cbuf,0x7C);
|
||||
emit_d8(cbuf,0x24);
|
||||
emit_d8(cbuf,framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
}
|
||||
// jmp EQ around INT3
|
||||
// QQQ TODO
|
||||
const int jump_around = 5; // size of call to breakpoint, 1 for CC
|
||||
emit_opcode(cbuf,0x74);
|
||||
emit_d8(cbuf, jump_around);
|
||||
// QQQ temporary
|
||||
emit_break(cbuf);
|
||||
// Die if stack mismatch
|
||||
// emit_opcode(cbuf,0xCC);
|
||||
}
|
||||
%}
|
||||
|
||||
%}
|
||||
|
||||
// INSTRUCTIONS -- Platform dependent
|
||||
|
||||
//----------OS and Locking Instructions----------------------------------------
|
||||
|
||||
// This name is KNOWN by the ADLC and cannot be changed.
|
||||
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
|
||||
// for this guy.
|
||||
instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{
|
||||
match(Set dst (ThreadLocal));
|
||||
effect(DEF dst, KILL cr);
|
||||
|
||||
format %{ "MOV $dst, Thread::current()" %}
|
||||
ins_encode( bsd_tlsencode(dst) );
|
||||
ins_pipe( ialu_reg_fat );
|
||||
%}
|
||||
|
||||
instruct TLS(eRegP dst) %{
|
||||
match(Set dst (ThreadLocal));
|
||||
|
||||
expand %{
|
||||
tlsLoadP(dst);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Die now
|
||||
instruct ShouldNotReachHere( )
|
||||
%{
|
||||
match(Halt);
|
||||
|
||||
// Use the following format syntax
|
||||
format %{ "INT3 ; ShouldNotReachHere" %}
|
||||
// QQQ TODO for now call breakpoint
|
||||
// opcode(0xCC);
|
||||
// ins_encode(Opc);
|
||||
ins_encode(bsd_breakpoint);
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
|
||||
|
||||
// Platform dependent source
|
||||
|
||||
source %{
|
||||
|
||||
// emit an interrupt that is caught by the debugger
|
||||
void emit_break(CodeBuffer &cbuf) {
|
||||
|
||||
// Debugger doesn't really catch this but best we can do so far QQQ
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
|
||||
}
|
||||
|
||||
void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
emit_break(cbuf);
|
||||
}
|
||||
|
||||
|
||||
uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
|
||||
return 5;
|
||||
}
|
||||
|
||||
%}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -55,8 +55,7 @@ encode %{
|
||||
// adding a syntax that specifies the sizes of fields in an order,
|
||||
// so that the adlc can build the emit functions automagically
|
||||
|
||||
enc_class Java_To_Runtime(method meth)
|
||||
%{
|
||||
enc_class Java_To_Runtime(method meth) %{
|
||||
// No relocation needed
|
||||
|
||||
// movq r10, <meth>
|
||||
@ -70,104 +69,15 @@ encode %{
|
||||
emit_opcode(cbuf, 0xD0 | (R10_enc - 8));
|
||||
%}
|
||||
|
||||
enc_class bsd_breakpoint
|
||||
%{
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
|
||||
%}
|
||||
|
||||
enc_class call_epilog
|
||||
%{
|
||||
if (VerifyStackAtCalls) {
|
||||
// Check that stack depth is unchanged: find majik cookie on stack
|
||||
int framesize =
|
||||
ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word));
|
||||
if (framesize) {
|
||||
if (framesize < 0x80) {
|
||||
emit_opcode(cbuf, Assembler::REX_W);
|
||||
emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood
|
||||
emit_d8(cbuf, 0x7C);
|
||||
emit_d8(cbuf, 0x24);
|
||||
emit_d8(cbuf, framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
} else {
|
||||
emit_opcode(cbuf, Assembler::REX_W);
|
||||
emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood
|
||||
emit_d8(cbuf, 0xBC);
|
||||
emit_d8(cbuf, 0x24);
|
||||
emit_d32(cbuf, framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
}
|
||||
}
|
||||
// jmp EQ around INT3
|
||||
// QQQ TODO
|
||||
const int jump_around = 5; // size of call to breakpoint, 1 for CC
|
||||
emit_opcode(cbuf, 0x74);
|
||||
emit_d8(cbuf, jump_around);
|
||||
// QQQ temporary
|
||||
emit_break(cbuf);
|
||||
// Die if stack mismatch
|
||||
// emit_opcode(cbuf,0xCC);
|
||||
}
|
||||
%}
|
||||
|
||||
%}
|
||||
|
||||
// INSTRUCTIONS -- Platform dependent
|
||||
|
||||
//----------OS and Locking Instructions----------------------------------------
|
||||
|
||||
// This name is KNOWN by the ADLC and cannot be changed.
|
||||
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
|
||||
// for this guy.
|
||||
instruct tlsLoadP(r15_RegP dst)
|
||||
%{
|
||||
match(Set dst (ThreadLocal));
|
||||
effect(DEF dst);
|
||||
|
||||
size(0);
|
||||
format %{ "# TLS is in R15" %}
|
||||
ins_encode( /*empty encoding*/ );
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
|
||||
// Die now
|
||||
instruct ShouldNotReachHere()
|
||||
%{
|
||||
match(Halt);
|
||||
|
||||
// Use the following format syntax
|
||||
format %{ "int3\t# ShouldNotReachHere" %}
|
||||
// QQQ TODO for now call breakpoint
|
||||
// opcode(0xCC);
|
||||
// ins_encode(Opc);
|
||||
ins_encode(bsd_breakpoint);
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
|
||||
// Platform dependent source
|
||||
|
||||
source
|
||||
%{
|
||||
source %{
|
||||
|
||||
int MachCallRuntimeNode::ret_addr_offset() {
|
||||
return 13; // movq r10,#addr; callq (r10)
|
||||
}
|
||||
|
||||
// emit an interrupt that is caught by the debugger
|
||||
void emit_break(CodeBuffer& cbuf) {
|
||||
// Debugger doesn't really catch this but best we can do so far QQQ
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
|
||||
}
|
||||
|
||||
void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
||||
emit_break(cbuf);
|
||||
}
|
||||
|
||||
uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const {
|
||||
return 5;
|
||||
}
|
||||
|
||||
%}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,137 +24,3 @@
|
||||
|
||||
// X86 Linux Architecture Description File
|
||||
|
||||
//----------OS-DEPENDENT ENCODING BLOCK-----------------------------------------------------
|
||||
// This block specifies the encoding classes used by the compiler to output
|
||||
// byte streams. Encoding classes generate functions which are called by
|
||||
// Machine Instruction Nodes in order to generate the bit encoding of the
|
||||
// instruction. Operands specify their base encoding interface with the
|
||||
// interface keyword. There are currently supported four interfaces,
|
||||
// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an
|
||||
// operand to generate a function which returns its register number when
|
||||
// queried. CONST_INTER causes an operand to generate a function which
|
||||
// returns the value of the constant when queried. MEMORY_INTER causes an
|
||||
// operand to generate four functions which return the Base Register, the
|
||||
// Index Register, the Scale Value, and the Offset Value of the operand when
|
||||
// queried. COND_INTER causes an operand to generate six functions which
|
||||
// return the encoding code (ie - encoding bits for the instruction)
|
||||
// associated with each basic boolean condition for a conditional instruction.
|
||||
// Instructions specify two basic values for encoding. They use the
|
||||
// ins_encode keyword to specify their encoding class (which must be one of
|
||||
// the class names specified in the encoding block), and they use the
|
||||
// opcode keyword to specify, in order, their primary, secondary, and
|
||||
// tertiary opcode. Only the opcode sections which a particular instruction
|
||||
// needs for encoding need to be specified.
|
||||
encode %{
|
||||
// Build emit functions for each basic byte or larger field in the intel
|
||||
// encoding scheme (opcode, rm, sib, immediate), and call them from C++
|
||||
// code in the enc_class source block. Emit functions will live in the
|
||||
// main source block for now. In future, we can generalize this by
|
||||
// adding a syntax that specifies the sizes of fields in an order,
|
||||
// so that the adlc can build the emit functions automagically
|
||||
|
||||
enc_class linux_tlsencode (eRegP dst) %{
|
||||
Register dstReg = as_Register($dst$$reg);
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->get_thread(dstReg);
|
||||
%}
|
||||
|
||||
enc_class linux_breakpoint %{
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
|
||||
%}
|
||||
|
||||
enc_class call_epilog %{
|
||||
if( VerifyStackAtCalls ) {
|
||||
// Check that stack depth is unchanged: find majik cookie on stack
|
||||
int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP,-3*VMRegImpl::slots_per_word));
|
||||
if(framesize >= 128) {
|
||||
emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood
|
||||
emit_d8(cbuf,0xBC);
|
||||
emit_d8(cbuf,0x24);
|
||||
emit_d32(cbuf,framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
}
|
||||
else {
|
||||
emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood
|
||||
emit_d8(cbuf,0x7C);
|
||||
emit_d8(cbuf,0x24);
|
||||
emit_d8(cbuf,framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
}
|
||||
// jmp EQ around INT3
|
||||
// QQQ TODO
|
||||
const int jump_around = 5; // size of call to breakpoint, 1 for CC
|
||||
emit_opcode(cbuf,0x74);
|
||||
emit_d8(cbuf, jump_around);
|
||||
// QQQ temporary
|
||||
emit_break(cbuf);
|
||||
// Die if stack mismatch
|
||||
// emit_opcode(cbuf,0xCC);
|
||||
}
|
||||
%}
|
||||
|
||||
%}
|
||||
|
||||
// INSTRUCTIONS -- Platform dependent
|
||||
|
||||
//----------OS and Locking Instructions----------------------------------------
|
||||
|
||||
// This name is KNOWN by the ADLC and cannot be changed.
|
||||
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
|
||||
// for this guy.
|
||||
instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{
|
||||
match(Set dst (ThreadLocal));
|
||||
effect(DEF dst, KILL cr);
|
||||
|
||||
format %{ "MOV $dst, Thread::current()" %}
|
||||
ins_encode( linux_tlsencode(dst) );
|
||||
ins_pipe( ialu_reg_fat );
|
||||
%}
|
||||
|
||||
instruct TLS(eRegP dst) %{
|
||||
match(Set dst (ThreadLocal));
|
||||
|
||||
expand %{
|
||||
tlsLoadP(dst);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Die now
|
||||
instruct ShouldNotReachHere( )
|
||||
%{
|
||||
match(Halt);
|
||||
|
||||
// Use the following format syntax
|
||||
format %{ "INT3 ; ShouldNotReachHere" %}
|
||||
// QQQ TODO for now call breakpoint
|
||||
// opcode(0xCC);
|
||||
// ins_encode(Opc);
|
||||
ins_encode(linux_breakpoint);
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
|
||||
|
||||
// Platform dependent source
|
||||
|
||||
source %{
|
||||
|
||||
// emit an interrupt that is caught by the debugger
|
||||
void emit_break(CodeBuffer &cbuf) {
|
||||
|
||||
// Debugger doesn't really catch this but best we can do so far QQQ
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
|
||||
}
|
||||
|
||||
void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
emit_break(cbuf);
|
||||
}
|
||||
|
||||
|
||||
uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
|
||||
return MachNode::size(ra_);
|
||||
}
|
||||
|
||||
%}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -55,8 +55,7 @@ encode %{
|
||||
// adding a syntax that specifies the sizes of fields in an order,
|
||||
// so that the adlc can build the emit functions automagically
|
||||
|
||||
enc_class Java_To_Runtime(method meth)
|
||||
%{
|
||||
enc_class Java_To_Runtime(method meth) %{
|
||||
// No relocation needed
|
||||
|
||||
// movq r10, <meth>
|
||||
@ -70,105 +69,15 @@ encode %{
|
||||
emit_opcode(cbuf, 0xD0 | (R10_enc - 8));
|
||||
%}
|
||||
|
||||
enc_class linux_breakpoint
|
||||
%{
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
|
||||
%}
|
||||
|
||||
enc_class call_epilog
|
||||
%{
|
||||
if (VerifyStackAtCalls) {
|
||||
// Check that stack depth is unchanged: find majik cookie on stack
|
||||
int framesize =
|
||||
ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word));
|
||||
if (framesize) {
|
||||
if (framesize < 0x80) {
|
||||
emit_opcode(cbuf, Assembler::REX_W);
|
||||
emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood
|
||||
emit_d8(cbuf, 0x7C);
|
||||
emit_d8(cbuf, 0x24);
|
||||
emit_d8(cbuf, framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
} else {
|
||||
emit_opcode(cbuf, Assembler::REX_W);
|
||||
emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood
|
||||
emit_d8(cbuf, 0xBC);
|
||||
emit_d8(cbuf, 0x24);
|
||||
emit_d32(cbuf, framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
}
|
||||
}
|
||||
// jmp EQ around INT3
|
||||
// QQQ TODO
|
||||
const int jump_around = 5; // size of call to breakpoint, 1 for CC
|
||||
emit_opcode(cbuf, 0x74);
|
||||
emit_d8(cbuf, jump_around);
|
||||
// QQQ temporary
|
||||
emit_break(cbuf);
|
||||
// Die if stack mismatch
|
||||
// emit_opcode(cbuf,0xCC);
|
||||
}
|
||||
%}
|
||||
|
||||
%}
|
||||
|
||||
// INSTRUCTIONS -- Platform dependent
|
||||
|
||||
//----------OS and Locking Instructions----------------------------------------
|
||||
|
||||
// This name is KNOWN by the ADLC and cannot be changed.
|
||||
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
|
||||
// for this guy.
|
||||
instruct tlsLoadP(r15_RegP dst)
|
||||
%{
|
||||
match(Set dst (ThreadLocal));
|
||||
effect(DEF dst);
|
||||
|
||||
size(0);
|
||||
format %{ "# TLS is in R15" %}
|
||||
ins_encode( /*empty encoding*/ );
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
|
||||
// Die now
|
||||
instruct ShouldNotReachHere()
|
||||
%{
|
||||
match(Halt);
|
||||
|
||||
// Use the following format syntax
|
||||
format %{ "int3\t# ShouldNotReachHere" %}
|
||||
// QQQ TODO for now call breakpoint
|
||||
// opcode(0xCC);
|
||||
// ins_encode(Opc);
|
||||
ins_encode(linux_breakpoint);
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
|
||||
// Platform dependent source
|
||||
|
||||
source
|
||||
%{
|
||||
source %{
|
||||
|
||||
int MachCallRuntimeNode::ret_addr_offset() {
|
||||
return 13; // movq r10,#addr; callq (r10)
|
||||
}
|
||||
|
||||
// emit an interrupt that is caught by the debugger
|
||||
void emit_break(CodeBuffer& cbuf) {
|
||||
// Debugger doesn't really catch this but best we can do so far QQQ
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
|
||||
}
|
||||
|
||||
void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
||||
emit_break(cbuf);
|
||||
}
|
||||
|
||||
uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const {
|
||||
// distance could be far and requires load and call through register
|
||||
return MachNode::size(ra_);
|
||||
}
|
||||
|
||||
%}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,144 +24,3 @@
|
||||
|
||||
// X86 Solaris Architecture Description File
|
||||
|
||||
//----------OS-DEPENDENT ENCODING BLOCK-----------------------------------------------------
|
||||
// This block specifies the encoding classes used by the compiler to output
|
||||
// byte streams. Encoding classes generate functions which are called by
|
||||
// Machine Instruction Nodes in order to generate the bit encoding of the
|
||||
// instruction. Operands specify their base encoding interface with the
|
||||
// interface keyword. There are currently supported four interfaces,
|
||||
// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an
|
||||
// operand to generate a function which returns its register number when
|
||||
// queried. CONST_INTER causes an operand to generate a function which
|
||||
// returns the value of the constant when queried. MEMORY_INTER causes an
|
||||
// operand to generate four functions which return the Base Register, the
|
||||
// Index Register, the Scale Value, and the Offset Value of the operand when
|
||||
// queried. COND_INTER causes an operand to generate six functions which
|
||||
// return the encoding code (ie - encoding bits for the instruction)
|
||||
// associated with each basic boolean condition for a conditional instruction.
|
||||
// Instructions specify two basic values for encoding. They use the
|
||||
// ins_encode keyword to specify their encoding class (which must be one of
|
||||
// the class names specified in the encoding block), and they use the
|
||||
// opcode keyword to specify, in order, their primary, secondary, and
|
||||
// tertiary opcode. Only the opcode sections which a particular instruction
|
||||
// needs for encoding need to be specified.
|
||||
encode %{
|
||||
// Build emit functions for each basic byte or larger field in the intel
|
||||
// encoding scheme (opcode, rm, sib, immediate), and call them from C++
|
||||
// code in the enc_class source block. Emit functions will live in the
|
||||
// main source block for now. In future, we can generalize this by
|
||||
// adding a syntax that specifies the sizes of fields in an order,
|
||||
// so that the adlc can build the emit functions automagically
|
||||
|
||||
enc_class solaris_tlsencode (eRegP dst) %{
|
||||
Register dstReg = as_Register($dst$$reg);
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->get_thread(dstReg);
|
||||
%}
|
||||
|
||||
enc_class solaris_breakpoint %{
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
// Really need to fix this
|
||||
masm->push(rax);
|
||||
masm->push(rcx);
|
||||
masm->push(rdx);
|
||||
masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
|
||||
masm->pop(rdx);
|
||||
masm->pop(rcx);
|
||||
masm->pop(rax);
|
||||
%}
|
||||
|
||||
enc_class call_epilog %{
|
||||
if( VerifyStackAtCalls ) {
|
||||
// Check that stack depth is unchanged: find majik cookie on stack
|
||||
int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP,-3*VMRegImpl::slots_per_word));
|
||||
if(framesize >= 128) {
|
||||
emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood
|
||||
emit_d8(cbuf,0xBC);
|
||||
emit_d8(cbuf,0x24);
|
||||
emit_d32(cbuf,framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
}
|
||||
else {
|
||||
emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood
|
||||
emit_d8(cbuf,0x7C);
|
||||
emit_d8(cbuf,0x24);
|
||||
emit_d8(cbuf,framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
}
|
||||
// jmp EQ around INT3
|
||||
// QQQ TODO
|
||||
const int jump_around = 11; // size of call to breakpoint (and register preserve), 1 for CC
|
||||
emit_opcode(cbuf,0x74);
|
||||
emit_d8(cbuf, jump_around);
|
||||
// QQQ temporary
|
||||
emit_break(cbuf);
|
||||
// Die if stack mismatch
|
||||
// emit_opcode(cbuf,0xCC);
|
||||
}
|
||||
%}
|
||||
|
||||
%}
|
||||
|
||||
// INSTRUCTIONS -- Platform dependent
|
||||
|
||||
//----------OS and Locking Instructions----------------------------------------
|
||||
|
||||
// This name is KNOWN by the ADLC and cannot be changed.
|
||||
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
|
||||
// for this guy.
|
||||
instruct tlsLoadP(eRegP dst, eFlagsReg cr) %{
|
||||
match(Set dst (ThreadLocal));
|
||||
effect(DEF dst, KILL cr);
|
||||
|
||||
format %{ "MOV $dst, Thread::current()" %}
|
||||
ins_encode( solaris_tlsencode(dst) );
|
||||
ins_pipe( ialu_reg_fat );
|
||||
%}
|
||||
|
||||
instruct TLS(eRegP dst) %{
|
||||
match(Set dst (ThreadLocal));
|
||||
|
||||
expand %{
|
||||
tlsLoadP(dst);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Die now
|
||||
instruct ShouldNotReachHere( )
|
||||
%{
|
||||
match(Halt);
|
||||
|
||||
// Use the following format syntax
|
||||
format %{ "INT3 ; ShouldNotReachHere" %}
|
||||
// QQQ TODO for now call breakpoint
|
||||
// opcode(0xCC);
|
||||
// ins_encode(Opc);
|
||||
ins_encode(solaris_breakpoint);
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
|
||||
|
||||
// Platform dependent source
|
||||
|
||||
source %{
|
||||
|
||||
// emit an interrupt that is caught by the debugger
|
||||
void emit_break(CodeBuffer &cbuf) {
|
||||
|
||||
// Debugger doesn't really catch this but best we can do so far QQQ
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
|
||||
}
|
||||
|
||||
void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
emit_break(cbuf);
|
||||
}
|
||||
|
||||
|
||||
uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
|
||||
return MachNode::size(ra_);
|
||||
}
|
||||
|
||||
%}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -55,8 +55,7 @@ encode %{
|
||||
// adding a syntax that specifies the sizes of fields in an order,
|
||||
// so that the adlc can build the emit functions automagically
|
||||
|
||||
enc_class Java_To_Runtime(method meth)
|
||||
%{
|
||||
enc_class Java_To_Runtime(method meth) %{
|
||||
// No relocation needed
|
||||
|
||||
// movq r10, <meth>
|
||||
@ -70,118 +69,24 @@ encode %{
|
||||
emit_opcode(cbuf, 0xD0 | (R10_enc - 8));
|
||||
%}
|
||||
|
||||
enc_class solaris_breakpoint
|
||||
%{
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
|
||||
%}
|
||||
|
||||
enc_class call_epilog
|
||||
%{
|
||||
if (VerifyStackAtCalls) {
|
||||
// Check that stack depth is unchanged: find majik cookie on stack
|
||||
int framesize =
|
||||
ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word));
|
||||
if (framesize) {
|
||||
if (framesize < 0x80) {
|
||||
emit_opcode(cbuf, Assembler::REX_W);
|
||||
emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood
|
||||
emit_d8(cbuf, 0x7C);
|
||||
emit_d8(cbuf, 0x24);
|
||||
emit_d8(cbuf, framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
} else {
|
||||
emit_opcode(cbuf, Assembler::REX_W);
|
||||
emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood
|
||||
emit_d8(cbuf, 0xBC);
|
||||
emit_d8(cbuf, 0x24);
|
||||
emit_d32(cbuf, framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
}
|
||||
}
|
||||
// jmp EQ around INT3
|
||||
// QQQ TODO
|
||||
const int jump_around = 5; // size of call to breakpoint, 1 for CC
|
||||
emit_opcode(cbuf, 0x74);
|
||||
emit_d8(cbuf, jump_around);
|
||||
// QQQ temporary
|
||||
emit_break(cbuf);
|
||||
// Die if stack mismatch
|
||||
// emit_opcode(cbuf,0xCC);
|
||||
}
|
||||
%}
|
||||
|
||||
enc_class post_call_verify_mxcsr %{
|
||||
MacroAssembler masm(&cbuf);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
if (RestoreMXCSROnJNICalls) {
|
||||
masm.ldmxcsr(ExternalAddress(StubRoutines::amd64::mxcsr_std()));
|
||||
__ ldmxcsr(ExternalAddress(StubRoutines::amd64::mxcsr_std()));
|
||||
}
|
||||
else if (CheckJNICalls) {
|
||||
masm.call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::amd64::verify_mxcsr_entry())));
|
||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::amd64::verify_mxcsr_entry())));
|
||||
}
|
||||
%}
|
||||
%}
|
||||
|
||||
// INSTRUCTIONS -- Platform dependent
|
||||
|
||||
//----------OS and Locking Instructions----------------------------------------
|
||||
|
||||
// This name is KNOWN by the ADLC and cannot be changed.
|
||||
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
|
||||
// for this guy.
|
||||
instruct tlsLoadP(r15_RegP dst)
|
||||
%{
|
||||
match(Set dst (ThreadLocal));
|
||||
effect(DEF dst);
|
||||
|
||||
size(0);
|
||||
format %{ "# TLS is in R15" %}
|
||||
ins_encode( /*empty encoding*/ );
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
|
||||
// Die now
|
||||
instruct ShouldNotReachHere()
|
||||
%{
|
||||
match(Halt);
|
||||
|
||||
// Use the following format syntax
|
||||
format %{ "int3\t# ShouldNotReachHere" %}
|
||||
// QQQ TODO for now call breakpoint
|
||||
// opcode(0xCC);
|
||||
// ins_encode(Opc);
|
||||
ins_encode(solaris_breakpoint);
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
|
||||
// Platform dependent source
|
||||
|
||||
source
|
||||
%{
|
||||
source %{
|
||||
|
||||
int MachCallRuntimeNode::ret_addr_offset()
|
||||
{
|
||||
int MachCallRuntimeNode::ret_addr_offset() {
|
||||
return 13; // movq r10,#addr; callq (r10)
|
||||
}
|
||||
|
||||
// emit an interrupt that is caught by the debugger
|
||||
void emit_break(CodeBuffer& cbuf)
|
||||
{
|
||||
// Debugger doesn't really catch this but best we can do so far QQQ
|
||||
MacroAssembler* masm = new MacroAssembler(&cbuf);
|
||||
masm->call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint)));
|
||||
}
|
||||
|
||||
void MachBreakpointNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
|
||||
{
|
||||
emit_break(cbuf);
|
||||
}
|
||||
|
||||
uint MachBreakpointNode::size(PhaseRegAlloc* ra_) const
|
||||
{
|
||||
// distance could be far and requires load and call through register
|
||||
return MachNode::size(ra_);
|
||||
}
|
||||
|
||||
%}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,134 +24,3 @@
|
||||
|
||||
// X86 Win32 Architecture Description File
|
||||
|
||||
//----------OS-DEPENDENT ENCODING BLOCK-----------------------------------------------------
|
||||
// This block specifies the encoding classes used by the compiler to output
|
||||
// byte streams. Encoding classes generate functions which are called by
|
||||
// Machine Instruction Nodes in order to generate the bit encoding of the
|
||||
// instruction. Operands specify their base encoding interface with the
|
||||
// interface keyword. There are currently supported four interfaces,
|
||||
// REG_INTER, CONST_INTER, MEMORY_INTER, & COND_INTER. REG_INTER causes an
|
||||
// operand to generate a function which returns its register number when
|
||||
// queried. CONST_INTER causes an operand to generate a function which
|
||||
// returns the value of the constant when queried. MEMORY_INTER causes an
|
||||
// operand to generate four functions which return the Base Register, the
|
||||
// Index Register, the Scale Value, and the Offset Value of the operand when
|
||||
// queried. COND_INTER causes an operand to generate six functions which
|
||||
// return the encoding code (ie - encoding bits for the instruction)
|
||||
// associated with each basic boolean condition for a conditional instruction.
|
||||
// Instructions specify two basic values for encoding. They use the
|
||||
// ins_encode keyword to specify their encoding class (which must be one of
|
||||
// the class names specified in the encoding block), and they use the
|
||||
// opcode keyword to specify, in order, their primary, secondary, and
|
||||
// tertiary opcode. Only the opcode sections which a particular instruction
|
||||
// needs for encoding need to be specified.
|
||||
encode %{
|
||||
// Build emit functions for each basic byte or larger field in the intel
|
||||
// encoding scheme (opcode, rm, sib, immediate), and call them from C++
|
||||
// code in the enc_class source block. Emit functions will live in the
|
||||
// main source block for now. In future, we can generalize this by
|
||||
// adding a syntax that specifies the sizes of fields in an order,
|
||||
// so that the adlc can build the emit functions automagically
|
||||
|
||||
enc_class tlsencode (eRegP dst, eRegP src) %{
|
||||
emit_rm(cbuf, 0x2, $dst$$reg, $src$$reg);
|
||||
emit_d32(cbuf, ThreadLocalStorage::get_thread_ptr_offset() );
|
||||
%}
|
||||
|
||||
enc_class call_epilog %{
|
||||
if( VerifyStackAtCalls ) {
|
||||
// Check that stack depth is unchanged: find majik cookie on stack
|
||||
int framesize = ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP,-3*VMRegImpl::slots_per_word));
|
||||
if(framesize >= 128) {
|
||||
emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood
|
||||
emit_d8(cbuf,0xBC);
|
||||
emit_d8(cbuf,0x24);
|
||||
emit_d32(cbuf,framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
}
|
||||
else {
|
||||
emit_opcode(cbuf, 0x81); // cmp [esp+0],0xbadb1ood
|
||||
emit_d8(cbuf,0x7C);
|
||||
emit_d8(cbuf,0x24);
|
||||
emit_d8(cbuf,framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
}
|
||||
// jmp EQ around INT3
|
||||
emit_opcode(cbuf,0x74);
|
||||
emit_d8(cbuf,1);
|
||||
// Die if stack mismatch
|
||||
emit_opcode(cbuf,0xCC);
|
||||
}
|
||||
%}
|
||||
|
||||
%}
|
||||
|
||||
// INSTRUCTIONS -- Platform dependent
|
||||
|
||||
|
||||
//----------OS and Locking Instructions----------------------------------------
|
||||
|
||||
// The prefix of this name is KNOWN by the ADLC and cannot be changed.
|
||||
instruct tlsLoadP_prefixLoadP(eRegP t1) %{
|
||||
effect(DEF t1);
|
||||
|
||||
format %{ "MOV $t1,FS:[0x00] "%}
|
||||
opcode(0x8B, 0x64);
|
||||
ins_encode(OpcS, OpcP, conmemref(t1));
|
||||
ins_pipe( ialu_reg_fat );
|
||||
%}
|
||||
|
||||
// This name is KNOWN by the ADLC and cannot be changed.
|
||||
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
|
||||
// for this guy.
|
||||
// %%% Should do this with a clause like: bottom_type(TypeRawPtr::BOTTOM);
|
||||
instruct tlsLoadP(eRegP dst, eRegP t1) %{
|
||||
effect(DEF dst, USE t1);
|
||||
|
||||
format %{ "MOV $dst,[$t1 + TLS::thread_ptr_offset()]" %}
|
||||
opcode(0x8B);
|
||||
ins_encode(OpcP, tlsencode(dst, t1));
|
||||
ins_pipe( ialu_reg_reg_fat );
|
||||
%}
|
||||
|
||||
instruct TLS(eRegP dst) %{
|
||||
match(Set dst (ThreadLocal));
|
||||
expand %{
|
||||
eRegP t1;
|
||||
tlsLoadP_prefixLoadP(t1);
|
||||
tlsLoadP(dst, t1);
|
||||
%}
|
||||
%}
|
||||
|
||||
// Die now
|
||||
instruct ShouldNotReachHere( )
|
||||
%{
|
||||
match(Halt);
|
||||
// Use the following format syntax
|
||||
format %{ "INT3 ; ShouldNotReachHere" %}
|
||||
opcode(0xCC);
|
||||
ins_encode(OpcP);
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
//
|
||||
// Platform dependent source
|
||||
//
|
||||
source %{
|
||||
|
||||
// emit an interrupt that is caught by the debugger
|
||||
void emit_break(CodeBuffer &cbuf) {
|
||||
cbuf.insts()->emit_int8((unsigned char) 0xcc);
|
||||
}
|
||||
|
||||
void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
emit_break(cbuf);
|
||||
}
|
||||
|
||||
|
||||
uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
%}
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -67,69 +67,6 @@ encode %{
|
||||
emit_opcode(cbuf, 0xD0 | (R10_enc - 8));
|
||||
%}
|
||||
|
||||
enc_class call_epilog %{
|
||||
if (VerifyStackAtCalls) {
|
||||
// Check that stack depth is unchanged: find majik cookie on stack
|
||||
int framesize =
|
||||
ra_->reg2offset_unchecked(OptoReg::add(ra_->_matcher._old_SP, -3*VMRegImpl::slots_per_word));
|
||||
if (framesize) {
|
||||
if (framesize < 0x80) {
|
||||
emit_opcode(cbuf, Assembler::REX_W);
|
||||
emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood
|
||||
emit_d8(cbuf, 0x7C);
|
||||
emit_d8(cbuf, 0x24);
|
||||
emit_d8(cbuf, framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
} else {
|
||||
emit_opcode(cbuf, Assembler::REX_W);
|
||||
emit_opcode(cbuf, 0x81); // cmpq [rsp+0],0xbadb1ood
|
||||
emit_d8(cbuf, 0xBC);
|
||||
emit_d8(cbuf, 0x24);
|
||||
emit_d32(cbuf, framesize); // Find majik cookie from ESP
|
||||
emit_d32(cbuf, 0xbadb100d);
|
||||
}
|
||||
}
|
||||
// jmp EQ around INT3
|
||||
// QQQ TODO
|
||||
const int jump_around = 5; // size of call to breakpoint, 1 for CC
|
||||
emit_opcode(cbuf, 0x74);
|
||||
emit_d8(cbuf, jump_around);
|
||||
// QQQ temporary
|
||||
emit_break(cbuf);
|
||||
// Die if stack mismatch
|
||||
// emit_opcode(cbuf,0xCC);
|
||||
}
|
||||
%}
|
||||
%}
|
||||
|
||||
// INSTRUCTIONS -- Platform dependent
|
||||
|
||||
|
||||
//----------OS and Locking Instructions----------------------------------------
|
||||
|
||||
// This name is KNOWN by the ADLC and cannot be changed.
|
||||
// The ADLC forces a 'TypeRawPtr::BOTTOM' output type
|
||||
// for this guy.
|
||||
instruct tlsLoadP(r15_RegP dst)
|
||||
%{
|
||||
match(Set dst (ThreadLocal));
|
||||
effect(DEF dst);
|
||||
|
||||
size(0);
|
||||
format %{ "# TLS is in R15" %}
|
||||
ins_encode( /*empty encoding*/ );
|
||||
ins_pipe(ialu_reg_reg);
|
||||
%}
|
||||
|
||||
// Die now
|
||||
instruct ShouldNotReachHere( )
|
||||
%{
|
||||
match(Halt);
|
||||
// Use the following format syntax
|
||||
format %{ "INT3 ; ShouldNotReachHere" %}
|
||||
opcode(0xCC);
|
||||
ins_encode(OpcP);
|
||||
ins_pipe( pipe_slow );
|
||||
%}
|
||||
|
||||
//
|
||||
@ -142,17 +79,4 @@ int MachCallRuntimeNode::ret_addr_offset()
|
||||
return 13; // movq r10,#addr; callq (r10)
|
||||
}
|
||||
|
||||
// emit an interrupt that is caught by the debugger
|
||||
void emit_break(CodeBuffer &cbuf) {
|
||||
cbuf.insts()->emit_int8((unsigned char) 0xcc);
|
||||
}
|
||||
|
||||
void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
emit_break(cbuf);
|
||||
}
|
||||
|
||||
uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
%}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1946,18 +1946,29 @@ void PhaseChaitin::dump_frame() const {
|
||||
reg2offset_unchecked(OptoReg::add(_matcher._old_SP,-1)) - reg2offset_unchecked(_matcher._new_SP)+jintSize);
|
||||
|
||||
// Preserve area dump
|
||||
int fixed_slots = C->fixed_slots();
|
||||
OptoReg::Name begin_in_preserve = OptoReg::add(_matcher._old_SP, -(int)C->in_preserve_stack_slots());
|
||||
OptoReg::Name return_addr = _matcher.return_addr();
|
||||
|
||||
reg = OptoReg::add(reg, -1);
|
||||
while (OptoReg::is_stack(reg)) {
|
||||
tty->print("#r%3.3d %s+%2d: ",reg,fp,reg2offset_unchecked(reg));
|
||||
if( _matcher.return_addr() == reg )
|
||||
if (return_addr == reg) {
|
||||
tty->print_cr("return address");
|
||||
else if( _matcher.return_addr() == OptoReg::add(reg,1) &&
|
||||
} else if (reg >= begin_in_preserve) {
|
||||
// Preserved slots are present on x86
|
||||
if (return_addr == OptoReg::add(reg, VMRegImpl::slots_per_word))
|
||||
tty->print_cr("saved fp register");
|
||||
else if (return_addr == OptoReg::add(reg, 2*VMRegImpl::slots_per_word) &&
|
||||
VerifyStackAtCalls)
|
||||
tty->print_cr("0xBADB100D +VerifyStackAtCalls");
|
||||
else if ((int)OptoReg::reg2stack(reg) < C->fixed_slots())
|
||||
tty->print_cr("Fixed slot %d", OptoReg::reg2stack(reg));
|
||||
else
|
||||
tty->print_cr("pad2, in_preserve");
|
||||
tty->print_cr("in_preserve");
|
||||
} else if ((int)OptoReg::reg2stack(reg) < fixed_slots) {
|
||||
tty->print_cr("Fixed slot %d", OptoReg::reg2stack(reg));
|
||||
} else {
|
||||
tty->print_cr("pad2, stack alignment");
|
||||
}
|
||||
reg = OptoReg::add(reg, -1);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user