7011627: C1: call_RT must support targets that don't fit in wdisp30
Summary: Make both compilers emit near and far calls when necessary.
Reviewed-by: never, kvn, phh
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Tue Jan 11 20:26:13 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Wed Jan 12 18:33:25 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, 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
@@ -823,15 +823,23 @@
};
// test if x is within signed immediate range for nbits
- static bool is_simm(int x, int nbits) { return -( 1 << nbits-1 ) <= x && x < ( 1 << nbits-1 ); }
+ static bool is_simm(intptr_t x, int nbits) { return -( intptr_t(1) << nbits-1 ) <= x && x < ( intptr_t(1) << nbits-1 ); }
// test if -4096 <= x <= 4095
- static bool is_simm13(int x) { return is_simm(x, 13); }
+ static bool is_simm13(intptr_t x) { return is_simm(x, 13); }
+
+ static bool is_in_wdisp_range(address a, address b, int nbits) {
+ intptr_t d = intptr_t(b) - intptr_t(a);
+ return is_simm(d, nbits + 2);
+ }
// test if label is in simm16 range in words (wdisp16).
bool is_in_wdisp16_range(Label& L) {
- intptr_t d = intptr_t(pc()) - intptr_t(target(L));
- return is_simm(d, 18);
+ return is_in_wdisp_range(target(L), pc(), 16);
+ }
+ // test if the distance between two addresses fits in simm30 range in words
+ static bool is_in_wdisp30_range(address a, address b) {
+ return is_in_wdisp_range(a, b, 30);
}
enum ASIs { // page 72, v9
@@ -1843,6 +1851,8 @@
inline void jmp( Register s1, Register s2 );
inline void jmp( Register s1, int simm13a, RelocationHolder const& rspec = RelocationHolder() );
+ // Check if the call target is out of wdisp30 range (relative to the code cache)
+ static inline bool is_far_target(address d);
inline void call( address d, relocInfo::relocType rt = relocInfo::runtime_call_type );
inline void call( Label& L, relocInfo::relocType rt = relocInfo::runtime_call_type );
inline void callr( Register s1, Register s2 );
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Tue Jan 11 20:26:13 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Wed Jan 12 18:33:25 2011 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2011, 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
@@ -588,10 +588,13 @@
inline void MacroAssembler::jmp( Register s1, Register s2 ) { jmpl( s1, s2, G0 ); }
inline void MacroAssembler::jmp( Register s1, int simm13a, RelocationHolder const& rspec ) { jmpl( s1, simm13a, G0, rspec); }
+inline bool MacroAssembler::is_far_target(address d) {
+ return !is_in_wdisp30_range(d, CodeCache::low_bound()) || !is_in_wdisp30_range(d, CodeCache::high_bound());
+}
+
// Call with a check to see if we need to deal with the added
// expense of relocation and if we overflow the displacement
-// of the quick call instruction./
-// Check to see if we have to deal with relocations
+// of the quick call instruction.
inline void MacroAssembler::call( address d, relocInfo::relocType rt ) {
#ifdef _LP64
intptr_t disp;
@@ -603,14 +606,12 @@
// Is this address within range of the call instruction?
// If not, use the expensive instruction sequence
- disp = (intptr_t)d - (intptr_t)pc();
- if ( disp != (intptr_t)(int32_t)disp ) {
+ if (is_far_target(d)) {
relocate(rt);
AddressLiteral dest(d);
jumpl_to(dest, O7, O7);
- }
- else {
- Assembler::call( d, rt );
+ } else {
+ Assembler::call(d, rt);
}
#else
Assembler::call( d, rt );
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Tue Jan 11 20:26:13 2011 -0800
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Wed Jan 12 18:33:25 2011 -0800
@@ -1,5 +1,5 @@
//
-// Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 1998, 2011, 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
@@ -575,7 +575,11 @@
int MachCallRuntimeNode::ret_addr_offset() {
#ifdef _LP64
- return NativeFarCall::instruction_size; // farcall; delay slot
+ if (MacroAssembler::is_far_target(entry_point())) {
+ return NativeFarCall::instruction_size;
+ } else {
+ return NativeCall::instruction_size;
+ }
#else
return NativeCall::instruction_size; // call; delay slot
#endif
@@ -941,7 +945,7 @@
#endif
}
-void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocType rtype, bool preserve_g2 = false, bool force_far_call = false) {
+void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocType rtype, bool preserve_g2 = false) {
// The method which records debug information at every safepoint
// expects the call to be the first instruction in the snippet as
// it creates a PcDesc structure which tracks the offset of a call
@@ -963,20 +967,7 @@
int startpos = __ offset();
#endif /* ASSERT */
-#ifdef _LP64
- // Calls to the runtime or native may not be reachable from compiled code,
- // so we generate the far call sequence on 64 bit sparc.
- // This code sequence is relocatable to any address, even on LP64.
- if ( force_far_call ) {
- __ relocate(rtype);
- AddressLiteral dest(entry_point);
- __ jumpl_to(dest, O7, O7);
- }
- else
-#endif
- {
- __ call((address)entry_point, rtype);
- }
+ __ call((address)entry_point, rtype);
if (preserve_g2) __ delayed()->mov(G2, L7);
else __ delayed()->nop();
@@ -2507,7 +2498,7 @@
// CALL directly to the runtime
// The user of this is responsible for ensuring that R_L7 is empty (killed).
emit_call_reloc(cbuf, $meth$$method, relocInfo::runtime_call_type,
- /*preserve_g2=*/true, /*force far call*/true);
+ /*preserve_g2=*/true);
%}
enc_class preserve_SP %{