8050022: linux-sparcv9: assert(SharedSkipVerify || obj->is_oop()) failed: sanity check
Summary: Provide promoted stack slots for floating-point registers in the SPARC c_calling_convention.
Reviewed-by: kvn, jrose, drchase
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Sep 18 12:23:20 2014 +0200
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Sep 18 11:46:33 2014 -0700
@@ -1128,51 +1128,82 @@
// 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 @@
#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 @@
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 @@
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);
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Thu Sep 18 12:23:20 2014 +0200
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Thu Sep 18 11:46:33 2014 -0700
@@ -1989,7 +1989,7 @@
// to implement the UseStrictFP mode.
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.
bool Matcher::float_in_double() { return false; }
@@ -3218,7 +3218,7 @@
// are owned by the CALLEE. Holes should not be nessecary in the
// incoming area, as the Java calling convention is completely under
// 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.
// Note 3: Region 0-3 is even aligned, with pad2 as needed. Region 3-5 is
// even aligned with pad0 as needed.
@@ -3284,7 +3284,7 @@
%}
// 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_calling_convention %{
// This is obviously always outgoing