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,14 +1128,17 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
// Hoist any int/ptr/long's in the first 6 to int regs. // Hoist any int/ptr/long's in the first 6 to int regs.
// Hoist any flt/dbl's in the first 16 dbl regs. // Hoist any flt/dbl's in the first 16 dbl regs.
int j = 0; // Count of actual args, not HALVES int j = 0; // Count of actual args, not HALVES
VMRegPair param_array_reg; // location of the argument in the parameter array
for (int i = 0; i < total_args_passed; i++, j++) { for (int i = 0; i < total_args_passed; i++, j++) {
param_array_reg.set_bad();
switch (sig_bt[i]) { switch (sig_bt[i]) {
case T_BOOLEAN: case T_BOOLEAN:
case T_BYTE: case T_BYTE:
case T_CHAR: case T_CHAR:
case T_INT: case T_INT:
case T_SHORT: case T_SHORT:
regs[i].set1( int_stk_helper( j ) ); break; regs[i].set1(int_stk_helper(j));
break;
case T_LONG: 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_ADDRESS: // raw pointers, like current thread, for VM calls
@ -1145,34 +1148,62 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
regs[i].set2(int_stk_helper(j)); regs[i].set2(int_stk_helper(j));
break; break;
case T_FLOAT: case T_FLOAT:
// 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) { if (j < 16) {
// V9ism: floats go in ODD registers regs[i].set1(as_FloatRegister(float_index)->as_VMReg());
regs[i].set1(as_FloatRegister(1 + (j<<1))->as_VMReg());
} else { } else {
// V9ism: floats go in ODD stack slot regs[i] = param_array_reg;
regs[i].set1(VMRegImpl::stack2reg(1 + (j<<1))); }
} }
break; break;
case T_DOUBLE: case T_DOUBLE:
{
assert(sig_bt[i + 1] == T_VOID, "expecting half"); 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) { if (j < 16) {
// V9ism: doubles go in EVEN/ODD regs regs[i].set2(as_FloatRegister(double_index)->as_VMReg());
regs[i].set2(as_FloatRegister(j<<1)->as_VMReg());
} else { } else {
// V9ism: doubles go in EVEN/ODD stack slots // V9ism: doubles go in EVEN/ODD stack slots
regs[i].set2(VMRegImpl::stack2reg(j<<1)); regs[i] = param_array_reg;
}
} }
break; 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: default:
ShouldNotReachHere(); ShouldNotReachHere();
} }
if (regs[i].first()->is_stack()) { // Keep track of the deepest parameter array slot.
int off = regs[i].first()->reg2stack(); 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 (off > max_stack_slots) max_stack_slots = off;
} }
if (regs[i].second()->is_stack()) { if (param_array_reg.second()->is_stack()) {
int off = regs[i].second()->reg2stack(); int off = param_array_reg.second()->reg2stack();
if (off > max_stack_slots) max_stack_slots = off; if (off > max_stack_slots) max_stack_slots = off;
} }
} }
@ -1358,10 +1389,9 @@ static void object_move(MacroAssembler* masm,
const Register rHandle = L5; const Register rHandle = L5;
int oop_slot = rOop->input_number() * VMRegImpl::slots_per_word + oop_handle_offset; int oop_slot = rOop->input_number() * VMRegImpl::slots_per_word + oop_handle_offset;
int offset = oop_slot * VMRegImpl::stack_slot_size; int offset = oop_slot * VMRegImpl::stack_slot_size;
Label skip;
__ st_ptr(rOop, SP, offset + STACK_BIAS); __ st_ptr(rOop, SP, offset + STACK_BIAS);
if (is_receiver) { if (is_receiver) {
*receiver_offset = oop_slot * VMRegImpl::stack_slot_size; *receiver_offset = offset;
} }
map->set_oop(VMRegImpl::stack2reg(oop_slot)); map->set_oop(VMRegImpl::stack2reg(oop_slot));
__ add(SP, offset + STACK_BIAS, rHandle); __ add(SP, offset + STACK_BIAS, rHandle);

View file

@ -1989,7 +1989,7 @@ void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) {
// to implement the UseStrictFP mode. // to implement the UseStrictFP mode.
const bool Matcher::strict_fp_requires_explicit_rounding = false; const bool Matcher::strict_fp_requires_explicit_rounding = false;
// Are floats conerted to double when stored to stack during deoptimization? // Are floats converted to double when stored to stack during deoptimization?
// Sparc does not handle callee-save floats. // Sparc does not handle callee-save floats.
bool Matcher::float_in_double() { return false; } bool Matcher::float_in_double() { return false; }
@ -3218,7 +3218,7 @@ enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, notemp_iRegI r
// are owned by the CALLEE. Holes should not be nessecary in the // are owned by the CALLEE. Holes should not be nessecary in the
// incoming area, as the Java calling convention is completely under // incoming area, as the Java calling convention is completely under
// the control of the AD file. Doubles can be sorted and packed to // the control of the AD file. Doubles can be sorted and packed to
// avoid holes. Holes in the outgoing arguments may be nessecary for // avoid holes. Holes in the outgoing arguments may be necessary for
// varargs C calling conventions. // varargs C calling conventions.
// Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is // Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is
// even aligned with pad0 as needed. // even aligned with pad0 as needed.
@ -3284,7 +3284,7 @@ frame %{
%} %}
// Body of function which returns an OptoRegs array locating // Body of function which returns an OptoRegs array locating
// arguments either in registers or in stack slots for callin // arguments either in registers or in stack slots for calling
// C. // C.
c_calling_convention %{ c_calling_convention %{
// This is obviously always outgoing // This is obviously always outgoing