提交 589b03e4 编写于 作者: I iveresov

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
上级 182f10ae
/*
* 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 @@ class Assembler : public AbstractAssembler {
};
// 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 @@ class MacroAssembler: public Assembler {
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 );
......
/*
* 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::fbp( Condition c, bool a, CC cc, Predict p, Label& L
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 @@ inline void MacroAssembler::call( address d, relocInfo::relocType rt ) {
// 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 );
......
//
// 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 MachCallDynamicJavaNode::ret_addr_offset() {
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 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, const MachNode* n, int primary, int te
#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 @@ void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocTyp
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 @@ encode %{
// 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 %{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册