aboutsummaryrefslogtreecommitdiff
path: root/src/cpu/sparc/vm/assembler_sparc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/sparc/vm/assembler_sparc.cpp')
-rw-r--r--src/cpu/sparc/vm/assembler_sparc.cpp56
1 files changed, 32 insertions, 24 deletions
diff --git a/src/cpu/sparc/vm/assembler_sparc.cpp b/src/cpu/sparc/vm/assembler_sparc.cpp
index 22cf4ced7..c4e319d0a 100644
--- a/src/cpu/sparc/vm/assembler_sparc.cpp
+++ b/src/cpu/sparc/vm/assembler_sparc.cpp
@@ -725,24 +725,6 @@ void MacroAssembler::jump(const AddressLiteral& addrlit, Register temp, int offs
}
-// Convert to C varargs format
-void MacroAssembler::set_varargs( Argument inArg, Register d ) {
- // spill register-resident args to their memory slots
- // (SPARC calling convention requires callers to have already preallocated these)
- // Note that the inArg might in fact be an outgoing argument,
- // if a leaf routine or stub does some tricky argument shuffling.
- // This routine must work even though one of the saved arguments
- // is in the d register (e.g., set_varargs(Argument(0, false), O0)).
- for (Argument savePtr = inArg;
- savePtr.is_register();
- savePtr = savePtr.successor()) {
- st_ptr(savePtr.as_register(), savePtr.address_in_frame());
- }
- // return the address of the first memory slot
- Address a = inArg.address_in_frame();
- add(a.base(), a.disp(), d);
-}
-
// Conditional breakpoint (for assertion checks in assembly code)
void MacroAssembler::breakpoint_trap(Condition c, CC cc) {
trap(c, cc, G0, ST_RESERVED_FOR_USER_0);
@@ -2943,6 +2925,20 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
assert(itable_index.is_constant() || itable_index.as_register() == method_result,
"caller must use same register for non-constant itable index as for method");
+ Label L_no_such_interface_restore;
+ bool did_save = false;
+ if (scan_temp == noreg || sethi_temp == noreg) {
+ Register recv_2 = recv_klass->is_global() ? recv_klass : L0;
+ Register intf_2 = intf_klass->is_global() ? intf_klass : L1;
+ assert(method_result->is_global(), "must be able to return value");
+ scan_temp = L2;
+ sethi_temp = L3;
+ save_frame_and_mov(0, recv_klass, recv_2, intf_klass, intf_2);
+ recv_klass = recv_2;
+ intf_klass = intf_2;
+ did_save = true;
+ }
+
// Compute start of first itableOffsetEntry (which is at the end of the vtable)
int vtable_base = InstanceKlass::vtable_start_offset() * wordSize;
int scan_step = itableOffsetEntry::size() * wordSize;
@@ -2981,7 +2977,7 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
// result = (klass + scan->offset() + itable_index);
// }
// }
- Label search, found_method;
+ Label L_search, L_found_method;
for (int peel = 1; peel >= 0; peel--) {
// %%%% Could load both offset and interface in one ldx, if they were
@@ -2991,23 +2987,23 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
// Check that this entry is non-null. A null entry means that
// the receiver class doesn't implement the interface, and wasn't the
// same as when the caller was compiled.
- bpr(Assembler::rc_z, false, Assembler::pn, method_result, L_no_such_interface);
+ bpr(Assembler::rc_z, false, Assembler::pn, method_result, did_save ? L_no_such_interface_restore : L_no_such_interface);
delayed()->cmp(method_result, intf_klass);
if (peel) {
- brx(Assembler::equal, false, Assembler::pt, found_method);
+ brx(Assembler::equal, false, Assembler::pt, L_found_method);
} else {
- brx(Assembler::notEqual, false, Assembler::pn, search);
+ brx(Assembler::notEqual, false, Assembler::pn, L_search);
// (invert the test to fall through to found_method...)
}
delayed()->add(scan_temp, scan_step, scan_temp);
if (!peel) break;
- bind(search);
+ bind(L_search);
}
- bind(found_method);
+ bind(L_found_method);
// Got a hit.
int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
@@ -3015,6 +3011,18 @@ void MacroAssembler::lookup_interface_method(Register recv_klass,
ito_offset -= scan_step;
lduw(scan_temp, ito_offset, scan_temp);
ld_ptr(recv_klass, scan_temp, method_result);
+
+ if (did_save) {
+ Label L_done;
+ ba(L_done);
+ delayed()->restore();
+
+ bind(L_no_such_interface_restore);
+ ba(L_no_such_interface);
+ delayed()->restore();
+
+ bind(L_done);
+ }
}