8050022: linux-sparcv9: assert(SharedSkipVerify || obj->is_oop()) failed: sanity check

Provide promoted stack slots for floating-point registers in the SPARC c_calling_convention.

Reviewed-by: kvn, jrose, drchase
This commit is contained in:
Morris Meyer 2014-09-18 11:46:33 -07:00
parent e39f822e38
commit c468032582
2 changed files with 66 additions and 36 deletions

View file

@ -1128,51 +1128,82 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
// Hoist any int/ptr/long's in the first 6 to int regs.
// Hoist any flt/dbl's in the first 16 dbl regs.
int j = 0; // Count of actual args, not HALVES
for( int i=0; i<total_args_passed; i++, j++ ) {
switch( sig_bt[i] ) {
VMRegPair param_array_reg; // location of the argument in the parameter array
for (int i = 0; i < total_args_passed; i++, j++) {
param_array_reg.set_bad();
switch (sig_bt[i]) {
case T_BOOLEAN:
case T_BYTE:
case T_CHAR:
case T_INT:
case T_SHORT:
regs[i].set1( int_stk_helper( j ) ); break;
regs[i].set1(int_stk_helper(j));
break;
case T_LONG:
assert( sig_bt[i+1] == T_VOID, "expecting half" );
assert(sig_bt[i+1] == T_VOID, "expecting half");
case T_ADDRESS: // raw pointers, like current thread, for VM calls
case T_ARRAY:
case T_OBJECT:
case T_METADATA:
regs[i].set2( int_stk_helper( j ) );
regs[i].set2(int_stk_helper(j));
break;
case T_FLOAT:
if ( j < 16 ) {
// V9ism: floats go in ODD registers
regs[i].set1(as_FloatRegister(1 + (j<<1))->as_VMReg());
} else {
// V9ism: floats go in ODD stack slot
regs[i].set1(VMRegImpl::stack2reg(1 + (j<<1)));
// Per SPARC Compliance Definition 2.4.1, page 3P-12 available here
// http://www.sparc.org/wp-content/uploads/2014/01/SCD.2.4.1.pdf.gz
//
// "When a callee prototype exists, and does not indicate variable arguments,
// floating-point values assigned to locations %sp+BIAS+128 through %sp+BIAS+248
// will be promoted to floating-point registers"
//
// By "promoted" it means that the argument is located in two places, an unused
// spill slot in the "parameter array" (starts at %sp+BIAS+128), and a live
// float register. In most cases, there are 6 or fewer arguments of any type,
// and the standard parameter array slots (%sp+BIAS+128 to %sp+BIAS+176 exclusive)
// serve as shadow slots. Per the spec floating point registers %d6 to %d16
// require slots beyond that (up to %sp+BIAS+248).
//
{
// V9ism: floats go in ODD registers and stack slots
int float_index = 1 + (j << 1);
param_array_reg.set1(VMRegImpl::stack2reg(float_index));
if (j < 16) {
regs[i].set1(as_FloatRegister(float_index)->as_VMReg());
} else {
regs[i] = param_array_reg;
}
}
break;
case T_DOUBLE:
assert( sig_bt[i+1] == T_VOID, "expecting half" );
if ( j < 16 ) {
// V9ism: doubles go in EVEN/ODD regs
regs[i].set2(as_FloatRegister(j<<1)->as_VMReg());
} else {
// V9ism: doubles go in EVEN/ODD stack slots
regs[i].set2(VMRegImpl::stack2reg(j<<1));
{
assert(sig_bt[i + 1] == T_VOID, "expecting half");
// V9ism: doubles go in EVEN/ODD regs and stack slots
int double_index = (j << 1);
param_array_reg.set2(VMRegImpl::stack2reg(double_index));
if (j < 16) {
regs[i].set2(as_FloatRegister(double_index)->as_VMReg());
} else {
// V9ism: doubles go in EVEN/ODD stack slots
regs[i] = param_array_reg;
}
}
break;
case T_VOID: regs[i].set_bad(); j--; break; // Do not count HALVES
case T_VOID:
regs[i].set_bad();
j--;
break; // Do not count HALVES
default:
ShouldNotReachHere();
}
if (regs[i].first()->is_stack()) {
int off = regs[i].first()->reg2stack();
// Keep track of the deepest parameter array slot.
if (!param_array_reg.first()->is_valid()) {
param_array_reg = regs[i];
}
if (param_array_reg.first()->is_stack()) {
int off = param_array_reg.first()->reg2stack();
if (off > max_stack_slots) max_stack_slots = off;
}
if (regs[i].second()->is_stack()) {
int off = regs[i].second()->reg2stack();
if (param_array_reg.second()->is_stack()) {
int off = param_array_reg.second()->reg2stack();
if (off > max_stack_slots) max_stack_slots = off;
}
}
@ -1180,8 +1211,8 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
#else // _LP64
// V8 convention: first 6 things in O-regs, rest on stack.
// Alignment is willy-nilly.
for( int i=0; i<total_args_passed; i++ ) {
switch( sig_bt[i] ) {
for (int i = 0; i < total_args_passed; i++) {
switch (sig_bt[i]) {
case T_ADDRESS: // raw pointers, like current thread, for VM calls
case T_ARRAY:
case T_BOOLEAN:
@ -1192,23 +1223,23 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
case T_OBJECT:
case T_METADATA:
case T_SHORT:
regs[i].set1( int_stk_helper( i ) );
regs[i].set1(int_stk_helper(i));
break;
case T_DOUBLE:
case T_LONG:
assert( sig_bt[i+1] == T_VOID, "expecting half" );
regs[i].set_pair( int_stk_helper( i+1 ), int_stk_helper( i ) );
assert(sig_bt[i + 1] == T_VOID, "expecting half");
regs[i].set_pair(int_stk_helper(i + 1), int_stk_helper(i));
break;
case T_VOID: regs[i].set_bad(); break;
default:
ShouldNotReachHere();
}
if (regs[i].first()->is_stack()) {
int off = regs[i].first()->reg2stack();
int off = regs[i].first()->reg2stack();
if (off > max_stack_slots) max_stack_slots = off;
}
if (regs[i].second()->is_stack()) {
int off = regs[i].second()->reg2stack();
int off = regs[i].second()->reg2stack();
if (off > max_stack_slots) max_stack_slots = off;
}
}
@ -1357,11 +1388,10 @@ static void object_move(MacroAssembler* masm,
const Register rOop = src.first()->as_Register();
const Register rHandle = L5;
int oop_slot = rOop->input_number() * VMRegImpl::slots_per_word + oop_handle_offset;
int offset = oop_slot*VMRegImpl::stack_slot_size;
Label skip;
int offset = oop_slot * VMRegImpl::stack_slot_size;
__ st_ptr(rOop, SP, offset + STACK_BIAS);
if (is_receiver) {
*receiver_offset = oop_slot * VMRegImpl::stack_slot_size;
*receiver_offset = offset;
}
map->set_oop(VMRegImpl::stack2reg(oop_slot));
__ add(SP, offset + STACK_BIAS, rHandle);