Merge
This commit is contained in:
commit
f40f23b2f0
@ -1,7 +1,7 @@
|
||||
^build/
|
||||
^dist/
|
||||
^nbproject/private/
|
||||
^src/share/tools/hsdis/bin/
|
||||
^src/share/tools/hsdis/build/
|
||||
^src/share/tools/IdealGraphVisualizer/[a-zA-Z0-9]*/build/
|
||||
^src/share/tools/IdealGraphVisualizer/build/
|
||||
^src/share/tools/IdealGraphVisualizer/dist/
|
||||
|
@ -46,24 +46,28 @@ jprt.my.solaris.sparc.jdk7=solaris_sparc_5.10
|
||||
jprt.my.solaris.sparc.jdk6=solaris_sparc_5.8
|
||||
jprt.my.solaris.sparc.jdk6perf=solaris_sparc_5.8
|
||||
jprt.my.solaris.sparc.jdk6u10=solaris_sparc_5.8
|
||||
jprt.my.solaris.sparc.jdk6u14=solaris_sparc_5.8
|
||||
jprt.my.solaris.sparc=${jprt.my.solaris.sparc.${jprt.tools.default.release}}
|
||||
|
||||
jprt.my.solaris.sparcv9.jdk7=solaris_sparcv9_5.10
|
||||
jprt.my.solaris.sparcv9.jdk6=solaris_sparcv9_5.8
|
||||
jprt.my.solaris.sparcv9.jdk6perf=solaris_sparcv9_5.8
|
||||
jprt.my.solaris.sparcv9.jdk6u10=solaris_sparcv9_5.8
|
||||
jprt.my.solaris.sparcv9.jdk6u14=solaris_sparcv9_5.8
|
||||
jprt.my.solaris.sparcv9=${jprt.my.solaris.sparcv9.${jprt.tools.default.release}}
|
||||
|
||||
jprt.my.solaris.i586.jdk7=solaris_i586_5.10
|
||||
jprt.my.solaris.i586.jdk6=solaris_i586_5.8
|
||||
jprt.my.solaris.i586.jdk6perf=solaris_i586_5.8
|
||||
jprt.my.solaris.i586.jdk6u10=solaris_i586_5.8
|
||||
jprt.my.solaris.i586.jdk6u14=solaris_i586_5.8
|
||||
jprt.my.solaris.i586=${jprt.my.solaris.i586.${jprt.tools.default.release}}
|
||||
|
||||
jprt.my.solaris.x64.jdk7=solaris_x64_5.10
|
||||
jprt.my.solaris.x64.jdk6=solaris_x64_5.10
|
||||
jprt.my.solaris.x64.jdk6perf=solaris_x64_5.10
|
||||
jprt.my.solaris.x64.jdk6u10=solaris_x64_5.10
|
||||
jprt.my.solaris.x64.jdk6u14=solaris_x64_5.10
|
||||
jprt.my.solaris.x64=${jprt.my.solaris.x64.${jprt.tools.default.release}}
|
||||
|
||||
jprt.my.linux.i586=linux_i586
|
||||
|
@ -46,7 +46,7 @@ C_COMPILER_REV := \
|
||||
$(shell $(CC) -V 2>&1 | sed -n 's/^.*[ ,\t]C[ ,\t]\([1-9]\.[0-9][0-9]*\).*/\1/p')
|
||||
|
||||
# Pick which compiler is validated
|
||||
ifeq ($(JDK_MINOR_VERSION),6)
|
||||
ifeq ($(JRE_RELEASE_VER),1.6.0)
|
||||
# Validated compiler for JDK6 is SS11 (5.8)
|
||||
VALIDATED_COMPILER_REV := 5.8
|
||||
VALIDATED_C_COMPILER_REV := 5.8
|
||||
@ -101,18 +101,9 @@ CFLAGS += ${SOLARIS_7_OR_LATER}
|
||||
|
||||
# New architecture options started in SS12 (5.9), we need both styles to build.
|
||||
# The older arch options for SS11 (5.8) or older and also for /usr/ccs/bin/as.
|
||||
# Note: SS12 default for 32bit sparc is now the same as v8plus, so the
|
||||
# settings below have changed all SS12 32bit sparc builds to be v8plus.
|
||||
# The older SS11 (5.8) settings have remained as they always have been.
|
||||
ifeq ($(TYPE),COMPILER2)
|
||||
ARCHFLAG_OLD/sparc = -xarch=v8plus
|
||||
else
|
||||
ifeq ($(TYPE),TIERED)
|
||||
ARCHFLAG_OLD/sparc = -xarch=v8plus
|
||||
else
|
||||
ARCHFLAG_OLD/sparc = -xarch=v8
|
||||
endif
|
||||
endif
|
||||
# Note: default for 32bit sparc is now the same as v8plus, so the
|
||||
# settings below have changed all 32bit sparc builds to be v8plus.
|
||||
ARCHFLAG_OLD/sparc = -xarch=v8plus
|
||||
ARCHFLAG_NEW/sparc = -m32 -xarch=sparc
|
||||
ARCHFLAG_OLD/sparcv9 = -xarch=v9
|
||||
ARCHFLAG_NEW/sparcv9 = -m64 -xarch=sparc
|
||||
|
@ -55,10 +55,16 @@ CPP_FLAGS=$(CPP_FLAGS) /D "COMPILER2"
|
||||
CPP_FLAGS=$(CPP_FLAGS) /D "COMPILER1" /D "COMPILER2"
|
||||
!endif
|
||||
|
||||
!if "$(BUILDARCH)" == "i486"
|
||||
HOTSPOT_LIB_ARCH=i386
|
||||
!else
|
||||
HOTSPOT_LIB_ARCH=$(BUILDARCH)
|
||||
!endif
|
||||
|
||||
# The following variables are defined in the generated local.make file.
|
||||
CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_RELEASE_VERSION=\"$(HS_BUILD_VER)\""
|
||||
CPP_FLAGS=$(CPP_FLAGS) /D "JRE_RELEASE_VERSION=\"$(JRE_RELEASE_VER)\""
|
||||
CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_LIB_ARCH=\"$(BUILDARCH)\""
|
||||
CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_LIB_ARCH=\"$(HOTSPOT_LIB_ARCH)\""
|
||||
CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_BUILD_TARGET=\"$(BUILD_FLAVOR)\""
|
||||
CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_BUILD_USER=\"$(BuildUser)\""
|
||||
CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_VM_DISTRO=\"$(HOTSPOT_VM_DISTRO)\""
|
||||
|
@ -25,24 +25,36 @@
|
||||
#include "incls/_precompiled.incl"
|
||||
#include "incls/_assembler_sparc.cpp.incl"
|
||||
|
||||
// Implementation of Address
|
||||
|
||||
Address::Address( addr_type t, int which ) {
|
||||
switch (t) {
|
||||
case extra_in_argument:
|
||||
case extra_out_argument:
|
||||
_base = t == extra_in_argument ? FP : SP;
|
||||
_hi = 0;
|
||||
// Warning: In LP64 mode, _disp will occupy more than 10 bits.
|
||||
// This is inconsistent with the other constructors but op
|
||||
// codes such as ld or ldx, only access disp() to get their
|
||||
// simm13 argument.
|
||||
_disp = ((which - Argument::n_register_parameters + frame::memory_parameter_word_sp_offset) * BytesPerWord) + STACK_BIAS;
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
break;
|
||||
// Convert the raw encoding form into the form expected by the
|
||||
// constructor for Address.
|
||||
Address Address::make_raw(int base, int index, int scale, int disp, bool disp_is_oop) {
|
||||
assert(scale == 0, "not supported");
|
||||
RelocationHolder rspec;
|
||||
if (disp_is_oop) {
|
||||
rspec = Relocation::spec_simple(relocInfo::oop_type);
|
||||
}
|
||||
|
||||
Register rindex = as_Register(index);
|
||||
if (rindex != G0) {
|
||||
Address madr(as_Register(base), rindex);
|
||||
madr._rspec = rspec;
|
||||
return madr;
|
||||
} else {
|
||||
Address madr(as_Register(base), disp);
|
||||
madr._rspec = rspec;
|
||||
return madr;
|
||||
}
|
||||
}
|
||||
|
||||
Address Argument::address_in_frame() const {
|
||||
// Warning: In LP64 mode disp will occupy more than 10 bits, but
|
||||
// op codes such as ld or ldx, only access disp() to get
|
||||
// their simm13 argument.
|
||||
int disp = ((_number - Argument::n_register_parameters + frame::memory_parameter_word_sp_offset) * BytesPerWord) + STACK_BIAS;
|
||||
if (is_in())
|
||||
return Address(FP, disp); // In argument.
|
||||
else
|
||||
return Address(SP, disp); // Out argument.
|
||||
}
|
||||
|
||||
static const char* argumentNames[][2] = {
|
||||
@ -614,16 +626,17 @@ void MacroAssembler::jmp(Register r1, int offset, const char* file, int line ) {
|
||||
}
|
||||
|
||||
// This code sequence is relocatable to any address, even on LP64.
|
||||
void MacroAssembler::jumpl( Address& a, Register d, int offset, const char* file, int line ) {
|
||||
void MacroAssembler::jumpl(AddressLiteral& addrlit, Register temp, Register d, int offset, const char* file, int line) {
|
||||
assert_not_delayed();
|
||||
// Force fixed length sethi because NativeJump and NativeFarCall don't handle
|
||||
// variable length instruction streams.
|
||||
sethi(a, /*ForceRelocatable=*/ true);
|
||||
patchable_sethi(addrlit, temp);
|
||||
Address a(temp, addrlit.low10() + offset); // Add the offset to the displacement.
|
||||
if (TraceJumps) {
|
||||
#ifndef PRODUCT
|
||||
// Must do the add here so relocation can find the remainder of the
|
||||
// value to be relocated.
|
||||
add(a.base(), a.disp() + offset, a.base(), a.rspec(offset));
|
||||
add(a.base(), a.disp(), a.base(), addrlit.rspec(offset));
|
||||
save_frame(0);
|
||||
verify_thread();
|
||||
ld(G2_thread, in_bytes(JavaThread::jmp_ring_index_offset()), O0);
|
||||
@ -652,15 +665,15 @@ void MacroAssembler::jumpl( Address& a, Register d, int offset, const char* file
|
||||
restore();
|
||||
jmpl(a.base(), G0, d);
|
||||
#else
|
||||
jmpl(a, d, offset);
|
||||
jmpl(a.base(), a.disp(), d);
|
||||
#endif /* PRODUCT */
|
||||
} else {
|
||||
jmpl(a, d, offset);
|
||||
jmpl(a.base(), a.disp(), d);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::jump( Address& a, int offset, const char* file, int line ) {
|
||||
jumpl( a, G0, offset, file, line );
|
||||
void MacroAssembler::jump(AddressLiteral& addrlit, Register temp, int offset, const char* file, int line) {
|
||||
jumpl(addrlit, temp, G0, offset, file, line);
|
||||
}
|
||||
|
||||
|
||||
@ -678,7 +691,8 @@ void MacroAssembler::set_varargs( Argument inArg, Register d ) {
|
||||
st_ptr(savePtr.as_register(), savePtr.address_in_frame());
|
||||
}
|
||||
// return the address of the first memory slot
|
||||
add(inArg.address_in_frame(), d);
|
||||
Address a = inArg.address_in_frame();
|
||||
add(a.base(), a.disp(), d);
|
||||
}
|
||||
|
||||
// Conditional breakpoint (for assertion checks in assembly code)
|
||||
@ -702,7 +716,6 @@ void MacroAssembler::flush_windows() {
|
||||
// offset to write to within the page. This minimizes bus traffic
|
||||
// due to cache line collision.
|
||||
void MacroAssembler::serialize_memory(Register thread, Register tmp1, Register tmp2) {
|
||||
Address mem_serialize_page(tmp1, os::get_memory_serialize_page());
|
||||
srl(thread, os::get_serialize_page_shift_count(), tmp2);
|
||||
if (Assembler::is_simm13(os::vm_page_size())) {
|
||||
and3(tmp2, (os::vm_page_size() - sizeof(int)), tmp2);
|
||||
@ -711,7 +724,7 @@ void MacroAssembler::serialize_memory(Register thread, Register tmp1, Register t
|
||||
set((os::vm_page_size() - sizeof(int)), tmp1);
|
||||
and3(tmp2, tmp1, tmp2);
|
||||
}
|
||||
load_address(mem_serialize_page);
|
||||
set(os::get_memory_serialize_page(), tmp1);
|
||||
st(G0, tmp1, tmp2);
|
||||
}
|
||||
|
||||
@ -830,10 +843,10 @@ void MacroAssembler::get_thread() {
|
||||
mov(G3, L2); // avoid clobbering G3 also
|
||||
mov(G4, L5); // avoid clobbering G4
|
||||
#ifdef ASSERT
|
||||
Address last_get_thread_addr(L3, (address)&last_get_thread);
|
||||
sethi(last_get_thread_addr);
|
||||
AddressLiteral last_get_thread_addrlit(&last_get_thread);
|
||||
set(last_get_thread_addrlit, L3);
|
||||
inc(L4, get_pc(L4) + 2 * BytesPerInstWord); // skip getpc() code + inc + st_ptr to point L4 at call
|
||||
st_ptr(L4, last_get_thread_addr);
|
||||
st_ptr(L4, L3, 0);
|
||||
#endif
|
||||
call(CAST_FROM_FN_PTR(address, reinitialize_thread), relocInfo::runtime_call_type);
|
||||
delayed()->nop();
|
||||
@ -919,13 +932,9 @@ void MacroAssembler::restore_thread(const Register thread_cache) {
|
||||
// %%% maybe get rid of [re]set_last_Java_frame
|
||||
void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_Java_pc) {
|
||||
assert_not_delayed();
|
||||
Address flags(G2_thread,
|
||||
0,
|
||||
in_bytes(JavaThread::frame_anchor_offset()) +
|
||||
in_bytes(JavaFrameAnchor::flags_offset()));
|
||||
Address pc_addr(G2_thread,
|
||||
0,
|
||||
in_bytes(JavaThread::last_Java_pc_offset()));
|
||||
Address flags(G2_thread, JavaThread::frame_anchor_offset() +
|
||||
JavaFrameAnchor::flags_offset());
|
||||
Address pc_addr(G2_thread, JavaThread::last_Java_pc_offset());
|
||||
|
||||
// Always set last_Java_pc and flags first because once last_Java_sp is visible
|
||||
// has_last_Java_frame is true and users will look at the rest of the fields.
|
||||
@ -977,22 +986,18 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_Ja
|
||||
#endif // ASSERT
|
||||
assert( last_java_sp != G4_scratch, "bad register usage in set_last_Java_frame");
|
||||
add( last_java_sp, STACK_BIAS, G4_scratch );
|
||||
st_ptr(G4_scratch, Address(G2_thread, 0, in_bytes(JavaThread::last_Java_sp_offset())));
|
||||
st_ptr(G4_scratch, G2_thread, JavaThread::last_Java_sp_offset());
|
||||
#else
|
||||
st_ptr(last_java_sp, Address(G2_thread, 0, in_bytes(JavaThread::last_Java_sp_offset())));
|
||||
st_ptr(last_java_sp, G2_thread, JavaThread::last_Java_sp_offset());
|
||||
#endif // _LP64
|
||||
}
|
||||
|
||||
void MacroAssembler::reset_last_Java_frame(void) {
|
||||
assert_not_delayed();
|
||||
|
||||
Address sp_addr(G2_thread, 0, in_bytes(JavaThread::last_Java_sp_offset()));
|
||||
Address pc_addr(G2_thread,
|
||||
0,
|
||||
in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::last_Java_pc_offset()));
|
||||
Address flags(G2_thread,
|
||||
0,
|
||||
in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::flags_offset()));
|
||||
Address sp_addr(G2_thread, JavaThread::last_Java_sp_offset());
|
||||
Address pc_addr(G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::last_Java_pc_offset());
|
||||
Address flags (G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::flags_offset());
|
||||
|
||||
#ifdef ASSERT
|
||||
// check that it WAS previously set
|
||||
@ -1063,7 +1068,7 @@ void MacroAssembler::check_and_forward_exception(Register scratch_reg)
|
||||
check_and_handle_popframe(scratch_reg);
|
||||
check_and_handle_earlyret(scratch_reg);
|
||||
|
||||
Address exception_addr(G2_thread, 0, in_bytes(Thread::pending_exception_offset()));
|
||||
Address exception_addr(G2_thread, Thread::pending_exception_offset());
|
||||
ld_ptr(exception_addr, scratch_reg);
|
||||
br_null(scratch_reg,false,pt,L);
|
||||
delayed()->nop();
|
||||
@ -1186,7 +1191,7 @@ void MacroAssembler::call_VM_leaf(Register thread_cache, address entry_point, Re
|
||||
|
||||
void MacroAssembler::get_vm_result(Register oop_result) {
|
||||
verify_thread();
|
||||
Address vm_result_addr(G2_thread, 0, in_bytes(JavaThread::vm_result_offset()));
|
||||
Address vm_result_addr(G2_thread, JavaThread::vm_result_offset());
|
||||
ld_ptr( vm_result_addr, oop_result);
|
||||
st_ptr(G0, vm_result_addr);
|
||||
verify_oop(oop_result);
|
||||
@ -1195,7 +1200,7 @@ void MacroAssembler::get_vm_result(Register oop_result) {
|
||||
|
||||
void MacroAssembler::get_vm_result_2(Register oop_result) {
|
||||
verify_thread();
|
||||
Address vm_result_addr_2(G2_thread, 0, in_bytes(JavaThread::vm_result_2_offset()));
|
||||
Address vm_result_addr_2(G2_thread, JavaThread::vm_result_2_offset());
|
||||
ld_ptr(vm_result_addr_2, oop_result);
|
||||
st_ptr(G0, vm_result_addr_2);
|
||||
verify_oop(oop_result);
|
||||
@ -1206,7 +1211,7 @@ void MacroAssembler::get_vm_result_2(Register oop_result) {
|
||||
// leave it undisturbed.
|
||||
void MacroAssembler::set_vm_result(Register oop_result) {
|
||||
verify_thread();
|
||||
Address vm_result_addr(G2_thread, 0, in_bytes(JavaThread::vm_result_offset()));
|
||||
Address vm_result_addr(G2_thread, JavaThread::vm_result_offset());
|
||||
verify_oop(oop_result);
|
||||
|
||||
# ifdef ASSERT
|
||||
@ -1234,81 +1239,78 @@ void MacroAssembler::card_table_write(jbyte* byte_map_base,
|
||||
#else
|
||||
srl(obj, CardTableModRefBS::card_shift, obj);
|
||||
#endif
|
||||
assert( tmp != obj, "need separate temp reg");
|
||||
Address rs(tmp, (address)byte_map_base);
|
||||
load_address(rs);
|
||||
stb(G0, rs.base(), obj);
|
||||
}
|
||||
|
||||
// %%% Note: The following six instructions have been moved,
|
||||
// unchanged, from assembler_sparc.inline.hpp.
|
||||
// They will be refactored at a later date.
|
||||
|
||||
void MacroAssembler::sethi(intptr_t imm22a,
|
||||
Register d,
|
||||
bool ForceRelocatable,
|
||||
RelocationHolder const& rspec) {
|
||||
Address adr( d, (address)imm22a, rspec );
|
||||
MacroAssembler::sethi( adr, ForceRelocatable );
|
||||
assert(tmp != obj, "need separate temp reg");
|
||||
set((address) byte_map_base, tmp);
|
||||
stb(G0, tmp, obj);
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::sethi(Address& a, bool ForceRelocatable) {
|
||||
void MacroAssembler::internal_sethi(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) {
|
||||
address save_pc;
|
||||
int shiftcnt;
|
||||
// if addr of local, do not need to load it
|
||||
assert(a.base() != FP && a.base() != SP, "just use ld or st for locals");
|
||||
#ifdef _LP64
|
||||
# ifdef CHECK_DELAY
|
||||
assert_not_delayed( (char *)"cannot put two instructions in delay slot" );
|
||||
assert_not_delayed((char*) "cannot put two instructions in delay slot");
|
||||
# endif
|
||||
v9_dep();
|
||||
// ForceRelocatable = 1;
|
||||
save_pc = pc();
|
||||
if (a.hi32() == 0 && a.low32() >= 0) {
|
||||
Assembler::sethi(a.low32(), a.base(), a.rspec());
|
||||
|
||||
int msb32 = (int) (addrlit.value() >> 32);
|
||||
int lsb32 = (int) (addrlit.value());
|
||||
|
||||
if (msb32 == 0 && lsb32 >= 0) {
|
||||
Assembler::sethi(lsb32, d, addrlit.rspec());
|
||||
}
|
||||
else if (a.hi32() == -1) {
|
||||
Assembler::sethi(~a.low32(), a.base(), a.rspec());
|
||||
xor3(a.base(), ~low10(~0), a.base());
|
||||
else if (msb32 == -1) {
|
||||
Assembler::sethi(~lsb32, d, addrlit.rspec());
|
||||
xor3(d, ~low10(~0), d);
|
||||
}
|
||||
else {
|
||||
Assembler::sethi(a.hi32(), a.base(), a.rspec() ); // 22
|
||||
if ( a.hi32() & 0x3ff ) // Any bits?
|
||||
or3( a.base(), a.hi32() & 0x3ff ,a.base() ); // High 32 bits are now in low 32
|
||||
if ( a.low32() & 0xFFFFFC00 ) { // done?
|
||||
if( (a.low32() >> 20) & 0xfff ) { // Any bits set?
|
||||
sllx(a.base(), 12, a.base()); // Make room for next 12 bits
|
||||
or3( a.base(), (a.low32() >> 20) & 0xfff,a.base() ); // Or in next 12
|
||||
shiftcnt = 0; // We already shifted
|
||||
Assembler::sethi(msb32, d, addrlit.rspec()); // msb 22-bits
|
||||
if (msb32 & 0x3ff) // Any bits?
|
||||
or3(d, msb32 & 0x3ff, d); // msb 32-bits are now in lsb 32
|
||||
if (lsb32 & 0xFFFFFC00) { // done?
|
||||
if ((lsb32 >> 20) & 0xfff) { // Any bits set?
|
||||
sllx(d, 12, d); // Make room for next 12 bits
|
||||
or3(d, (lsb32 >> 20) & 0xfff, d); // Or in next 12
|
||||
shiftcnt = 0; // We already shifted
|
||||
}
|
||||
else
|
||||
shiftcnt = 12;
|
||||
if( (a.low32() >> 10) & 0x3ff ) {
|
||||
sllx(a.base(), shiftcnt+10, a.base());// Make room for last 10 bits
|
||||
or3( a.base(), (a.low32() >> 10) & 0x3ff,a.base() ); // Or in next 10
|
||||
if ((lsb32 >> 10) & 0x3ff) {
|
||||
sllx(d, shiftcnt + 10, d); // Make room for last 10 bits
|
||||
or3(d, (lsb32 >> 10) & 0x3ff, d); // Or in next 10
|
||||
shiftcnt = 0;
|
||||
}
|
||||
else
|
||||
shiftcnt = 10;
|
||||
sllx(a.base(), shiftcnt+10 , a.base()); // Shift leaving disp field 0'd
|
||||
sllx(d, shiftcnt + 10, d); // Shift leaving disp field 0'd
|
||||
}
|
||||
else
|
||||
sllx( a.base(), 32, a.base() );
|
||||
sllx(d, 32, d);
|
||||
}
|
||||
// Pad out the instruction sequence so it can be
|
||||
// patched later.
|
||||
if ( ForceRelocatable || (a.rtype() != relocInfo::none &&
|
||||
a.rtype() != relocInfo::runtime_call_type) ) {
|
||||
while ( pc() < (save_pc + (7 * BytesPerInstWord )) )
|
||||
// Pad out the instruction sequence so it can be patched later.
|
||||
if (ForceRelocatable || (addrlit.rtype() != relocInfo::none &&
|
||||
addrlit.rtype() != relocInfo::runtime_call_type)) {
|
||||
while (pc() < (save_pc + (7 * BytesPerInstWord)))
|
||||
nop();
|
||||
}
|
||||
#else
|
||||
Assembler::sethi(a.hi(), a.base(), a.rspec());
|
||||
Assembler::sethi(addrlit.value(), d, addrlit.rspec());
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::sethi(const AddressLiteral& addrlit, Register d) {
|
||||
internal_sethi(addrlit, d, false);
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::patchable_sethi(const AddressLiteral& addrlit, Register d) {
|
||||
internal_sethi(addrlit, d, true);
|
||||
}
|
||||
|
||||
|
||||
int MacroAssembler::size_of_sethi(address a, bool worst_case) {
|
||||
#ifdef _LP64
|
||||
if (worst_case) return 7;
|
||||
@ -1339,61 +1341,50 @@ int MacroAssembler::worst_case_size_of_set() {
|
||||
return size_of_sethi(NULL, true) + 1;
|
||||
}
|
||||
|
||||
void MacroAssembler::set(intptr_t value, Register d,
|
||||
RelocationHolder const& rspec) {
|
||||
Address val( d, (address)value, rspec);
|
||||
|
||||
if ( rspec.type() == relocInfo::none ) {
|
||||
void MacroAssembler::internal_set(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) {
|
||||
intptr_t value = addrlit.value();
|
||||
|
||||
if (!ForceRelocatable && addrlit.rspec().type() == relocInfo::none) {
|
||||
// can optimize
|
||||
if (-4096 <= value && value <= 4095) {
|
||||
if (-4096 <= value && value <= 4095) {
|
||||
or3(G0, value, d); // setsw (this leaves upper 32 bits sign-extended)
|
||||
return;
|
||||
}
|
||||
if (inv_hi22(hi22(value)) == value) {
|
||||
sethi(val);
|
||||
sethi(addrlit, d);
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert_not_delayed( (char *)"cannot put two instructions in delay slot" );
|
||||
sethi( val );
|
||||
if (rspec.type() != relocInfo::none || (value & 0x3ff) != 0) {
|
||||
add( d, value & 0x3ff, d, rspec);
|
||||
assert_not_delayed((char*) "cannot put two instructions in delay slot");
|
||||
internal_sethi(addrlit, d, ForceRelocatable);
|
||||
if (ForceRelocatable || addrlit.rspec().type() != relocInfo::none || addrlit.low10() != 0) {
|
||||
add(d, addrlit.low10(), d, addrlit.rspec());
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::setsw(int value, Register d,
|
||||
RelocationHolder const& rspec) {
|
||||
Address val( d, (address)value, rspec);
|
||||
if ( rspec.type() == relocInfo::none ) {
|
||||
// can optimize
|
||||
if (-4096 <= value && value <= 4095) {
|
||||
or3(G0, value, d);
|
||||
return;
|
||||
}
|
||||
if (inv_hi22(hi22(value)) == value) {
|
||||
sethi( val );
|
||||
#ifndef _LP64
|
||||
if ( value < 0 ) {
|
||||
assert_not_delayed();
|
||||
sra (d, G0, d);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert_not_delayed();
|
||||
sethi( val );
|
||||
add( d, value & 0x3ff, d, rspec);
|
||||
|
||||
// (A negative value could be loaded in 2 insns with sethi/xor,
|
||||
// but it would take a more complex relocation.)
|
||||
#ifndef _LP64
|
||||
if ( value < 0)
|
||||
sra(d, G0, d);
|
||||
#endif
|
||||
void MacroAssembler::set(const AddressLiteral& al, Register d) {
|
||||
internal_set(al, d, false);
|
||||
}
|
||||
|
||||
// %%% End of moved six set instructions.
|
||||
void MacroAssembler::set(intptr_t value, Register d) {
|
||||
AddressLiteral al(value);
|
||||
internal_set(al, d, false);
|
||||
}
|
||||
|
||||
void MacroAssembler::set(address addr, Register d, RelocationHolder const& rspec) {
|
||||
AddressLiteral al(addr, rspec);
|
||||
internal_set(al, d, false);
|
||||
}
|
||||
|
||||
void MacroAssembler::patchable_set(const AddressLiteral& al, Register d) {
|
||||
internal_set(al, d, true);
|
||||
}
|
||||
|
||||
void MacroAssembler::patchable_set(intptr_t value, Register d) {
|
||||
AddressLiteral al(value);
|
||||
internal_set(al, d, true);
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::set64(jlong value, Register d, Register tmp) {
|
||||
@ -1512,17 +1503,17 @@ void MacroAssembler::save_frame_and_mov(int extraWords,
|
||||
}
|
||||
|
||||
|
||||
Address MacroAssembler::allocate_oop_address(jobject obj, Register d) {
|
||||
AddressLiteral MacroAssembler::allocate_oop_address(jobject obj) {
|
||||
assert(oop_recorder() != NULL, "this assembler needs an OopRecorder");
|
||||
int oop_index = oop_recorder()->allocate_index(obj);
|
||||
return Address(d, address(obj), oop_Relocation::spec(oop_index));
|
||||
return AddressLiteral(obj, oop_Relocation::spec(oop_index));
|
||||
}
|
||||
|
||||
|
||||
Address MacroAssembler::constant_oop_address(jobject obj, Register d) {
|
||||
AddressLiteral MacroAssembler::constant_oop_address(jobject obj) {
|
||||
assert(oop_recorder() != NULL, "this assembler needs an OopRecorder");
|
||||
int oop_index = oop_recorder()->find_index(obj);
|
||||
return Address(d, address(obj), oop_Relocation::spec(oop_index));
|
||||
return AddressLiteral(obj, oop_Relocation::spec(oop_index));
|
||||
}
|
||||
|
||||
void MacroAssembler::set_narrow_oop(jobject obj, Register d) {
|
||||
@ -1682,7 +1673,7 @@ void MacroAssembler::_verify_oop(Register reg, const char* msg, const char * fil
|
||||
sprintf(real_msg, "%s%s(%s:%d)", msg, buffer, file, line);
|
||||
|
||||
// Call indirectly to solve generation ordering problem
|
||||
Address a(O7, (address)StubRoutines::verify_oop_subroutine_entry_address());
|
||||
AddressLiteral a(StubRoutines::verify_oop_subroutine_entry_address());
|
||||
|
||||
// Make some space on stack above the current register window.
|
||||
// Enough to hold 8 64-bit registers.
|
||||
@ -1718,7 +1709,7 @@ void MacroAssembler::_verify_oop_addr(Address addr, const char* msg, const char
|
||||
sprintf(real_msg, "%s at SP+%d (%s:%d)", msg, addr.disp(), file, line);
|
||||
|
||||
// Call indirectly to solve generation ordering problem
|
||||
Address a(O7, (address)StubRoutines::verify_oop_subroutine_entry_address());
|
||||
AddressLiteral a(StubRoutines::verify_oop_subroutine_entry_address());
|
||||
|
||||
// Make some space on stack above the current register window.
|
||||
// Enough to hold 8 64-bit registers.
|
||||
@ -1772,11 +1763,7 @@ void MacroAssembler::verify_oop_subroutine() {
|
||||
{ // count number of verifies
|
||||
Register O2_adr = O2;
|
||||
Register O3_accum = O3;
|
||||
Address count_addr( O2_adr, (address) StubRoutines::verify_oop_count_addr() );
|
||||
sethi(count_addr);
|
||||
ld(count_addr, O3_accum);
|
||||
inc(O3_accum);
|
||||
st(O3_accum, count_addr);
|
||||
inc_counter(StubRoutines::verify_oop_count_addr(), O2_adr, O3_accum);
|
||||
}
|
||||
|
||||
Register O2_mask = O2;
|
||||
@ -1870,8 +1857,8 @@ void MacroAssembler::verify_oop_subroutine() {
|
||||
assert(StubRoutines::Sparc::stop_subroutine_entry_address(), "hasn't been generated yet");
|
||||
|
||||
// call indirectly to solve generation ordering problem
|
||||
Address a(O5, (address)StubRoutines::Sparc::stop_subroutine_entry_address());
|
||||
load_ptr_contents(a, O5);
|
||||
AddressLiteral al(StubRoutines::Sparc::stop_subroutine_entry_address());
|
||||
load_ptr_contents(al, O5);
|
||||
jmpl(O5, 0, O7);
|
||||
delayed()->nop();
|
||||
}
|
||||
@ -1891,7 +1878,7 @@ void MacroAssembler::stop(const char* msg) {
|
||||
assert(StubRoutines::Sparc::stop_subroutine_entry_address(), "hasn't been generated yet");
|
||||
|
||||
// call indirectly to solve generation ordering problem
|
||||
Address a(O5, (address)StubRoutines::Sparc::stop_subroutine_entry_address());
|
||||
AddressLiteral a(StubRoutines::Sparc::stop_subroutine_entry_address());
|
||||
load_ptr_contents(a, O5);
|
||||
jmpl(O5, 0, O7);
|
||||
delayed()->nop();
|
||||
@ -2003,7 +1990,7 @@ void MacroAssembler::calc_mem_param_words(Register Rparam_words, Register Rresul
|
||||
subcc( Rparam_words, Argument::n_register_parameters, Rresult); // how many mem words?
|
||||
Label no_extras;
|
||||
br( negative, true, pt, no_extras ); // if neg, clear reg
|
||||
delayed()->set( 0, Rresult); // annuled, so only if taken
|
||||
delayed()->set(0, Rresult); // annuled, so only if taken
|
||||
bind( no_extras );
|
||||
}
|
||||
|
||||
@ -2623,7 +2610,7 @@ RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_ad
|
||||
return RegisterOrConstant(value + offset);
|
||||
|
||||
// load indirectly to solve generation ordering problem
|
||||
Address a(tmp, (address) delayed_value_addr);
|
||||
AddressLiteral a(delayed_value_addr);
|
||||
load_ptr_contents(a, tmp);
|
||||
|
||||
#ifdef ASSERT
|
||||
@ -3107,21 +3094,21 @@ void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
|
||||
delayed()->nop();
|
||||
|
||||
load_klass(obj_reg, temp_reg);
|
||||
ld_ptr(Address(temp_reg, 0, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()), temp_reg);
|
||||
ld_ptr(Address(temp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()), temp_reg);
|
||||
or3(G2_thread, temp_reg, temp_reg);
|
||||
xor3(mark_reg, temp_reg, temp_reg);
|
||||
andcc(temp_reg, ~((int) markOopDesc::age_mask_in_place), temp_reg);
|
||||
if (counters != NULL) {
|
||||
cond_inc(Assembler::equal, (address) counters->biased_lock_entry_count_addr(), mark_reg, temp_reg);
|
||||
// Reload mark_reg as we may need it later
|
||||
ld_ptr(Address(obj_reg, 0, oopDesc::mark_offset_in_bytes()), mark_reg);
|
||||
ld_ptr(Address(obj_reg, oopDesc::mark_offset_in_bytes()), mark_reg);
|
||||
}
|
||||
brx(Assembler::equal, true, Assembler::pt, done);
|
||||
delayed()->nop();
|
||||
|
||||
Label try_revoke_bias;
|
||||
Label try_rebias;
|
||||
Address mark_addr = Address(obj_reg, 0, oopDesc::mark_offset_in_bytes());
|
||||
Address mark_addr = Address(obj_reg, oopDesc::mark_offset_in_bytes());
|
||||
assert(mark_addr.disp() == 0, "cas must take a zero displacement");
|
||||
|
||||
// At this point we know that the header has the bias pattern and
|
||||
@ -3185,7 +3172,7 @@ void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
|
||||
// FIXME: due to a lack of registers we currently blow away the age
|
||||
// bits in this situation. Should attempt to preserve them.
|
||||
load_klass(obj_reg, temp_reg);
|
||||
ld_ptr(Address(temp_reg, 0, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()), temp_reg);
|
||||
ld_ptr(Address(temp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()), temp_reg);
|
||||
or3(G2_thread, temp_reg, temp_reg);
|
||||
casn(mark_addr.base(), mark_reg, temp_reg);
|
||||
// If the biasing toward our thread failed, this means that
|
||||
@ -3216,7 +3203,7 @@ void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
|
||||
// FIXME: due to a lack of registers we currently blow away the age
|
||||
// bits in this situation. Should attempt to preserve them.
|
||||
load_klass(obj_reg, temp_reg);
|
||||
ld_ptr(Address(temp_reg, 0, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()), temp_reg);
|
||||
ld_ptr(Address(temp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()), temp_reg);
|
||||
casn(mark_addr.base(), mark_reg, temp_reg);
|
||||
// Fall through to the normal CAS-based lock, because no matter what
|
||||
// the result of the above CAS, some thread must have succeeded in
|
||||
@ -3283,7 +3270,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark,
|
||||
Register Rbox, Register Rscratch,
|
||||
BiasedLockingCounters* counters,
|
||||
bool try_bias) {
|
||||
Address mark_addr(Roop, 0, oopDesc::mark_offset_in_bytes());
|
||||
Address mark_addr(Roop, oopDesc::mark_offset_in_bytes());
|
||||
|
||||
verify_oop(Roop);
|
||||
Label done ;
|
||||
@ -3386,7 +3373,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark,
|
||||
// If m->owner != null goto IsLocked
|
||||
// Pessimistic form: Test-and-CAS vs CAS
|
||||
// The optimistic form avoids RTS->RTO cache line upgrades.
|
||||
ld_ptr (Address (Rmark, 0, ObjectMonitor::owner_offset_in_bytes()-2), Rscratch) ;
|
||||
ld_ptr (Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch);
|
||||
andcc (Rscratch, Rscratch, G0) ;
|
||||
brx (Assembler::notZero, false, Assembler::pn, done) ;
|
||||
delayed()->nop() ;
|
||||
@ -3482,7 +3469,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark,
|
||||
// Test-and-CAS vs CAS
|
||||
// Pessimistic form avoids futile (doomed) CAS attempts
|
||||
// The optimistic form avoids RTS->RTO cache line upgrades.
|
||||
ld_ptr (Address (Rmark, 0, ObjectMonitor::owner_offset_in_bytes()-2), Rscratch) ;
|
||||
ld_ptr (Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch);
|
||||
andcc (Rscratch, Rscratch, G0) ;
|
||||
brx (Assembler::notZero, false, Assembler::pn, done) ;
|
||||
delayed()->nop() ;
|
||||
@ -3508,7 +3495,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark,
|
||||
void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark,
|
||||
Register Rbox, Register Rscratch,
|
||||
bool try_bias) {
|
||||
Address mark_addr(Roop, 0, oopDesc::mark_offset_in_bytes());
|
||||
Address mark_addr(Roop, oopDesc::mark_offset_in_bytes());
|
||||
|
||||
Label done ;
|
||||
|
||||
@ -3568,14 +3555,14 @@ void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark,
|
||||
// Note that we use 1-0 locking by default for the inflated case. We
|
||||
// close the resultant (and rare) race by having contented threads in
|
||||
// monitorenter periodically poll _owner.
|
||||
ld_ptr (Address(Rmark, 0, ObjectMonitor::owner_offset_in_bytes()-2), Rscratch) ;
|
||||
ld_ptr (Address(Rmark, 0, ObjectMonitor::recursions_offset_in_bytes()-2), Rbox) ;
|
||||
ld_ptr (Rmark, ObjectMonitor::owner_offset_in_bytes() - 2, Rscratch);
|
||||
ld_ptr (Rmark, ObjectMonitor::recursions_offset_in_bytes() - 2, Rbox);
|
||||
xor3 (Rscratch, G2_thread, Rscratch) ;
|
||||
orcc (Rbox, Rscratch, Rbox) ;
|
||||
brx (Assembler::notZero, false, Assembler::pn, done) ;
|
||||
delayed()->
|
||||
ld_ptr (Address (Rmark, 0, ObjectMonitor::EntryList_offset_in_bytes()-2), Rscratch) ;
|
||||
ld_ptr (Address (Rmark, 0, ObjectMonitor::cxq_offset_in_bytes()-2), Rbox) ;
|
||||
ld_ptr (Rmark, ObjectMonitor::EntryList_offset_in_bytes() - 2, Rscratch);
|
||||
ld_ptr (Rmark, ObjectMonitor::cxq_offset_in_bytes() - 2, Rbox);
|
||||
orcc (Rbox, Rscratch, G0) ;
|
||||
if (EmitSync & 65536) {
|
||||
Label LSucc ;
|
||||
@ -3583,12 +3570,12 @@ void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark,
|
||||
delayed()->nop() ;
|
||||
br (Assembler::always, false, Assembler::pt, done) ;
|
||||
delayed()->
|
||||
st_ptr (G0, Address (Rmark, 0, ObjectMonitor::owner_offset_in_bytes()-2)) ;
|
||||
st_ptr (G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2);
|
||||
|
||||
bind (LSucc) ;
|
||||
st_ptr (G0, Address (Rmark, 0, ObjectMonitor::owner_offset_in_bytes()-2)) ;
|
||||
st_ptr (G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2);
|
||||
if (os::is_MP()) { membar (StoreLoad) ; }
|
||||
ld_ptr (Address (Rmark, 0, ObjectMonitor::succ_offset_in_bytes()-2), Rscratch) ;
|
||||
ld_ptr (Rmark, ObjectMonitor::succ_offset_in_bytes() - 2, Rscratch);
|
||||
andcc (Rscratch, Rscratch, G0) ;
|
||||
brx (Assembler::notZero, false, Assembler::pt, done) ;
|
||||
delayed()-> andcc (G0, G0, G0) ;
|
||||
@ -3606,7 +3593,7 @@ void MacroAssembler::compiler_unlock_object(Register Roop, Register Rmark,
|
||||
delayed()->nop() ;
|
||||
br (Assembler::always, false, Assembler::pt, done) ;
|
||||
delayed()->
|
||||
st_ptr (G0, Address (Rmark, 0, ObjectMonitor::owner_offset_in_bytes()-2)) ;
|
||||
st_ptr (G0, Rmark, ObjectMonitor::owner_offset_in_bytes() - 2);
|
||||
}
|
||||
|
||||
bind (LStacked) ;
|
||||
@ -4005,20 +3992,26 @@ void MacroAssembler::cond_inc(Assembler::Condition cond, address counter_ptr,
|
||||
bind(L);
|
||||
}
|
||||
|
||||
void MacroAssembler::inc_counter(address counter_ptr, Register Rtmp1, Register Rtmp2) {
|
||||
Address counter_addr(Rtmp1, counter_ptr);
|
||||
load_contents(counter_addr, Rtmp2);
|
||||
void MacroAssembler::inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2) {
|
||||
AddressLiteral addrlit(counter_addr);
|
||||
sethi(addrlit, Rtmp1); // Move hi22 bits into temporary register.
|
||||
Address addr(Rtmp1, addrlit.low10()); // Build an address with low10 bits.
|
||||
ld(addr, Rtmp2);
|
||||
inc(Rtmp2);
|
||||
store_contents(Rtmp2, counter_addr);
|
||||
st(Rtmp2, addr);
|
||||
}
|
||||
|
||||
void MacroAssembler::inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2) {
|
||||
inc_counter((address) counter_addr, Rtmp1, Rtmp2);
|
||||
}
|
||||
|
||||
SkipIfEqual::SkipIfEqual(
|
||||
MacroAssembler* masm, Register temp, const bool* flag_addr,
|
||||
Assembler::Condition condition) {
|
||||
_masm = masm;
|
||||
Address flag(temp, (address)flag_addr, relocInfo::none);
|
||||
_masm->sethi(flag);
|
||||
_masm->ldub(flag, temp);
|
||||
AddressLiteral flag(flag_addr);
|
||||
_masm->sethi(flag, temp);
|
||||
_masm->ldub(temp, flag.low10(), temp);
|
||||
_masm->tst(temp);
|
||||
_masm->br(condition, false, Assembler::pt, _label);
|
||||
_masm->delayed()->nop();
|
||||
@ -4333,8 +4326,8 @@ static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) {
|
||||
#else
|
||||
masm.srl(O0, CardTableModRefBS::card_shift, O0);
|
||||
#endif
|
||||
Address rs(O1, (address)byte_map_base);
|
||||
masm.load_address(rs); // O1 := <card table base>
|
||||
AddressLiteral addrlit(byte_map_base);
|
||||
masm.set(addrlit, O1); // O1 := <card table base>
|
||||
masm.ldub(O0, O1, O2); // O2 := [O0 + O1]
|
||||
|
||||
masm.br_on_reg_cond(Assembler::rc_nz, /*annul*/false, Assembler::pt,
|
||||
@ -4494,10 +4487,9 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val
|
||||
#else
|
||||
post_filter_masm->srl(store_addr, CardTableModRefBS::card_shift, store_addr);
|
||||
#endif
|
||||
assert( tmp != store_addr, "need separate temp reg");
|
||||
Address rs(tmp, (address)bs->byte_map_base);
|
||||
load_address(rs);
|
||||
stb(G0, rs.base(), store_addr);
|
||||
assert(tmp != store_addr, "need separate temp reg");
|
||||
set(bs->byte_map_base, tmp);
|
||||
stb(G0, tmp, store_addr);
|
||||
}
|
||||
|
||||
bind(filtered);
|
||||
@ -4516,24 +4508,6 @@ void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_v
|
||||
card_table_write(bs->byte_map_base, tmp, store_addr);
|
||||
}
|
||||
|
||||
// Loading values by size and signed-ness
|
||||
void MacroAssembler::load_sized_value(Register s1, RegisterOrConstant s2, Register d,
|
||||
int size_in_bytes, bool is_signed) {
|
||||
switch (size_in_bytes ^ (is_signed ? -1 : 0)) {
|
||||
case ~8: // fall through:
|
||||
case 8: ld_long( s1, s2, d ); break;
|
||||
case ~4: ldsw( s1, s2, d ); break;
|
||||
case 4: lduw( s1, s2, d ); break;
|
||||
case ~2: ldsh( s1, s2, d ); break;
|
||||
case 2: lduh( s1, s2, d ); break;
|
||||
case ~1: ldsb( s1, s2, d ); break;
|
||||
case 1: ldub( s1, s2, d ); break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MacroAssembler::load_klass(Register src_oop, Register klass) {
|
||||
// The number of bytes in this code is used by
|
||||
// MachCallDynamicJavaNode::ret_addr_offset()
|
||||
@ -4563,12 +4537,12 @@ void MacroAssembler::store_klass_gap(Register s, Register d) {
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::load_heap_oop(const Address& s, Register d, int offset) {
|
||||
void MacroAssembler::load_heap_oop(const Address& s, Register d) {
|
||||
if (UseCompressedOops) {
|
||||
lduw(s, d, offset);
|
||||
lduw(s, d);
|
||||
decode_heap_oop(d);
|
||||
} else {
|
||||
ld_ptr(s, d, offset);
|
||||
ld_ptr(s, d);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4714,7 +4688,7 @@ void MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) {
|
||||
void MacroAssembler::reinit_heapbase() {
|
||||
if (UseCompressedOops) {
|
||||
// call indirectly to solve generation ordering problem
|
||||
Address base(G6_heapbase, (address)Universe::narrow_oop_base_addr());
|
||||
AddressLiteral base(Universe::narrow_oop_base_addr());
|
||||
load_ptr_contents(base, G6_heapbase);
|
||||
}
|
||||
}
|
||||
|
@ -274,21 +274,90 @@ REGISTER_DECLARATION(Register, Oissuing_pc , O1); // where the exception is comi
|
||||
|
||||
class Address VALUE_OBJ_CLASS_SPEC {
|
||||
private:
|
||||
Register _base;
|
||||
#ifdef _LP64
|
||||
int _hi32; // bits 63::32
|
||||
int _low32; // bits 31::0
|
||||
#endif
|
||||
int _hi;
|
||||
int _disp;
|
||||
RelocationHolder _rspec;
|
||||
Register _base; // Base register.
|
||||
RegisterOrConstant _index_or_disp; // Index register or constant displacement.
|
||||
RelocationHolder _rspec;
|
||||
|
||||
RelocationHolder rspec_from_rtype(relocInfo::relocType rt, address a = NULL) {
|
||||
switch (rt) {
|
||||
public:
|
||||
Address() : _base(noreg), _index_or_disp(noreg) {}
|
||||
|
||||
Address(Register base, RegisterOrConstant index_or_disp)
|
||||
: _base(base),
|
||||
_index_or_disp(index_or_disp) {
|
||||
}
|
||||
|
||||
Address(Register base, Register index)
|
||||
: _base(base),
|
||||
_index_or_disp(index) {
|
||||
}
|
||||
|
||||
Address(Register base, int disp)
|
||||
: _base(base),
|
||||
_index_or_disp(disp) {
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
// ByteSize is only a class when ASSERT is defined, otherwise it's an int.
|
||||
Address(Register base, ByteSize disp)
|
||||
: _base(base),
|
||||
_index_or_disp(in_bytes(disp)) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// accessors
|
||||
Register base() const { return _base; }
|
||||
Register index() const { return _index_or_disp.as_register(); }
|
||||
int disp() const { return _index_or_disp.as_constant(); }
|
||||
|
||||
bool has_index() const { return _index_or_disp.is_register(); }
|
||||
bool has_disp() const { return _index_or_disp.is_constant(); }
|
||||
|
||||
const relocInfo::relocType rtype() { return _rspec.type(); }
|
||||
const RelocationHolder& rspec() { return _rspec; }
|
||||
|
||||
RelocationHolder rspec(int offset) const {
|
||||
return offset == 0 ? _rspec : _rspec.plus(offset);
|
||||
}
|
||||
|
||||
inline bool is_simm13(int offset = 0); // check disp+offset for overflow
|
||||
|
||||
Address plus_disp(int plusdisp) const { // bump disp by a small amount
|
||||
assert(_index_or_disp.is_constant(), "must have a displacement");
|
||||
Address a(base(), disp() + plusdisp);
|
||||
return a;
|
||||
}
|
||||
|
||||
Address after_save() const {
|
||||
Address a = (*this);
|
||||
a._base = a._base->after_save();
|
||||
return a;
|
||||
}
|
||||
|
||||
Address after_restore() const {
|
||||
Address a = (*this);
|
||||
a._base = a._base->after_restore();
|
||||
return a;
|
||||
}
|
||||
|
||||
// Convert the raw encoding form into the form expected by the
|
||||
// constructor for Address.
|
||||
static Address make_raw(int base, int index, int scale, int disp, bool disp_is_oop);
|
||||
|
||||
friend class Assembler;
|
||||
};
|
||||
|
||||
|
||||
class AddressLiteral VALUE_OBJ_CLASS_SPEC {
|
||||
private:
|
||||
address _address;
|
||||
RelocationHolder _rspec;
|
||||
|
||||
RelocationHolder rspec_from_rtype(relocInfo::relocType rtype, address addr) {
|
||||
switch (rtype) {
|
||||
case relocInfo::external_word_type:
|
||||
return external_word_Relocation::spec(a);
|
||||
return external_word_Relocation::spec(addr);
|
||||
case relocInfo::internal_word_type:
|
||||
return internal_word_Relocation::spec(a);
|
||||
return internal_word_Relocation::spec(addr);
|
||||
#ifdef _LP64
|
||||
case relocInfo::opt_virtual_call_type:
|
||||
return opt_virtual_call_Relocation::spec();
|
||||
@ -305,127 +374,86 @@ class Address VALUE_OBJ_CLASS_SPEC {
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
// creation
|
||||
AddressLiteral() : _address(NULL), _rspec(NULL) {}
|
||||
|
||||
public:
|
||||
Address(Register b, address a, relocInfo::relocType rt = relocInfo::none)
|
||||
: _rspec(rspec_from_rtype(rt, a))
|
||||
{
|
||||
_base = b;
|
||||
AddressLiteral(address addr, RelocationHolder const& rspec)
|
||||
: _address(addr),
|
||||
_rspec(rspec) {}
|
||||
|
||||
// Some constructors to avoid casting at the call site.
|
||||
AddressLiteral(jobject obj, RelocationHolder const& rspec)
|
||||
: _address((address) obj),
|
||||
_rspec(rspec) {}
|
||||
|
||||
AddressLiteral(intptr_t value, RelocationHolder const& rspec)
|
||||
: _address((address) value),
|
||||
_rspec(rspec) {}
|
||||
|
||||
AddressLiteral(address addr, relocInfo::relocType rtype = relocInfo::none)
|
||||
: _address((address) addr),
|
||||
_rspec(rspec_from_rtype(rtype, (address) addr)) {}
|
||||
|
||||
// Some constructors to avoid casting at the call site.
|
||||
AddressLiteral(address* addr, relocInfo::relocType rtype = relocInfo::none)
|
||||
: _address((address) addr),
|
||||
_rspec(rspec_from_rtype(rtype, (address) addr)) {}
|
||||
|
||||
AddressLiteral(bool* addr, relocInfo::relocType rtype = relocInfo::none)
|
||||
: _address((address) addr),
|
||||
_rspec(rspec_from_rtype(rtype, (address) addr)) {}
|
||||
|
||||
AddressLiteral(const bool* addr, relocInfo::relocType rtype = relocInfo::none)
|
||||
: _address((address) addr),
|
||||
_rspec(rspec_from_rtype(rtype, (address) addr)) {}
|
||||
|
||||
AddressLiteral(signed char* addr, relocInfo::relocType rtype = relocInfo::none)
|
||||
: _address((address) addr),
|
||||
_rspec(rspec_from_rtype(rtype, (address) addr)) {}
|
||||
|
||||
AddressLiteral(int* addr, relocInfo::relocType rtype = relocInfo::none)
|
||||
: _address((address) addr),
|
||||
_rspec(rspec_from_rtype(rtype, (address) addr)) {}
|
||||
|
||||
AddressLiteral(intptr_t addr, relocInfo::relocType rtype = relocInfo::none)
|
||||
: _address((address) addr),
|
||||
_rspec(rspec_from_rtype(rtype, (address) addr)) {}
|
||||
|
||||
#ifdef _LP64
|
||||
_hi32 = (intptr_t)a >> 32; // top 32 bits in 64 bit word
|
||||
_low32 = (intptr_t)a & ~0; // low 32 bits in 64 bit word
|
||||
// 32-bit complains about a multiple declaration for int*.
|
||||
AddressLiteral(intptr_t* addr, relocInfo::relocType rtype = relocInfo::none)
|
||||
: _address((address) addr),
|
||||
_rspec(rspec_from_rtype(rtype, (address) addr)) {}
|
||||
#endif
|
||||
_hi = (intptr_t)a & ~0x3ff; // top 22 bits in low word
|
||||
_disp = (intptr_t)a & 0x3ff; // bottom 10 bits
|
||||
}
|
||||
|
||||
Address(Register b, address a, RelocationHolder const& rspec)
|
||||
: _rspec(rspec)
|
||||
{
|
||||
_base = b;
|
||||
#ifdef _LP64
|
||||
_hi32 = (intptr_t)a >> 32; // top 32 bits in 64 bit word
|
||||
_low32 = (intptr_t)a & ~0; // low 32 bits in 64 bit word
|
||||
#endif
|
||||
_hi = (intptr_t)a & ~0x3ff; // top 22 bits
|
||||
_disp = (intptr_t)a & 0x3ff; // bottom 10 bits
|
||||
}
|
||||
AddressLiteral(oop addr, relocInfo::relocType rtype = relocInfo::none)
|
||||
: _address((address) addr),
|
||||
_rspec(rspec_from_rtype(rtype, (address) addr)) {}
|
||||
|
||||
Address(Register b, intptr_t h, intptr_t d, RelocationHolder const& rspec = RelocationHolder())
|
||||
: _rspec(rspec)
|
||||
{
|
||||
_base = b;
|
||||
#ifdef _LP64
|
||||
// [RGV] Put in Assert to force me to check usage of this constructor
|
||||
assert( h == 0, "Check usage of this constructor" );
|
||||
_hi32 = h;
|
||||
_low32 = d;
|
||||
_hi = h;
|
||||
_disp = d;
|
||||
#else
|
||||
_hi = h;
|
||||
_disp = d;
|
||||
#endif
|
||||
}
|
||||
AddressLiteral(float* addr, relocInfo::relocType rtype = relocInfo::none)
|
||||
: _address((address) addr),
|
||||
_rspec(rspec_from_rtype(rtype, (address) addr)) {}
|
||||
|
||||
Address()
|
||||
: _rspec(RelocationHolder())
|
||||
{
|
||||
_base = G0;
|
||||
#ifdef _LP64
|
||||
_hi32 = 0;
|
||||
_low32 = 0;
|
||||
#endif
|
||||
_hi = 0;
|
||||
_disp = 0;
|
||||
}
|
||||
AddressLiteral(double* addr, relocInfo::relocType rtype = relocInfo::none)
|
||||
: _address((address) addr),
|
||||
_rspec(rspec_from_rtype(rtype, (address) addr)) {}
|
||||
|
||||
// fancier constructors
|
||||
intptr_t value() const { return (intptr_t) _address; }
|
||||
int low10() const;
|
||||
|
||||
enum addr_type {
|
||||
extra_in_argument, // in the In registers
|
||||
extra_out_argument // in the Outs
|
||||
};
|
||||
const relocInfo::relocType rtype() const { return _rspec.type(); }
|
||||
const RelocationHolder& rspec() const { return _rspec; }
|
||||
|
||||
Address( addr_type, int );
|
||||
|
||||
// accessors
|
||||
|
||||
Register base() const { return _base; }
|
||||
#ifdef _LP64
|
||||
int hi32() const { return _hi32; }
|
||||
int low32() const { return _low32; }
|
||||
#endif
|
||||
int hi() const { return _hi; }
|
||||
int disp() const { return _disp; }
|
||||
#ifdef _LP64
|
||||
intptr_t value() const { return ((intptr_t)_hi32 << 32) |
|
||||
(intptr_t)(uint32_t)_low32; }
|
||||
#else
|
||||
int value() const { return _hi | _disp; }
|
||||
#endif
|
||||
const relocInfo::relocType rtype() { return _rspec.type(); }
|
||||
const RelocationHolder& rspec() { return _rspec; }
|
||||
|
||||
RelocationHolder rspec(int offset) const {
|
||||
RelocationHolder rspec(int offset) const {
|
||||
return offset == 0 ? _rspec : _rspec.plus(offset);
|
||||
}
|
||||
|
||||
inline bool is_simm13(int offset = 0); // check disp+offset for overflow
|
||||
|
||||
Address plus_disp(int disp) const { // bump disp by a small amount
|
||||
Address a = (*this);
|
||||
a._disp += disp;
|
||||
return a;
|
||||
}
|
||||
|
||||
Address split_disp() const { // deal with disp overflow
|
||||
Address a = (*this);
|
||||
int hi_disp = _disp & ~0x3ff;
|
||||
if (hi_disp != 0) {
|
||||
a._disp -= hi_disp;
|
||||
a._hi += hi_disp;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
Address after_save() const {
|
||||
Address a = (*this);
|
||||
a._base = a._base->after_save();
|
||||
return a;
|
||||
}
|
||||
|
||||
Address after_restore() const {
|
||||
Address a = (*this);
|
||||
a._base = a._base->after_restore();
|
||||
return a;
|
||||
}
|
||||
|
||||
friend class Assembler;
|
||||
};
|
||||
|
||||
|
||||
inline Address RegisterImpl::address_in_saved_window() const {
|
||||
return (Address(SP, 0, (sp_offset_in_saved_window() * wordSize) + STACK_BIAS));
|
||||
return (Address(SP, (sp_offset_in_saved_window() * wordSize) + STACK_BIAS));
|
||||
}
|
||||
|
||||
|
||||
@ -495,11 +523,7 @@ class Argument VALUE_OBJ_CLASS_SPEC {
|
||||
// When applied to a register-based argument, give the corresponding address
|
||||
// into the 6-word area "into which callee may store register arguments"
|
||||
// (This is a different place than the corresponding register-save area location.)
|
||||
Address address_in_frame() const {
|
||||
return Address( is_in() ? Address::extra_in_argument
|
||||
: Address::extra_out_argument,
|
||||
_number );
|
||||
}
|
||||
Address address_in_frame() const;
|
||||
|
||||
// debugging
|
||||
const char* name() const;
|
||||
@ -521,6 +545,7 @@ class Assembler : public AbstractAssembler {
|
||||
|
||||
|
||||
friend class AbstractAssembler;
|
||||
friend class AddressLiteral;
|
||||
|
||||
// code patchers need various routines like inv_wdisp()
|
||||
friend class NativeInstruction;
|
||||
@ -1093,11 +1118,11 @@ public:
|
||||
|
||||
// pp 135 (addc was addx in v8)
|
||||
|
||||
inline void add( Register s1, Register s2, Register d );
|
||||
inline void add( Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none);
|
||||
inline void add( Register s1, int simm13a, Register d, RelocationHolder const& rspec);
|
||||
inline void add( Register s1, RegisterOrConstant s2, Register d, int offset = 0);
|
||||
inline void add( const Address& a, Register d, int offset = 0);
|
||||
inline void add(Register s1, Register s2, Register d );
|
||||
inline void add(Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none);
|
||||
inline void add(Register s1, int simm13a, Register d, RelocationHolder const& rspec);
|
||||
inline void add(Register s1, RegisterOrConstant s2, Register d, int offset = 0);
|
||||
inline void add(const Address& a, Register d, int offset = 0) { add( a.base(), a.disp() + offset, d, a.rspec(offset)); }
|
||||
|
||||
void addcc( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
|
||||
void addcc( Register s1, int simm13a, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); }
|
||||
@ -1252,14 +1277,12 @@ public:
|
||||
void jmpl( Register s1, Register s2, Register d );
|
||||
void jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec = RelocationHolder() );
|
||||
|
||||
inline void jmpl( Address& a, Register d, int offset = 0);
|
||||
|
||||
// 171
|
||||
|
||||
inline void ldf( FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d );
|
||||
inline void ldf( FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d );
|
||||
inline void ldf(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d);
|
||||
inline void ldf(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d, RelocationHolder const& rspec = RelocationHolder());
|
||||
|
||||
inline void ldf( FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset = 0);
|
||||
inline void ldf(FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset = 0);
|
||||
|
||||
|
||||
inline void ldfsr( Register s1, Register s2 );
|
||||
@ -1303,15 +1326,20 @@ public:
|
||||
inline void ldd( Register s1, Register s2, Register d );
|
||||
inline void ldd( Register s1, int simm13a, Register d);
|
||||
|
||||
inline void ldsb( const Address& a, Register d, int offset = 0 );
|
||||
inline void ldsh( const Address& a, Register d, int offset = 0 );
|
||||
inline void ldsw( const Address& a, Register d, int offset = 0 );
|
||||
inline void ldub( const Address& a, Register d, int offset = 0 );
|
||||
inline void lduh( const Address& a, Register d, int offset = 0 );
|
||||
inline void lduw( const Address& a, Register d, int offset = 0 );
|
||||
inline void ldx( const Address& a, Register d, int offset = 0 );
|
||||
inline void ld( const Address& a, Register d, int offset = 0 );
|
||||
inline void ldd( const Address& a, Register d, int offset = 0 );
|
||||
#ifdef ASSERT
|
||||
// ByteSize is only a class when ASSERT is defined, otherwise it's an int.
|
||||
inline void ld( Register s1, ByteSize simm13a, Register d);
|
||||
#endif
|
||||
|
||||
inline void ldsb(const Address& a, Register d, int offset = 0);
|
||||
inline void ldsh(const Address& a, Register d, int offset = 0);
|
||||
inline void ldsw(const Address& a, Register d, int offset = 0);
|
||||
inline void ldub(const Address& a, Register d, int offset = 0);
|
||||
inline void lduh(const Address& a, Register d, int offset = 0);
|
||||
inline void lduw(const Address& a, Register d, int offset = 0);
|
||||
inline void ldx( const Address& a, Register d, int offset = 0);
|
||||
inline void ld( const Address& a, Register d, int offset = 0);
|
||||
inline void ldd( const Address& a, Register d, int offset = 0);
|
||||
|
||||
inline void ldub( Register s1, RegisterOrConstant s2, Register d );
|
||||
inline void ldsb( Register s1, RegisterOrConstant s2, Register d );
|
||||
@ -1536,6 +1564,11 @@ public:
|
||||
inline void std( Register d, Register s1, Register s2 );
|
||||
inline void std( Register d, Register s1, int simm13a);
|
||||
|
||||
#ifdef ASSERT
|
||||
// ByteSize is only a class when ASSERT is defined, otherwise it's an int.
|
||||
inline void st( Register d, Register s1, ByteSize simm13a);
|
||||
#endif
|
||||
|
||||
inline void stb( Register d, const Address& a, int offset = 0 );
|
||||
inline void sth( Register d, const Address& a, int offset = 0 );
|
||||
inline void stw( Register d, const Address& a, int offset = 0 );
|
||||
@ -1684,8 +1717,8 @@ class RegistersForDebugging : public StackObj {
|
||||
|
||||
#define JMP2(r1, r2) jmp(r1, r2, __FILE__, __LINE__)
|
||||
#define JMP(r1, off) jmp(r1, off, __FILE__, __LINE__)
|
||||
#define JUMP(a, off) jump(a, off, __FILE__, __LINE__)
|
||||
#define JUMPL(a, d, off) jumpl(a, d, off, __FILE__, __LINE__)
|
||||
#define JUMP(a, temp, off) jump(a, temp, off, __FILE__, __LINE__)
|
||||
#define JUMPL(a, temp, d, off) jumpl(a, temp, d, off, __FILE__, __LINE__)
|
||||
|
||||
|
||||
class MacroAssembler: public Assembler {
|
||||
@ -1830,17 +1863,26 @@ class MacroAssembler: public Assembler {
|
||||
#endif
|
||||
|
||||
// sethi Macro handles optimizations and relocations
|
||||
void sethi( Address& a, bool ForceRelocatable = false );
|
||||
void sethi( intptr_t imm22a, Register d, bool ForceRelocatable = false, RelocationHolder const& rspec = RelocationHolder());
|
||||
private:
|
||||
void internal_sethi(const AddressLiteral& addrlit, Register d, bool ForceRelocatable);
|
||||
public:
|
||||
void sethi(const AddressLiteral& addrlit, Register d);
|
||||
void patchable_sethi(const AddressLiteral& addrlit, Register d);
|
||||
|
||||
// compute the size of a sethi/set
|
||||
static int size_of_sethi( address a, bool worst_case = false );
|
||||
static int worst_case_size_of_set();
|
||||
|
||||
// set may be either setsw or setuw (high 32 bits may be zero or sign)
|
||||
void set( intptr_t value, Register d, RelocationHolder const& rspec = RelocationHolder() );
|
||||
void setsw( int value, Register d, RelocationHolder const& rspec = RelocationHolder() );
|
||||
void set64( jlong value, Register d, Register tmp);
|
||||
private:
|
||||
void internal_set(const AddressLiteral& al, Register d, bool ForceRelocatable);
|
||||
public:
|
||||
void set(const AddressLiteral& addrlit, Register d);
|
||||
void set(intptr_t value, Register d);
|
||||
void set(address addr, Register d, RelocationHolder const& rspec);
|
||||
void patchable_set(const AddressLiteral& addrlit, Register d);
|
||||
void patchable_set(intptr_t value, Register d);
|
||||
void set64(jlong value, Register d, Register tmp);
|
||||
|
||||
// sign-extend 32 to 64
|
||||
inline void signx( Register s, Register d ) { sra( s, G0, d); }
|
||||
@ -1930,24 +1972,22 @@ class MacroAssembler: public Assembler {
|
||||
inline void mov( int simm13a, Register d) { or3( G0, simm13a, d); }
|
||||
|
||||
// address pseudos: make these names unlike instruction names to avoid confusion
|
||||
inline void split_disp( Address& a, Register temp );
|
||||
inline intptr_t load_pc_address( Register reg, int bytes_to_skip );
|
||||
inline void load_address( Address& a, int offset = 0 );
|
||||
inline void load_contents( Address& a, Register d, int offset = 0 );
|
||||
inline void load_ptr_contents( Address& a, Register d, int offset = 0 );
|
||||
inline void store_contents( Register s, Address& a, int offset = 0 );
|
||||
inline void store_ptr_contents( Register s, Address& a, int offset = 0 );
|
||||
inline void jumpl_to( Address& a, Register d, int offset = 0 );
|
||||
inline void jump_to( Address& a, int offset = 0 );
|
||||
inline void jump_indirect_to( Address& a, Register temp, int ld_offset = 0, int jmp_offset = 0 );
|
||||
inline void load_contents(AddressLiteral& addrlit, Register d, int offset = 0);
|
||||
inline void load_ptr_contents(AddressLiteral& addrlit, Register d, int offset = 0);
|
||||
inline void store_contents(Register s, AddressLiteral& addrlit, Register temp, int offset = 0);
|
||||
inline void store_ptr_contents(Register s, AddressLiteral& addrlit, Register temp, int offset = 0);
|
||||
inline void jumpl_to(AddressLiteral& addrlit, Register temp, Register d, int offset = 0);
|
||||
inline void jump_to(AddressLiteral& addrlit, Register temp, int offset = 0);
|
||||
inline void jump_indirect_to(Address& a, Register temp, int ld_offset = 0, int jmp_offset = 0);
|
||||
|
||||
// ring buffer traceable jumps
|
||||
|
||||
void jmp2( Register r1, Register r2, const char* file, int line );
|
||||
void jmp ( Register r1, int offset, const char* file, int line );
|
||||
|
||||
void jumpl( Address& a, Register d, int offset, const char* file, int line );
|
||||
void jump ( Address& a, int offset, const char* file, int line );
|
||||
void jumpl(AddressLiteral& addrlit, Register temp, Register d, int offset, const char* file, int line);
|
||||
void jump (AddressLiteral& addrlit, Register temp, int offset, const char* file, int line);
|
||||
|
||||
|
||||
// argument pseudos:
|
||||
@ -1972,29 +2012,31 @@ class MacroAssembler: public Assembler {
|
||||
// Functions for isolating 64 bit loads for LP64
|
||||
// ld_ptr will perform ld for 32 bit VM's and ldx for 64 bit VM's
|
||||
// st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's
|
||||
inline void ld_ptr( Register s1, Register s2, Register d );
|
||||
inline void ld_ptr( Register s1, int simm13a, Register d);
|
||||
inline void ld_ptr( Register s1, RegisterOrConstant s2, Register d );
|
||||
inline void ld_ptr( const Address& a, Register d, int offset = 0 );
|
||||
inline void st_ptr( Register d, Register s1, Register s2 );
|
||||
inline void st_ptr( Register d, Register s1, int simm13a);
|
||||
inline void st_ptr( Register d, Register s1, RegisterOrConstant s2 );
|
||||
inline void st_ptr( Register d, const Address& a, int offset = 0 );
|
||||
inline void ld_ptr(Register s1, Register s2, Register d);
|
||||
inline void ld_ptr(Register s1, int simm13a, Register d);
|
||||
inline void ld_ptr(Register s1, RegisterOrConstant s2, Register d);
|
||||
inline void ld_ptr(const Address& a, Register d, int offset = 0);
|
||||
inline void st_ptr(Register d, Register s1, Register s2);
|
||||
inline void st_ptr(Register d, Register s1, int simm13a);
|
||||
inline void st_ptr(Register d, Register s1, RegisterOrConstant s2);
|
||||
inline void st_ptr(Register d, const Address& a, int offset = 0);
|
||||
|
||||
#ifdef ASSERT
|
||||
// ByteSize is only a class when ASSERT is defined, otherwise it's an int.
|
||||
inline void ld_ptr(Register s1, ByteSize simm13a, Register d);
|
||||
inline void st_ptr(Register d, Register s1, ByteSize simm13a);
|
||||
#endif
|
||||
|
||||
// ld_long will perform ld for 32 bit VM's and ldx for 64 bit VM's
|
||||
// st_long will perform st for 32 bit VM's and stx for 64 bit VM's
|
||||
inline void ld_long( Register s1, Register s2, Register d );
|
||||
inline void ld_long( Register s1, int simm13a, Register d );
|
||||
inline void ld_long( Register s1, RegisterOrConstant s2, Register d );
|
||||
inline void ld_long( const Address& a, Register d, int offset = 0 );
|
||||
inline void st_long( Register d, Register s1, Register s2 );
|
||||
inline void st_long( Register d, Register s1, int simm13a );
|
||||
inline void st_long( Register d, Register s1, RegisterOrConstant s2 );
|
||||
inline void st_long( Register d, const Address& a, int offset = 0 );
|
||||
|
||||
// Loading values by size and signed-ness
|
||||
void load_sized_value(Register s1, RegisterOrConstant s2, Register d,
|
||||
int size_in_bytes, bool is_signed);
|
||||
inline void ld_long(Register s1, Register s2, Register d);
|
||||
inline void ld_long(Register s1, int simm13a, Register d);
|
||||
inline void ld_long(Register s1, RegisterOrConstant s2, Register d);
|
||||
inline void ld_long(const Address& a, Register d, int offset = 0);
|
||||
inline void st_long(Register d, Register s1, Register s2);
|
||||
inline void st_long(Register d, Register s1, int simm13a);
|
||||
inline void st_long(Register d, Register s1, RegisterOrConstant s2);
|
||||
inline void st_long(Register d, const Address& a, int offset = 0);
|
||||
|
||||
// Helpers for address formation.
|
||||
// They update the dest in place, whether it is a register or constant.
|
||||
@ -2049,8 +2091,8 @@ class MacroAssembler: public Assembler {
|
||||
// These are idioms to flag the need for care with accessing bools but on
|
||||
// this platform we assume byte size
|
||||
|
||||
inline void stbool( Register d, const Address& a, int offset = 0 ) { stb(d, a, offset); }
|
||||
inline void ldbool( const Address& a, Register d, int offset = 0 ) { ldsb( a, d, offset ); }
|
||||
inline void stbool(Register d, const Address& a) { stb(d, a); }
|
||||
inline void ldbool(const Address& a, Register d) { ldsb(a, d); }
|
||||
inline void tstbool( Register s ) { tst(s); }
|
||||
inline void movbool( bool boolconst, Register d) { mov( (int) boolconst, d); }
|
||||
|
||||
@ -2060,7 +2102,7 @@ class MacroAssembler: public Assembler {
|
||||
void store_klass_gap(Register s, Register dst_oop);
|
||||
|
||||
// oop manipulations
|
||||
void load_heap_oop(const Address& s, Register d, int offset = 0);
|
||||
void load_heap_oop(const Address& s, Register d);
|
||||
void load_heap_oop(Register s1, Register s2, Register d);
|
||||
void load_heap_oop(Register s1, int simm13a, Register d);
|
||||
void store_heap_oop(Register d, Register s1, Register s2);
|
||||
@ -2190,11 +2232,11 @@ class MacroAssembler: public Assembler {
|
||||
void print_CPU_state();
|
||||
|
||||
// oops in code
|
||||
Address allocate_oop_address( jobject obj, Register d ); // allocate_index
|
||||
Address constant_oop_address( jobject obj, Register d ); // find_index
|
||||
inline void set_oop ( jobject obj, Register d ); // uses allocate_oop_address
|
||||
inline void set_oop_constant( jobject obj, Register d ); // uses constant_oop_address
|
||||
inline void set_oop ( Address obj_addr ); // same as load_address
|
||||
AddressLiteral allocate_oop_address(jobject obj); // allocate_index
|
||||
AddressLiteral constant_oop_address(jobject obj); // find_index
|
||||
inline void set_oop (jobject obj, Register d); // uses allocate_oop_address
|
||||
inline void set_oop_constant (jobject obj, Register d); // uses constant_oop_address
|
||||
inline void set_oop (AddressLiteral& obj_addr, Register d); // same as load_address
|
||||
|
||||
void set_narrow_oop( jobject obj, Register d );
|
||||
|
||||
@ -2410,7 +2452,8 @@ class MacroAssembler: public Assembler {
|
||||
// Conditionally (non-atomically) increments passed counter address, preserving condition codes.
|
||||
void cond_inc(Condition cond, address counter_addr, Register Rtemp1, Register Rtemp2);
|
||||
// Unconditional increment.
|
||||
void inc_counter(address counter_addr, Register Rtemp1, Register Rtemp2);
|
||||
void inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2);
|
||||
void inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2);
|
||||
|
||||
#undef VIRTUAL
|
||||
|
||||
|
@ -38,6 +38,11 @@ inline void MacroAssembler::pd_print_patched_instruction(address branch) {
|
||||
inline bool Address::is_simm13(int offset) { return Assembler::is_simm13(disp() + offset); }
|
||||
|
||||
|
||||
inline int AddressLiteral::low10() const {
|
||||
return Assembler::low10(value());
|
||||
}
|
||||
|
||||
|
||||
// inlines for SPARC assembler -- dmu 5/97
|
||||
|
||||
inline void Assembler::check_delay() {
|
||||
@ -63,10 +68,9 @@ inline void Assembler::emit_data(int x, RelocationHolder const& rspec) {
|
||||
}
|
||||
|
||||
|
||||
inline void Assembler::add( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::add( Register s1, int simm13a, Register d, relocInfo::relocType rtype ) { emit_data( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rtype ); }
|
||||
inline void Assembler::add( Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { emit_data( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec ); }
|
||||
inline void Assembler::add( const Address& a, Register d, int offset) { add( a.base(), a.disp() + offset, d, a.rspec(offset)); }
|
||||
inline void Assembler::add(Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::add(Register s1, int simm13a, Register d, relocInfo::relocType rtype ) { emit_data( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rtype ); }
|
||||
inline void Assembler::add(Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { emit_data( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec ); }
|
||||
|
||||
inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt ) { v9_only(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bpr_op2) | wdisp16(intptr_t(d), intptr_t(pc())) | predict(p) | rs1(s1), rt); has_delay_slot(); }
|
||||
inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, Label& L) { bpr( c, a, p, s1, target(L)); }
|
||||
@ -95,13 +99,10 @@ inline void Assembler::flush( Register s1, int simm13a) { emit_data( op(arith_op
|
||||
inline void Assembler::jmpl( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); }
|
||||
inline void Assembler::jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { emit_data( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); has_delay_slot(); }
|
||||
|
||||
inline void Assembler::jmpl( Address& a, Register d, int offset) { jmpl( a.base(), a.disp() + offset, d, a.rspec(offset)); }
|
||||
inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { emit_long( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d, RelocationHolder const& rspec) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); }
|
||||
|
||||
|
||||
inline void Assembler::ldf( FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { emit_long( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldf( FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
inline void Assembler::ldf( FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset) { relocate(a.rspec(offset)); ldf( w, a.base(), a.disp() + offset, d); }
|
||||
inline void Assembler::ldf(FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset) { relocate(a.rspec(offset)); ldf( w, a.base(), a.disp() + offset, d); }
|
||||
|
||||
inline void Assembler::ldfsr( Register s1, Register s2) { v9_dep(); emit_long( op(ldst_op) | op3(ldfsr_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldfsr( Register s1, int simm13a) { v9_dep(); emit_data( op(ldst_op) | op3(ldfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
@ -136,50 +137,69 @@ inline void Assembler::ldd( Register s1, int simm13a, Register d) { v9_dep();
|
||||
|
||||
#ifdef _LP64
|
||||
// Make all 32 bit loads signed so 64 bit registers maintain proper sign
|
||||
inline void Assembler::ld( Register s1, Register s2, Register d) { ldsw( s1, s2, d); }
|
||||
inline void Assembler::ld( Register s1, int simm13a, Register d) { ldsw( s1, simm13a, d); }
|
||||
inline void Assembler::ld( Register s1, Register s2, Register d) { ldsw( s1, s2, d); }
|
||||
inline void Assembler::ld( Register s1, int simm13a, Register d) { ldsw( s1, simm13a, d); }
|
||||
#else
|
||||
inline void Assembler::ld( Register s1, Register s2, Register d) { lduw( s1, s2, d); }
|
||||
inline void Assembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); }
|
||||
inline void Assembler::ld( Register s1, Register s2, Register d) { lduw( s1, s2, d); }
|
||||
inline void Assembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); }
|
||||
#endif
|
||||
|
||||
inline void Assembler::ldub( Register s1, RegisterOrConstant s2, Register d) {
|
||||
if (s2.is_register()) ldsb(s1, s2.as_register(), d);
|
||||
else ldsb(s1, s2.as_constant(), d);
|
||||
#ifdef ASSERT
|
||||
// ByteSize is only a class when ASSERT is defined, otherwise it's an int.
|
||||
# ifdef _LP64
|
||||
inline void Assembler::ld( Register s1, ByteSize simm13a, Register d) { ldsw( s1, in_bytes(simm13a), d); }
|
||||
# else
|
||||
inline void Assembler::ld( Register s1, ByteSize simm13a, Register d) { lduw( s1, in_bytes(simm13a), d); }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
inline void Assembler::ld( const Address& a, Register d, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); ld( a.base(), a.index(), d); }
|
||||
else { ld( a.base(), a.disp() + offset, d); }
|
||||
}
|
||||
inline void Assembler::ldsb( Register s1, RegisterOrConstant s2, Register d) {
|
||||
if (s2.is_register()) ldsb(s1, s2.as_register(), d);
|
||||
else ldsb(s1, s2.as_constant(), d);
|
||||
inline void Assembler::ldsb(const Address& a, Register d, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); ldsb(a.base(), a.index(), d); }
|
||||
else { ldsb(a.base(), a.disp() + offset, d); }
|
||||
}
|
||||
inline void Assembler::lduh( Register s1, RegisterOrConstant s2, Register d) {
|
||||
if (s2.is_register()) ldsh(s1, s2.as_register(), d);
|
||||
else ldsh(s1, s2.as_constant(), d);
|
||||
inline void Assembler::ldsh(const Address& a, Register d, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); ldsh(a.base(), a.index(), d); }
|
||||
else { ldsh(a.base(), a.disp() + offset, d); }
|
||||
}
|
||||
inline void Assembler::ldsh( Register s1, RegisterOrConstant s2, Register d) {
|
||||
if (s2.is_register()) ldsh(s1, s2.as_register(), d);
|
||||
else ldsh(s1, s2.as_constant(), d);
|
||||
inline void Assembler::ldsw(const Address& a, Register d, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); ldsw(a.base(), a.index(), d); }
|
||||
else { ldsw(a.base(), a.disp() + offset, d); }
|
||||
}
|
||||
inline void Assembler::lduw( Register s1, RegisterOrConstant s2, Register d) {
|
||||
if (s2.is_register()) ldsw(s1, s2.as_register(), d);
|
||||
else ldsw(s1, s2.as_constant(), d);
|
||||
inline void Assembler::ldub(const Address& a, Register d, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); ldub(a.base(), a.index(), d); }
|
||||
else { ldub(a.base(), a.disp() + offset, d); }
|
||||
}
|
||||
inline void Assembler::ldsw( Register s1, RegisterOrConstant s2, Register d) {
|
||||
if (s2.is_register()) ldsw(s1, s2.as_register(), d);
|
||||
else ldsw(s1, s2.as_constant(), d);
|
||||
inline void Assembler::lduh(const Address& a, Register d, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); lduh(a.base(), a.index(), d); }
|
||||
else { lduh(a.base(), a.disp() + offset, d); }
|
||||
}
|
||||
inline void Assembler::ldx( Register s1, RegisterOrConstant s2, Register d) {
|
||||
if (s2.is_register()) ldx(s1, s2.as_register(), d);
|
||||
else ldx(s1, s2.as_constant(), d);
|
||||
inline void Assembler::lduw(const Address& a, Register d, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); lduw(a.base(), a.index(), d); }
|
||||
else { lduw(a.base(), a.disp() + offset, d); }
|
||||
}
|
||||
inline void Assembler::ld( Register s1, RegisterOrConstant s2, Register d) {
|
||||
if (s2.is_register()) ld(s1, s2.as_register(), d);
|
||||
else ld(s1, s2.as_constant(), d);
|
||||
inline void Assembler::ldd( const Address& a, Register d, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); ldd( a.base(), a.index(), d); }
|
||||
else { ldd( a.base(), a.disp() + offset, d); }
|
||||
}
|
||||
inline void Assembler::ldd( Register s1, RegisterOrConstant s2, Register d) {
|
||||
if (s2.is_register()) ldd(s1, s2.as_register(), d);
|
||||
else ldd(s1, s2.as_constant(), d);
|
||||
inline void Assembler::ldx( const Address& a, Register d, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); ldx( a.base(), a.index(), d); }
|
||||
else { ldx( a.base(), a.disp() + offset, d); }
|
||||
}
|
||||
|
||||
inline void Assembler::ldub(Register s1, RegisterOrConstant s2, Register d) { ldub(Address(s1, s2), d); }
|
||||
inline void Assembler::ldsb(Register s1, RegisterOrConstant s2, Register d) { ldsb(Address(s1, s2), d); }
|
||||
inline void Assembler::lduh(Register s1, RegisterOrConstant s2, Register d) { lduh(Address(s1, s2), d); }
|
||||
inline void Assembler::ldsh(Register s1, RegisterOrConstant s2, Register d) { ldsh(Address(s1, s2), d); }
|
||||
inline void Assembler::lduw(Register s1, RegisterOrConstant s2, Register d) { lduw(Address(s1, s2), d); }
|
||||
inline void Assembler::ldsw(Register s1, RegisterOrConstant s2, Register d) { ldsw(Address(s1, s2), d); }
|
||||
inline void Assembler::ldx( Register s1, RegisterOrConstant s2, Register d) { ldx( Address(s1, s2), d); }
|
||||
inline void Assembler::ld( Register s1, RegisterOrConstant s2, Register d) { ld( Address(s1, s2), d); }
|
||||
inline void Assembler::ldd( Register s1, RegisterOrConstant s2, Register d) { ldd( Address(s1, s2), d); }
|
||||
|
||||
// form effective addresses this way:
|
||||
inline void Assembler::add( Register s1, RegisterOrConstant s2, Register d, int offset) {
|
||||
if (s2.is_register()) add(s1, s2.as_register(), d);
|
||||
@ -187,17 +207,6 @@ inline void Assembler::add( Register s1, RegisterOrConstant s2, Register d, in
|
||||
if (offset != 0) add(d, offset, d);
|
||||
}
|
||||
|
||||
inline void Assembler::ld( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ld( a.base(), a.disp() + offset, d ); }
|
||||
inline void Assembler::ldsb( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldsb( a.base(), a.disp() + offset, d ); }
|
||||
inline void Assembler::ldsh( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldsh( a.base(), a.disp() + offset, d ); }
|
||||
inline void Assembler::ldsw( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldsw( a.base(), a.disp() + offset, d ); }
|
||||
inline void Assembler::ldub( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldub( a.base(), a.disp() + offset, d ); }
|
||||
inline void Assembler::lduh( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); lduh( a.base(), a.disp() + offset, d ); }
|
||||
inline void Assembler::lduw( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); lduw( a.base(), a.disp() + offset, d ); }
|
||||
inline void Assembler::ldd( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldd( a.base(), a.disp() + offset, d ); }
|
||||
inline void Assembler::ldx( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldx( a.base(), a.disp() + offset, d ); }
|
||||
|
||||
|
||||
inline void Assembler::ldstub( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldstub_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::ldstub( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldstub_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
@ -240,36 +249,44 @@ inline void Assembler::stx( Register d, Register s1, int simm13a) { v9_only();
|
||||
inline void Assembler::std( Register d, Register s1, Register s2) { v9_dep(); assert(d->is_even(), "not even"); emit_long( op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | rs2(s2) ); }
|
||||
inline void Assembler::std( Register d, Register s1, int simm13a) { v9_dep(); assert(d->is_even(), "not even"); emit_data( op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); }
|
||||
|
||||
inline void Assembler::st( Register d, Register s1, Register s2) { stw(d, s1, s2); }
|
||||
inline void Assembler::st( Register d, Register s1, int simm13a) { stw(d, s1, simm13a); }
|
||||
inline void Assembler::st( Register d, Register s1, Register s2) { stw(d, s1, s2); }
|
||||
inline void Assembler::st( Register d, Register s1, int simm13a) { stw(d, s1, simm13a); }
|
||||
|
||||
inline void Assembler::stb( Register d, Register s1, RegisterOrConstant s2) {
|
||||
if (s2.is_register()) stb(d, s1, s2.as_register());
|
||||
else stb(d, s1, s2.as_constant());
|
||||
#ifdef ASSERT
|
||||
// ByteSize is only a class when ASSERT is defined, otherwise it's an int.
|
||||
inline void Assembler::st( Register d, Register s1, ByteSize simm13a) { stw(d, s1, in_bytes(simm13a)); }
|
||||
#endif
|
||||
|
||||
inline void Assembler::stb(Register d, const Address& a, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); stb(d, a.base(), a.index() ); }
|
||||
else { stb(d, a.base(), a.disp() + offset); }
|
||||
}
|
||||
inline void Assembler::sth( Register d, Register s1, RegisterOrConstant s2) {
|
||||
if (s2.is_register()) sth(d, s1, s2.as_register());
|
||||
else sth(d, s1, s2.as_constant());
|
||||
inline void Assembler::sth(Register d, const Address& a, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); sth(d, a.base(), a.index() ); }
|
||||
else { sth(d, a.base(), a.disp() + offset); }
|
||||
}
|
||||
inline void Assembler::stx( Register d, Register s1, RegisterOrConstant s2) {
|
||||
if (s2.is_register()) stx(d, s1, s2.as_register());
|
||||
else stx(d, s1, s2.as_constant());
|
||||
inline void Assembler::stw(Register d, const Address& a, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); stw(d, a.base(), a.index() ); }
|
||||
else { stw(d, a.base(), a.disp() + offset); }
|
||||
}
|
||||
inline void Assembler::std( Register d, Register s1, RegisterOrConstant s2) {
|
||||
if (s2.is_register()) std(d, s1, s2.as_register());
|
||||
else std(d, s1, s2.as_constant());
|
||||
inline void Assembler::st( Register d, const Address& a, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); st( d, a.base(), a.index() ); }
|
||||
else { st( d, a.base(), a.disp() + offset); }
|
||||
}
|
||||
inline void Assembler::st( Register d, Register s1, RegisterOrConstant s2) {
|
||||
if (s2.is_register()) st(d, s1, s2.as_register());
|
||||
else st(d, s1, s2.as_constant());
|
||||
inline void Assembler::std(Register d, const Address& a, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); std(d, a.base(), a.index() ); }
|
||||
else { std(d, a.base(), a.disp() + offset); }
|
||||
}
|
||||
inline void Assembler::stx(Register d, const Address& a, int offset) {
|
||||
if (a.has_index()) { assert(offset == 0, ""); stx(d, a.base(), a.index() ); }
|
||||
else { stx(d, a.base(), a.disp() + offset); }
|
||||
}
|
||||
|
||||
inline void Assembler::stb( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stb( d, a.base(), a.disp() + offset); }
|
||||
inline void Assembler::sth( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); sth( d, a.base(), a.disp() + offset); }
|
||||
inline void Assembler::stw( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stw( d, a.base(), a.disp() + offset); }
|
||||
inline void Assembler::st( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); st( d, a.base(), a.disp() + offset); }
|
||||
inline void Assembler::std( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); std( d, a.base(), a.disp() + offset); }
|
||||
inline void Assembler::stx( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stx( d, a.base(), a.disp() + offset); }
|
||||
inline void Assembler::stb(Register d, Register s1, RegisterOrConstant s2) { stb(d, Address(s1, s2)); }
|
||||
inline void Assembler::sth(Register d, Register s1, RegisterOrConstant s2) { sth(d, Address(s1, s2)); }
|
||||
inline void Assembler::stx(Register d, Register s1, RegisterOrConstant s2) { stx(d, Address(s1, s2)); }
|
||||
inline void Assembler::std(Register d, Register s1, RegisterOrConstant s2) { std(d, Address(s1, s2)); }
|
||||
inline void Assembler::st( Register d, Register s1, RegisterOrConstant s2) { st( d, Address(s1, s2)); }
|
||||
|
||||
// v8 p 99
|
||||
|
||||
@ -294,39 +311,46 @@ inline void Assembler::swap( Address& a, Register d, int offset ) { relocate(
|
||||
// Use the right loads/stores for the platform
|
||||
inline void MacroAssembler::ld_ptr( Register s1, Register s2, Register d ) {
|
||||
#ifdef _LP64
|
||||
Assembler::ldx( s1, s2, d);
|
||||
Assembler::ldx(s1, s2, d);
|
||||
#else
|
||||
Assembler::ld( s1, s2, d);
|
||||
Assembler::ld( s1, s2, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::ld_ptr( Register s1, int simm13a, Register d ) {
|
||||
#ifdef _LP64
|
||||
Assembler::ldx( s1, simm13a, d);
|
||||
Assembler::ldx(s1, simm13a, d);
|
||||
#else
|
||||
Assembler::ld( s1, simm13a, d);
|
||||
Assembler::ld( s1, simm13a, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
// ByteSize is only a class when ASSERT is defined, otherwise it's an int.
|
||||
inline void MacroAssembler::ld_ptr( Register s1, ByteSize simm13a, Register d ) {
|
||||
ld_ptr(s1, in_bytes(simm13a), d);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void MacroAssembler::ld_ptr( Register s1, RegisterOrConstant s2, Register d ) {
|
||||
#ifdef _LP64
|
||||
Assembler::ldx( s1, s2, d);
|
||||
Assembler::ldx(s1, s2, d);
|
||||
#else
|
||||
Assembler::ld( s1, s2, d);
|
||||
Assembler::ld( s1, s2, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::ld_ptr( const Address& a, Register d, int offset ) {
|
||||
inline void MacroAssembler::ld_ptr(const Address& a, Register d, int offset) {
|
||||
#ifdef _LP64
|
||||
Assembler::ldx( a, d, offset );
|
||||
Assembler::ldx(a, d, offset);
|
||||
#else
|
||||
Assembler::ld( a, d, offset );
|
||||
Assembler::ld( a, d, offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::st_ptr( Register d, Register s1, Register s2 ) {
|
||||
#ifdef _LP64
|
||||
Assembler::stx( d, s1, s2);
|
||||
Assembler::stx(d, s1, s2);
|
||||
#else
|
||||
Assembler::st( d, s1, s2);
|
||||
#endif
|
||||
@ -334,25 +358,32 @@ inline void MacroAssembler::st_ptr( Register d, Register s1, Register s2 ) {
|
||||
|
||||
inline void MacroAssembler::st_ptr( Register d, Register s1, int simm13a ) {
|
||||
#ifdef _LP64
|
||||
Assembler::stx( d, s1, simm13a);
|
||||
Assembler::stx(d, s1, simm13a);
|
||||
#else
|
||||
Assembler::st( d, s1, simm13a);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
// ByteSize is only a class when ASSERT is defined, otherwise it's an int.
|
||||
inline void MacroAssembler::st_ptr( Register d, Register s1, ByteSize simm13a ) {
|
||||
st_ptr(d, s1, in_bytes(simm13a));
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterOrConstant s2 ) {
|
||||
#ifdef _LP64
|
||||
Assembler::stx( d, s1, s2);
|
||||
Assembler::stx(d, s1, s2);
|
||||
#else
|
||||
Assembler::st( d, s1, s2);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::st_ptr( Register d, const Address& a, int offset) {
|
||||
inline void MacroAssembler::st_ptr(Register d, const Address& a, int offset) {
|
||||
#ifdef _LP64
|
||||
Assembler::stx( d, a, offset);
|
||||
Assembler::stx(d, a, offset);
|
||||
#else
|
||||
Assembler::st( d, a, offset);
|
||||
Assembler::st( d, a, offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -381,11 +412,11 @@ inline void MacroAssembler::ld_long( Register s1, RegisterOrConstant s2, Registe
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void MacroAssembler::ld_long( const Address& a, Register d, int offset ) {
|
||||
inline void MacroAssembler::ld_long(const Address& a, Register d, int offset) {
|
||||
#ifdef _LP64
|
||||
Assembler::ldx(a, d, offset );
|
||||
Assembler::ldx(a, d, offset);
|
||||
#else
|
||||
Assembler::ldd(a, d, offset );
|
||||
Assembler::ldd(a, d, offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -427,7 +458,7 @@ inline void MacroAssembler::sll_ptr( Register s1, Register s2, Register d ) {
|
||||
#ifdef _LP64
|
||||
Assembler::sllx(s1, s2, d);
|
||||
#else
|
||||
Assembler::sll(s1, s2, d);
|
||||
Assembler::sll( s1, s2, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -435,7 +466,7 @@ inline void MacroAssembler::sll_ptr( Register s1, int imm6a, Register d ) {
|
||||
#ifdef _LP64
|
||||
Assembler::sllx(s1, imm6a, d);
|
||||
#else
|
||||
Assembler::sll(s1, imm6a, d);
|
||||
Assembler::sll( s1, imm6a, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -443,7 +474,7 @@ inline void MacroAssembler::srl_ptr( Register s1, Register s2, Register d ) {
|
||||
#ifdef _LP64
|
||||
Assembler::srlx(s1, s2, d);
|
||||
#else
|
||||
Assembler::srl(s1, s2, d);
|
||||
Assembler::srl( s1, s2, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -451,7 +482,7 @@ inline void MacroAssembler::srl_ptr( Register s1, int imm6a, Register d ) {
|
||||
#ifdef _LP64
|
||||
Assembler::srlx(s1, imm6a, d);
|
||||
#else
|
||||
Assembler::srl(s1, imm6a, d);
|
||||
Assembler::srl( s1, imm6a, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -541,9 +572,8 @@ inline void MacroAssembler::call( address d, relocInfo::relocType rt ) {
|
||||
disp = (intptr_t)d - (intptr_t)pc();
|
||||
if ( disp != (intptr_t)(int32_t)disp ) {
|
||||
relocate(rt);
|
||||
Address dest(O7, (address)d);
|
||||
sethi(dest, /*ForceRelocatable=*/ true);
|
||||
jmpl(dest, O7);
|
||||
AddressLiteral dest(d);
|
||||
jumpl_to(dest, O7, O7);
|
||||
}
|
||||
else {
|
||||
Assembler::call( d, rt );
|
||||
@ -603,96 +633,72 @@ inline intptr_t MacroAssembler::load_pc_address( Register reg, int bytes_to_skip
|
||||
return thepc;
|
||||
}
|
||||
|
||||
inline void MacroAssembler::load_address( Address& a, int offset ) {
|
||||
|
||||
inline void MacroAssembler::load_contents(AddressLiteral& addrlit, Register d, int offset) {
|
||||
assert_not_delayed();
|
||||
#ifdef _LP64
|
||||
sethi(a);
|
||||
add(a, a.base(), offset);
|
||||
#else
|
||||
if (a.hi() == 0 && a.rtype() == relocInfo::none) {
|
||||
set(a.disp() + offset, a.base());
|
||||
}
|
||||
else {
|
||||
sethi(a);
|
||||
add(a, a.base(), offset);
|
||||
}
|
||||
#endif
|
||||
sethi(addrlit, d);
|
||||
ld(d, addrlit.low10() + offset, d);
|
||||
}
|
||||
|
||||
|
||||
inline void MacroAssembler::split_disp( Address& a, Register temp ) {
|
||||
inline void MacroAssembler::load_ptr_contents(AddressLiteral& addrlit, Register d, int offset) {
|
||||
assert_not_delayed();
|
||||
a = a.split_disp();
|
||||
Assembler::sethi(a.hi(), temp, a.rspec());
|
||||
add(a.base(), temp, a.base());
|
||||
sethi(addrlit, d);
|
||||
ld_ptr(d, addrlit.low10() + offset, d);
|
||||
}
|
||||
|
||||
|
||||
inline void MacroAssembler::load_contents( Address& a, Register d, int offset ) {
|
||||
inline void MacroAssembler::store_contents(Register s, AddressLiteral& addrlit, Register temp, int offset) {
|
||||
assert_not_delayed();
|
||||
sethi(a);
|
||||
ld(a, d, offset);
|
||||
sethi(addrlit, temp);
|
||||
st(s, temp, addrlit.low10() + offset);
|
||||
}
|
||||
|
||||
|
||||
inline void MacroAssembler::load_ptr_contents( Address& a, Register d, int offset ) {
|
||||
inline void MacroAssembler::store_ptr_contents(Register s, AddressLiteral& addrlit, Register temp, int offset) {
|
||||
assert_not_delayed();
|
||||
sethi(a);
|
||||
ld_ptr(a, d, offset);
|
||||
}
|
||||
|
||||
|
||||
inline void MacroAssembler::store_contents( Register s, Address& a, int offset ) {
|
||||
assert_not_delayed();
|
||||
sethi(a);
|
||||
st(s, a, offset);
|
||||
}
|
||||
|
||||
|
||||
inline void MacroAssembler::store_ptr_contents( Register s, Address& a, int offset ) {
|
||||
assert_not_delayed();
|
||||
sethi(a);
|
||||
st_ptr(s, a, offset);
|
||||
sethi(addrlit, temp);
|
||||
st_ptr(s, temp, addrlit.low10() + offset);
|
||||
}
|
||||
|
||||
|
||||
// This code sequence is relocatable to any address, even on LP64.
|
||||
inline void MacroAssembler::jumpl_to( Address& a, Register d, int offset ) {
|
||||
inline void MacroAssembler::jumpl_to(AddressLiteral& addrlit, Register temp, Register d, int offset) {
|
||||
assert_not_delayed();
|
||||
// Force fixed length sethi because NativeJump and NativeFarCall don't handle
|
||||
// variable length instruction streams.
|
||||
sethi(a, /*ForceRelocatable=*/ true);
|
||||
jmpl(a, d, offset);
|
||||
patchable_sethi(addrlit, temp);
|
||||
jmpl(temp, addrlit.low10() + offset, d);
|
||||
}
|
||||
|
||||
|
||||
inline void MacroAssembler::jump_to( Address& a, int offset ) {
|
||||
jumpl_to( a, G0, offset );
|
||||
inline void MacroAssembler::jump_to(AddressLiteral& addrlit, Register temp, int offset) {
|
||||
jumpl_to(addrlit, temp, G0, offset);
|
||||
}
|
||||
|
||||
|
||||
inline void MacroAssembler::jump_indirect_to( Address& a, Register temp,
|
||||
int ld_offset, int jmp_offset ) {
|
||||
inline void MacroAssembler::jump_indirect_to(Address& a, Register temp,
|
||||
int ld_offset, int jmp_offset) {
|
||||
assert_not_delayed();
|
||||
//sethi(a); // sethi is caller responsibility for this one
|
||||
//sethi(al); // sethi is caller responsibility for this one
|
||||
ld_ptr(a, temp, ld_offset);
|
||||
jmp(temp, jmp_offset);
|
||||
}
|
||||
|
||||
|
||||
inline void MacroAssembler::set_oop( jobject obj, Register d ) {
|
||||
set_oop(allocate_oop_address(obj, d));
|
||||
inline void MacroAssembler::set_oop(jobject obj, Register d) {
|
||||
set_oop(allocate_oop_address(obj), d);
|
||||
}
|
||||
|
||||
|
||||
inline void MacroAssembler::set_oop_constant( jobject obj, Register d ) {
|
||||
set_oop(constant_oop_address(obj, d));
|
||||
inline void MacroAssembler::set_oop_constant(jobject obj, Register d) {
|
||||
set_oop(constant_oop_address(obj), d);
|
||||
}
|
||||
|
||||
|
||||
inline void MacroAssembler::set_oop( Address obj_addr ) {
|
||||
assert(obj_addr.rspec().type()==relocInfo::oop_type, "must be an oop reloc");
|
||||
load_address(obj_addr);
|
||||
inline void MacroAssembler::set_oop(AddressLiteral& obj_addr, Register d) {
|
||||
assert(obj_addr.rspec().type() == relocInfo::oop_type, "must be an oop reloc");
|
||||
set(obj_addr, d);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. 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
|
||||
@ -277,10 +277,11 @@ void PatchingStub::emit_code(LIR_Assembler* ce) {
|
||||
|
||||
if (_id == load_klass_id) {
|
||||
// produce a copy of the load klass instruction for use by the being initialized case
|
||||
#ifdef ASSERT
|
||||
address start = __ pc();
|
||||
Address addr = Address(_obj, address(NULL), oop_Relocation::spec(_oop_index));
|
||||
__ sethi(addr, true);
|
||||
__ add(addr, _obj, 0);
|
||||
#endif
|
||||
AddressLiteral addrlit(NULL, oop_Relocation::spec(_oop_index));
|
||||
__ patchable_set(addrlit, _obj);
|
||||
|
||||
#ifdef ASSERT
|
||||
for (int i = 0; i < _bytes_to_copy; i++) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. 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
|
||||
@ -327,7 +327,7 @@ void FrameMap::init () {
|
||||
|
||||
|
||||
Address FrameMap::make_new_address(ByteSize sp_offset) const {
|
||||
return Address(SP, 0, STACK_BIAS + in_bytes(sp_offset));
|
||||
return Address(SP, STACK_BIAS + in_bytes(sp_offset));
|
||||
}
|
||||
|
||||
|
||||
|
@ -196,7 +196,7 @@ void LIR_Assembler::osr_entry() {
|
||||
// verify the interpreter's monitor has a non-null object
|
||||
{
|
||||
Label L;
|
||||
__ ld_ptr(Address(OSR_buf, 0, slot_offset + BasicObjectLock::obj_offset_in_bytes()), O7);
|
||||
__ ld_ptr(OSR_buf, slot_offset + BasicObjectLock::obj_offset_in_bytes(), O7);
|
||||
__ cmp(G0, O7);
|
||||
__ br(Assembler::notEqual, false, Assembler::pt, L);
|
||||
__ delayed()->nop();
|
||||
@ -205,9 +205,9 @@ void LIR_Assembler::osr_entry() {
|
||||
}
|
||||
#endif // ASSERT
|
||||
// Copy the lock field into the compiled activation.
|
||||
__ ld_ptr(Address(OSR_buf, 0, slot_offset + BasicObjectLock::lock_offset_in_bytes()), O7);
|
||||
__ ld_ptr(OSR_buf, slot_offset + BasicObjectLock::lock_offset_in_bytes(), O7);
|
||||
__ st_ptr(O7, frame_map()->address_for_monitor_lock(i));
|
||||
__ ld_ptr(Address(OSR_buf, 0, slot_offset + BasicObjectLock::obj_offset_in_bytes()), O7);
|
||||
__ ld_ptr(OSR_buf, slot_offset + BasicObjectLock::obj_offset_in_bytes(), O7);
|
||||
__ st_ptr(O7, frame_map()->address_for_monitor_object(i));
|
||||
}
|
||||
}
|
||||
@ -238,21 +238,21 @@ void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst
|
||||
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
|
||||
int count_offset = java_lang_String:: count_offset_in_bytes();
|
||||
|
||||
__ ld_ptr(Address(str0, 0, value_offset), tmp0);
|
||||
__ ld(Address(str0, 0, offset_offset), tmp2);
|
||||
__ ld_ptr(str0, value_offset, tmp0);
|
||||
__ ld(str0, offset_offset, tmp2);
|
||||
__ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
|
||||
__ ld(Address(str0, 0, count_offset), str0);
|
||||
__ ld(str0, count_offset, str0);
|
||||
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
|
||||
|
||||
// str1 may be null
|
||||
add_debug_info_for_null_check_here(info);
|
||||
|
||||
__ ld_ptr(Address(str1, 0, value_offset), tmp1);
|
||||
__ ld_ptr(str1, value_offset, tmp1);
|
||||
__ add(tmp0, tmp2, tmp0);
|
||||
|
||||
__ ld(Address(str1, 0, offset_offset), tmp2);
|
||||
__ ld(str1, offset_offset, tmp2);
|
||||
__ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
|
||||
__ ld(Address(str1, 0, count_offset), str1);
|
||||
__ ld(str1, count_offset, str1);
|
||||
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
|
||||
__ subcc(str0, str1, O7);
|
||||
__ add(tmp1, tmp2, tmp1);
|
||||
@ -412,9 +412,9 @@ void LIR_Assembler::emit_deopt_handler() {
|
||||
#endif // ASSERT
|
||||
compilation()->offsets()->set_value(CodeOffsets::Deopt, code_offset());
|
||||
|
||||
Address deopt_blob(G3_scratch, SharedRuntime::deopt_blob()->unpack());
|
||||
AddressLiteral deopt_blob(SharedRuntime::deopt_blob()->unpack());
|
||||
|
||||
__ JUMP(deopt_blob, 0); // sethi;jmp
|
||||
__ JUMP(deopt_blob, G3_scratch, 0); // sethi;jmp
|
||||
__ delayed()->nop();
|
||||
|
||||
assert(code_offset() - offset <= deopt_handler_size, "overflow");
|
||||
@ -441,13 +441,12 @@ void LIR_Assembler::jobject2reg_with_patching(Register reg, CodeEmitInfo *info)
|
||||
int oop_index = __ oop_recorder()->allocate_index((jobject)NULL);
|
||||
PatchingStub* patch = new PatchingStub(_masm, PatchingStub::load_klass_id, oop_index);
|
||||
|
||||
Address addr = Address(reg, address(NULL), oop_Relocation::spec(oop_index));
|
||||
assert(addr.rspec().type() == relocInfo::oop_type, "must be an oop reloc");
|
||||
AddressLiteral addrlit(NULL, oop_Relocation::spec(oop_index));
|
||||
assert(addrlit.rspec().type() == relocInfo::oop_type, "must be an oop reloc");
|
||||
// It may not seem necessary to use a sethi/add pair to load a NULL into dest, but the
|
||||
// NULL will be dynamically patched later and the patched value may be large. We must
|
||||
// therefore generate the sethi/add as a placeholders
|
||||
__ sethi(addr, true);
|
||||
__ add(addr, reg, 0);
|
||||
__ patchable_set(addrlit, reg);
|
||||
|
||||
patching_epilog(patch, lir_patch_normal, reg, info);
|
||||
}
|
||||
@ -706,7 +705,7 @@ void LIR_Assembler::ic_call(address entry, CodeEmitInfo* info) {
|
||||
|
||||
void LIR_Assembler::vtable_call(int vtable_offset, CodeEmitInfo* info) {
|
||||
add_debug_info_for_null_check_here(info);
|
||||
__ ld_ptr(Address(O0, 0, oopDesc::klass_offset_in_bytes()), G3_scratch);
|
||||
__ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch);
|
||||
if (__ is_simm13(vtable_offset) ) {
|
||||
__ ld_ptr(G3_scratch, vtable_offset, G5_method);
|
||||
} else {
|
||||
@ -715,7 +714,7 @@ void LIR_Assembler::vtable_call(int vtable_offset, CodeEmitInfo* info) {
|
||||
// ld_ptr, set_hi, set
|
||||
__ ld_ptr(G3_scratch, G5_method, G5_method);
|
||||
}
|
||||
__ ld_ptr(G5_method, in_bytes(methodOopDesc::from_compiled_offset()), G3_scratch);
|
||||
__ ld_ptr(G5_method, methodOopDesc::from_compiled_offset(), G3_scratch);
|
||||
__ callr(G3_scratch, G0);
|
||||
// the peephole pass fills the delay slot
|
||||
}
|
||||
@ -738,8 +737,7 @@ int LIR_Assembler::load(Register s, int disp, Register d, BasicType ld_type, Cod
|
||||
default : ShouldNotReachHere();
|
||||
}
|
||||
} else {
|
||||
__ sethi(disp & ~0x3ff, O7, true);
|
||||
__ add(O7, disp & 0x3ff, O7);
|
||||
__ set(disp, O7);
|
||||
if (info != NULL) add_debug_info_for_null_check_here(info);
|
||||
load_offset = code_offset();
|
||||
switch(ld_type) {
|
||||
@ -775,8 +773,7 @@ void LIR_Assembler::store(Register value, Register base, int offset, BasicType t
|
||||
default : ShouldNotReachHere();
|
||||
}
|
||||
} else {
|
||||
__ sethi(offset & ~0x3ff, O7, true);
|
||||
__ add(O7, offset & 0x3ff, O7);
|
||||
__ set(offset, O7);
|
||||
if (info != NULL) add_debug_info_for_null_check_here(info);
|
||||
switch (type) {
|
||||
case T_BOOLEAN: // fall through
|
||||
@ -813,8 +810,7 @@ void LIR_Assembler::load(Register s, int disp, FloatRegister d, BasicType ld_typ
|
||||
__ ldf(w, s, disp, d);
|
||||
}
|
||||
} else {
|
||||
__ sethi(disp & ~0x3ff, O7, true);
|
||||
__ add(O7, disp & 0x3ff, O7);
|
||||
__ set(disp, O7);
|
||||
if (info != NULL) add_debug_info_for_null_check_here(info);
|
||||
__ ldf(w, s, O7, d);
|
||||
}
|
||||
@ -839,8 +835,7 @@ void LIR_Assembler::store(FloatRegister value, Register base, int offset, BasicT
|
||||
__ stf(w, value, base, offset);
|
||||
}
|
||||
} else {
|
||||
__ sethi(offset & ~0x3ff, O7, true);
|
||||
__ add(O7, offset & 0x3ff, O7);
|
||||
__ set(offset, O7);
|
||||
if (info != NULL) add_debug_info_for_null_check_here(info);
|
||||
__ stf(w, value, O7, base);
|
||||
}
|
||||
@ -852,8 +847,7 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType
|
||||
if (!Assembler::is_simm13(offset + (type == T_LONG) ? wordSize : 0)) {
|
||||
assert(!unaligned, "can't handle this");
|
||||
// for offsets larger than a simm13 we setup the offset in O7
|
||||
__ sethi(offset & ~0x3ff, O7, true);
|
||||
__ add(O7, offset & 0x3ff, O7);
|
||||
__ set(offset, O7);
|
||||
store_offset = store(from_reg, base, O7, type);
|
||||
} else {
|
||||
if (type == T_ARRAY || type == T_OBJECT) __ verify_oop(from_reg->as_register());
|
||||
@ -937,8 +931,7 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ
|
||||
assert(base != O7, "destroying register");
|
||||
assert(!unaligned, "can't handle this");
|
||||
// for offsets larger than a simm13 we setup the offset in O7
|
||||
__ sethi(offset & ~0x3ff, O7, true);
|
||||
__ add(O7, offset & 0x3ff, O7);
|
||||
__ set(offset, O7);
|
||||
load_offset = load(base, O7, to_reg, type);
|
||||
} else {
|
||||
load_offset = code_offset();
|
||||
@ -1213,7 +1206,7 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod
|
||||
assert(to_reg->is_single_fpu(), "wrong register kind");
|
||||
|
||||
__ set(con, O7);
|
||||
Address temp_slot(SP, 0, (frame::register_save_words * wordSize) + STACK_BIAS);
|
||||
Address temp_slot(SP, (frame::register_save_words * wordSize) + STACK_BIAS);
|
||||
__ st(O7, temp_slot);
|
||||
__ ldf(FloatRegisterImpl::S, temp_slot, to_reg->as_float_reg());
|
||||
}
|
||||
@ -1238,8 +1231,8 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod
|
||||
} else {
|
||||
ShouldNotReachHere();
|
||||
assert(to_reg->is_double_fpu(), "wrong register kind");
|
||||
Address temp_slot_lo(SP, 0, ((frame::register_save_words ) * wordSize) + STACK_BIAS);
|
||||
Address temp_slot_hi(SP, 0, ((frame::register_save_words) * wordSize) + (longSize/2) + STACK_BIAS);
|
||||
Address temp_slot_lo(SP, ((frame::register_save_words ) * wordSize) + STACK_BIAS);
|
||||
Address temp_slot_hi(SP, ((frame::register_save_words) * wordSize) + (longSize/2) + STACK_BIAS);
|
||||
__ set(low(con), O7);
|
||||
__ st(O7, temp_slot_lo);
|
||||
__ set(high(con), O7);
|
||||
@ -1267,17 +1260,16 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod
|
||||
break;
|
||||
}
|
||||
RelocationHolder rspec = internal_word_Relocation::spec(const_addr);
|
||||
AddressLiteral const_addrlit(const_addr, rspec);
|
||||
if (to_reg->is_single_fpu()) {
|
||||
__ sethi( (intx)const_addr & ~0x3ff, O7, true, rspec);
|
||||
__ patchable_sethi(const_addrlit, O7);
|
||||
__ relocate(rspec);
|
||||
|
||||
int offset = (intx)const_addr & 0x3ff;
|
||||
__ ldf (FloatRegisterImpl::S, O7, offset, to_reg->as_float_reg());
|
||||
__ ldf(FloatRegisterImpl::S, O7, const_addrlit.low10(), to_reg->as_float_reg());
|
||||
|
||||
} else {
|
||||
assert(to_reg->is_single_cpu(), "Must be a cpu register.");
|
||||
|
||||
__ set((intx)const_addr, O7, rspec);
|
||||
__ set(const_addrlit, O7);
|
||||
load(O7, 0, to_reg->as_register(), T_INT);
|
||||
}
|
||||
}
|
||||
@ -1293,10 +1285,10 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod
|
||||
RelocationHolder rspec = internal_word_Relocation::spec(const_addr);
|
||||
|
||||
if (to_reg->is_double_fpu()) {
|
||||
__ sethi( (intx)const_addr & ~0x3ff, O7, true, rspec);
|
||||
int offset = (intx)const_addr & 0x3ff;
|
||||
AddressLiteral const_addrlit(const_addr, rspec);
|
||||
__ patchable_sethi(const_addrlit, O7);
|
||||
__ relocate(rspec);
|
||||
__ ldf (FloatRegisterImpl::D, O7, offset, to_reg->as_double_reg());
|
||||
__ ldf (FloatRegisterImpl::D, O7, const_addrlit.low10(), to_reg->as_double_reg());
|
||||
} else {
|
||||
assert(to_reg->is_double_cpu(), "Must be a long register.");
|
||||
#ifdef _LP64
|
||||
@ -1317,7 +1309,7 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod
|
||||
|
||||
Address LIR_Assembler::as_Address(LIR_Address* addr) {
|
||||
Register reg = addr->base()->as_register();
|
||||
return Address(reg, 0, addr->disp());
|
||||
return Address(reg, addr->disp());
|
||||
}
|
||||
|
||||
|
||||
@ -1360,13 +1352,13 @@ void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) {
|
||||
|
||||
Address LIR_Assembler::as_Address_hi(LIR_Address* addr) {
|
||||
Address base = as_Address(addr);
|
||||
return Address(base.base(), 0, base.disp() + hi_word_offset_in_bytes);
|
||||
return Address(base.base(), base.disp() + hi_word_offset_in_bytes);
|
||||
}
|
||||
|
||||
|
||||
Address LIR_Assembler::as_Address_lo(LIR_Address* addr) {
|
||||
Address base = as_Address(addr);
|
||||
return Address(base.base(), 0, base.disp() + lo_word_offset_in_bytes);
|
||||
return Address(base.base(), base.disp() + lo_word_offset_in_bytes);
|
||||
}
|
||||
|
||||
|
||||
@ -1396,8 +1388,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src_opr, LIR_Opr dest, BasicType type,
|
||||
if (addr->index()->is_illegal()) {
|
||||
if (!Assembler::is_simm13(disp_value) && (!unaligned || Assembler::is_simm13(disp_value + 4))) {
|
||||
if (needs_patching) {
|
||||
__ sethi(0, O7, true);
|
||||
__ add(O7, 0, O7);
|
||||
__ patchable_set(0, O7);
|
||||
} else {
|
||||
__ set(disp_value, O7);
|
||||
}
|
||||
@ -1544,8 +1535,7 @@ void LIR_Assembler::reg2mem(LIR_Opr from_reg, LIR_Opr dest, BasicType type,
|
||||
if (addr->index()->is_illegal()) {
|
||||
if (!Assembler::is_simm13(disp_value) && (!unaligned || Assembler::is_simm13(disp_value + 4))) {
|
||||
if (needs_patching) {
|
||||
__ sethi(0, O7, true);
|
||||
__ add(O7, 0, O7);
|
||||
__ patchable_set(0, O7);
|
||||
} else {
|
||||
__ set(disp_value, O7);
|
||||
}
|
||||
@ -1627,8 +1617,8 @@ void LIR_Assembler::emit_static_call_stub() {
|
||||
|
||||
__ set_oop(NULL, G5);
|
||||
// must be set to -1 at code generation time
|
||||
Address a(G3, (address)-1);
|
||||
__ jump_to(a, 0);
|
||||
AddressLiteral addrlit(-1);
|
||||
__ jump_to(addrlit, G3);
|
||||
__ delayed()->nop();
|
||||
|
||||
assert(__ offset() - start <= call_stub_size, "stub too big");
|
||||
@ -2063,7 +2053,7 @@ void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmit
|
||||
address pc_for_athrow = __ pc();
|
||||
int pc_for_athrow_offset = __ offset();
|
||||
RelocationHolder rspec = internal_word_Relocation::spec(pc_for_athrow);
|
||||
__ set((intptr_t)pc_for_athrow, Oissuing_pc, rspec);
|
||||
__ set(pc_for_athrow, Oissuing_pc, rspec);
|
||||
add_call_info(pc_for_athrow_offset, info); // for exception handler
|
||||
|
||||
__ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type);
|
||||
@ -2451,7 +2441,7 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
|
||||
}
|
||||
|
||||
|
||||
Address flags_addr(mdo, 0, md->byte_offset_of_slot(data, DataLayout::flags_offset()) - mdo_offset_bias);
|
||||
Address flags_addr(mdo, md->byte_offset_of_slot(data, DataLayout::flags_offset()) - mdo_offset_bias);
|
||||
__ ldub(flags_addr, data_val);
|
||||
__ or3(data_val, BitData::null_seen_byte_constant(), data_val);
|
||||
__ stb(data_val, flags_addr);
|
||||
@ -2738,7 +2728,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
__ add(mdo, O7, mdo);
|
||||
}
|
||||
|
||||
Address counter_addr(mdo, 0, md->byte_offset_of_slot(data, CounterData::count_offset()) - mdo_offset_bias);
|
||||
Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()) - mdo_offset_bias);
|
||||
__ lduw(counter_addr, tmp1);
|
||||
__ add(tmp1, DataLayout::counter_increment, tmp1);
|
||||
__ stw(tmp1, counter_addr);
|
||||
@ -2764,8 +2754,8 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
for (i = 0; i < VirtualCallData::row_limit(); i++) {
|
||||
ciKlass* receiver = vc_data->receiver(i);
|
||||
if (known_klass->equals(receiver)) {
|
||||
Address data_addr(mdo, 0, md->byte_offset_of_slot(data,
|
||||
VirtualCallData::receiver_count_offset(i)) -
|
||||
Address data_addr(mdo, md->byte_offset_of_slot(data,
|
||||
VirtualCallData::receiver_count_offset(i)) -
|
||||
mdo_offset_bias);
|
||||
__ lduw(data_addr, tmp1);
|
||||
__ add(tmp1, DataLayout::counter_increment, tmp1);
|
||||
@ -2782,11 +2772,11 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
for (i = 0; i < VirtualCallData::row_limit(); i++) {
|
||||
ciKlass* receiver = vc_data->receiver(i);
|
||||
if (receiver == NULL) {
|
||||
Address recv_addr(mdo, 0, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)) -
|
||||
Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)) -
|
||||
mdo_offset_bias);
|
||||
jobject2reg(known_klass->encoding(), tmp1);
|
||||
__ st_ptr(tmp1, recv_addr);
|
||||
Address data_addr(mdo, 0, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) -
|
||||
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) -
|
||||
mdo_offset_bias);
|
||||
__ lduw(data_addr, tmp1);
|
||||
__ add(tmp1, DataLayout::counter_increment, tmp1);
|
||||
@ -2795,20 +2785,20 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
load(Address(recv, 0, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT);
|
||||
load(Address(recv, oopDesc::klass_offset_in_bytes()), recv, T_OBJECT);
|
||||
Label update_done;
|
||||
uint i;
|
||||
for (i = 0; i < VirtualCallData::row_limit(); i++) {
|
||||
Label next_test;
|
||||
// See if the receiver is receiver[n].
|
||||
Address receiver_addr(mdo, 0, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)) -
|
||||
Address receiver_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)) -
|
||||
mdo_offset_bias);
|
||||
__ ld_ptr(receiver_addr, tmp1);
|
||||
__ verify_oop(tmp1);
|
||||
__ cmp(recv, tmp1);
|
||||
__ brx(Assembler::notEqual, false, Assembler::pt, next_test);
|
||||
__ delayed()->nop();
|
||||
Address data_addr(mdo, 0, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) -
|
||||
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) -
|
||||
mdo_offset_bias);
|
||||
__ lduw(data_addr, tmp1);
|
||||
__ add(tmp1, DataLayout::counter_increment, tmp1);
|
||||
@ -2821,7 +2811,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
// Didn't find receiver; find next empty slot and fill it in
|
||||
for (i = 0; i < VirtualCallData::row_limit(); i++) {
|
||||
Label next_test;
|
||||
Address recv_addr(mdo, 0, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)) -
|
||||
Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)) -
|
||||
mdo_offset_bias);
|
||||
load(recv_addr, tmp1, T_OBJECT);
|
||||
__ tst(tmp1);
|
||||
@ -2829,8 +2819,8 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
|
||||
__ delayed()->nop();
|
||||
__ st_ptr(recv, recv_addr);
|
||||
__ set(DataLayout::counter_increment, tmp1);
|
||||
__ st_ptr(tmp1, Address(mdo, 0, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) -
|
||||
mdo_offset_bias));
|
||||
__ st_ptr(tmp1, mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) -
|
||||
mdo_offset_bias);
|
||||
if (i < (VirtualCallData::row_limit() - 1)) {
|
||||
__ br(Assembler::always, false, Assembler::pt, update_done);
|
||||
__ delayed()->nop();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. 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
|
||||
@ -29,13 +29,13 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
|
||||
Label L;
|
||||
const Register temp_reg = G3_scratch;
|
||||
// Note: needs more testing of out-of-line vs. inline slow case
|
||||
Address ic_miss(temp_reg, SharedRuntime::get_ic_miss_stub());
|
||||
verify_oop(receiver);
|
||||
ld_ptr(receiver, oopDesc::klass_offset_in_bytes(), temp_reg);
|
||||
cmp(temp_reg, iCache);
|
||||
brx(Assembler::equal, true, Assembler::pt, L);
|
||||
delayed()->nop();
|
||||
jump_to(ic_miss, 0);
|
||||
AddressLiteral ic_miss(SharedRuntime::get_ic_miss_stub());
|
||||
jump_to(ic_miss, temp_reg);
|
||||
delayed()->nop();
|
||||
align(CodeEntryAlignment);
|
||||
bind(L);
|
||||
@ -84,7 +84,7 @@ void C1_MacroAssembler::lock_object(Register Rmark, Register Roop, Register Rbox
|
||||
|
||||
Label done;
|
||||
|
||||
Address mark_addr(Roop, 0, oopDesc::mark_offset_in_bytes());
|
||||
Address mark_addr(Roop, oopDesc::mark_offset_in_bytes());
|
||||
|
||||
// The following move must be the first instruction of emitted since debug
|
||||
// information may be generated for it.
|
||||
@ -132,7 +132,7 @@ void C1_MacroAssembler::unlock_object(Register Rmark, Register Roop, Register Rb
|
||||
|
||||
Label done;
|
||||
|
||||
Address mark_addr(Roop, 0, oopDesc::mark_offset_in_bytes());
|
||||
Address mark_addr(Roop, oopDesc::mark_offset_in_bytes());
|
||||
assert(mark_addr.disp() == 0, "cas must take a zero displacement");
|
||||
|
||||
if (UseBiasedLocking) {
|
||||
@ -370,7 +370,7 @@ void C1_MacroAssembler::allocate_array(
|
||||
|
||||
void C1_MacroAssembler::verify_stack_oop(int stack_offset) {
|
||||
if (!VerifyOops) return;
|
||||
verify_oop_addr(Address(SP, 0, stack_offset + STACK_BIAS));
|
||||
verify_oop_addr(Address(SP, stack_offset + STACK_BIAS));
|
||||
}
|
||||
|
||||
void C1_MacroAssembler::verify_not_null_oop(Register r) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1999-2009 Sun Microsystems, Inc. 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
|
||||
@ -57,13 +57,13 @@ int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address e
|
||||
|
||||
// check for pending exceptions
|
||||
{ Label L;
|
||||
Address exception_addr(G2_thread, 0, in_bytes(Thread::pending_exception_offset()));
|
||||
Address exception_addr(G2_thread, Thread::pending_exception_offset());
|
||||
ld_ptr(exception_addr, Gtemp);
|
||||
br_null(Gtemp, false, pt, L);
|
||||
delayed()->nop();
|
||||
Address vm_result_addr(G2_thread, 0, in_bytes(JavaThread::vm_result_offset()));
|
||||
Address vm_result_addr(G2_thread, JavaThread::vm_result_offset());
|
||||
st_ptr(G0, vm_result_addr);
|
||||
Address vm_result_addr_2(G2_thread, 0, in_bytes(JavaThread::vm_result_2_offset()));
|
||||
Address vm_result_addr_2(G2_thread, JavaThread::vm_result_2_offset());
|
||||
st_ptr(G0, vm_result_addr_2);
|
||||
|
||||
if (frame_size() == no_frame_size) {
|
||||
@ -73,8 +73,8 @@ int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address e
|
||||
} else if (_stub_id == Runtime1::forward_exception_id) {
|
||||
should_not_reach_here();
|
||||
} else {
|
||||
Address exc(G4, Runtime1::entry_for(Runtime1::forward_exception_id));
|
||||
jump_to(exc, 0);
|
||||
AddressLiteral exc(Runtime1::entry_for(Runtime1::forward_exception_id));
|
||||
jump_to(exc, G4);
|
||||
delayed()->nop();
|
||||
}
|
||||
bind(L);
|
||||
@ -85,7 +85,7 @@ int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address e
|
||||
get_vm_result (oop_result1);
|
||||
} else {
|
||||
// be a little paranoid and clear the result
|
||||
Address vm_result_addr(G2_thread, 0, in_bytes(JavaThread::vm_result_offset()));
|
||||
Address vm_result_addr(G2_thread, JavaThread::vm_result_offset());
|
||||
st_ptr(G0, vm_result_addr);
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address e
|
||||
get_vm_result_2(oop_result2);
|
||||
} else {
|
||||
// be a little paranoid and clear the result
|
||||
Address vm_result_addr_2(G2_thread, 0, in_bytes(JavaThread::vm_result_2_offset()));
|
||||
Address vm_result_addr_2(G2_thread, JavaThread::vm_result_2_offset());
|
||||
st_ptr(G0, vm_result_addr_2);
|
||||
}
|
||||
|
||||
@ -479,8 +479,8 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
|
||||
Register G4_length = G4; // Incoming
|
||||
Register O0_obj = O0; // Outgoing
|
||||
|
||||
Address klass_lh(G5_klass, 0, ((klassOopDesc::header_size() * HeapWordSize)
|
||||
+ Klass::layout_helper_offset_in_bytes()));
|
||||
Address klass_lh(G5_klass, ((klassOopDesc::header_size() * HeapWordSize)
|
||||
+ Klass::layout_helper_offset_in_bytes()));
|
||||
assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise");
|
||||
assert(Klass::_lh_header_size_mask == 0xFF, "bytewise");
|
||||
// Use this offset to pick out an individual byte of the layout_helper:
|
||||
@ -902,8 +902,8 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
|
||||
__ srl(addr, CardTableModRefBS::card_shift, addr);
|
||||
#endif
|
||||
|
||||
Address rs(cardtable, (address)byte_map_base);
|
||||
__ load_address(rs); // cardtable := <card table base>
|
||||
AddressLiteral rs(byte_map_base);
|
||||
__ set(rs, cardtable); // cardtable := <card table base>
|
||||
__ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable]
|
||||
|
||||
__ br_on_reg_cond(Assembler::rc_nz, /*annul*/false, Assembler::pt,
|
||||
@ -1022,8 +1022,8 @@ void Runtime1::generate_handle_exception(StubAssembler* sasm, OopMapSet* oop_map
|
||||
|
||||
__ restore();
|
||||
|
||||
Address exc(G4, Runtime1::entry_for(Runtime1::unwind_exception_id));
|
||||
__ jump_to(exc, 0);
|
||||
AddressLiteral exc(Runtime1::entry_for(Runtime1::unwind_exception_id));
|
||||
__ jump_to(exc, G4);
|
||||
__ delayed()->nop();
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2004-2009 Sun Microsystems, Inc. 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
|
||||
@ -106,8 +106,7 @@ void CompactingPermGenGen::generate_vtable_methods(void** vtbl_list,
|
||||
__ and3(L0, 255, L4); // Isolate L3 = method offset;.
|
||||
__ sll(L4, LogBytesPerWord, L4);
|
||||
__ ld_ptr(L3, L4, L4); // Get address of correct virtual method
|
||||
Address method(L4, 0);
|
||||
__ jmpl(method, G0); // Jump to correct method.
|
||||
__ jmpl(L4, 0, G0); // Jump to correct method.
|
||||
__ delayed()->restore(); // Restore registers.
|
||||
|
||||
__ flush();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||
@ -46,14 +46,13 @@ void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, oop cached_o
|
||||
// (1) the oop is old (i.e., doesn't matter for scavenges)
|
||||
// (2) these ICStubs are removed *before* a GC happens, so the roots disappear
|
||||
assert(cached_oop == NULL || cached_oop->is_perm(), "must be old oop");
|
||||
Address cached_oop_addr(G5_inline_cache_reg, address(cached_oop));
|
||||
// Force the sethi to generate the fixed sequence so next_instruction_address works
|
||||
masm->sethi(cached_oop_addr, true /* ForceRelocatable */ );
|
||||
masm->add(cached_oop_addr, G5_inline_cache_reg);
|
||||
AddressLiteral cached_oop_addrlit(cached_oop, relocInfo::none);
|
||||
// Force the set to generate the fixed sequence so next_instruction_address works
|
||||
masm->patchable_set(cached_oop_addrlit, G5_inline_cache_reg);
|
||||
assert(G3_scratch != G5_method, "Do not clobber the method oop in the transition stub");
|
||||
assert(G3_scratch != G5_inline_cache_reg, "Do not clobber the inline cache register in the transition stub");
|
||||
Address entry(G3_scratch, entry_point);
|
||||
masm->JUMP(entry, 0);
|
||||
AddressLiteral entry(entry_point);
|
||||
masm->JUMP(entry, G3_scratch, 0);
|
||||
masm->delayed()->nop();
|
||||
masm->flush();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||
@ -35,8 +35,8 @@
|
||||
|
||||
// This file specializes the assember with interpreter-specific macros
|
||||
|
||||
const Address InterpreterMacroAssembler::l_tmp( FP, 0, (frame::interpreter_frame_l_scratch_fp_offset * wordSize ) + STACK_BIAS);
|
||||
const Address InterpreterMacroAssembler::d_tmp( FP, 0, (frame::interpreter_frame_d_scratch_fp_offset * wordSize) + STACK_BIAS);
|
||||
const Address InterpreterMacroAssembler::l_tmp(FP, (frame::interpreter_frame_l_scratch_fp_offset * wordSize) + STACK_BIAS);
|
||||
const Address InterpreterMacroAssembler::d_tmp(FP, (frame::interpreter_frame_d_scratch_fp_offset * wordSize) + STACK_BIAS);
|
||||
|
||||
#else // CC_INTERP
|
||||
#ifndef STATE
|
||||
@ -78,14 +78,12 @@ void InterpreterMacroAssembler::dispatch_prolog(TosState state, int bcp_incr) {
|
||||
sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize
|
||||
ld_ptr(IdispatchTables, Lbyte_code, IdispatchAddress);// get entry addr
|
||||
#else
|
||||
ldub( Lbcp, bcp_incr, Lbyte_code); // load next bytecode
|
||||
ldub( Lbcp, bcp_incr, Lbyte_code); // load next bytecode
|
||||
// dispatch table to use
|
||||
Address tbl(G3_scratch, (address)Interpreter::dispatch_table(state));
|
||||
|
||||
sethi(tbl);
|
||||
sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize
|
||||
add(tbl, tbl.base(), 0);
|
||||
ld_ptr( G3_scratch, Lbyte_code, IdispatchAddress); // get entry addr
|
||||
AddressLiteral tbl(Interpreter::dispatch_table(state));
|
||||
sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize
|
||||
set(tbl, G3_scratch); // compute addr of table
|
||||
ld_ptr(G3_scratch, Lbyte_code, IdispatchAddress); // get entry addr
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -165,8 +163,7 @@ void InterpreterMacroAssembler::check_and_handle_popframe(Register scratch_reg)
|
||||
Label L;
|
||||
|
||||
// Check the "pending popframe condition" flag in the current thread
|
||||
Address popframe_condition_addr(G2_thread, 0, in_bytes(JavaThread::popframe_condition_offset()));
|
||||
ld(popframe_condition_addr, scratch_reg);
|
||||
ld(G2_thread, JavaThread::popframe_condition_offset(), scratch_reg);
|
||||
|
||||
// Initiate popframe handling only if it is not already being processed. If the flag
|
||||
// has the popframe_processing bit set, it means that this code is called *during* popframe
|
||||
@ -192,11 +189,10 @@ void InterpreterMacroAssembler::check_and_handle_popframe(Register scratch_reg)
|
||||
|
||||
void InterpreterMacroAssembler::load_earlyret_value(TosState state) {
|
||||
Register thr_state = G4_scratch;
|
||||
ld_ptr(Address(G2_thread, 0, in_bytes(JavaThread::jvmti_thread_state_offset())),
|
||||
thr_state);
|
||||
const Address tos_addr(thr_state, 0, in_bytes(JvmtiThreadState::earlyret_tos_offset()));
|
||||
const Address oop_addr(thr_state, 0, in_bytes(JvmtiThreadState::earlyret_oop_offset()));
|
||||
const Address val_addr(thr_state, 0, in_bytes(JvmtiThreadState::earlyret_value_offset()));
|
||||
ld_ptr(G2_thread, JavaThread::jvmti_thread_state_offset(), thr_state);
|
||||
const Address tos_addr(thr_state, JvmtiThreadState::earlyret_tos_offset());
|
||||
const Address oop_addr(thr_state, JvmtiThreadState::earlyret_oop_offset());
|
||||
const Address val_addr(thr_state, JvmtiThreadState::earlyret_value_offset());
|
||||
switch (state) {
|
||||
case ltos: ld_long(val_addr, Otos_l); break;
|
||||
case atos: ld_ptr(oop_addr, Otos_l);
|
||||
@ -222,8 +218,7 @@ void InterpreterMacroAssembler::check_and_handle_earlyret(Register scratch_reg)
|
||||
if (JvmtiExport::can_force_early_return()) {
|
||||
Label L;
|
||||
Register thr_state = G3_scratch;
|
||||
ld_ptr(Address(G2_thread, 0, in_bytes(JavaThread::jvmti_thread_state_offset())),
|
||||
thr_state);
|
||||
ld_ptr(G2_thread, JavaThread::jvmti_thread_state_offset(), thr_state);
|
||||
tst(thr_state);
|
||||
br(zero, false, pt, L); // if (thread->jvmti_thread_state() == NULL) exit;
|
||||
delayed()->nop();
|
||||
@ -231,16 +226,14 @@ void InterpreterMacroAssembler::check_and_handle_earlyret(Register scratch_reg)
|
||||
// Initiate earlyret handling only if it is not already being processed.
|
||||
// If the flag has the earlyret_processing bit set, it means that this code
|
||||
// is called *during* earlyret handling - we don't want to reenter.
|
||||
ld(Address(thr_state, 0, in_bytes(JvmtiThreadState::earlyret_state_offset())),
|
||||
G4_scratch);
|
||||
ld(thr_state, JvmtiThreadState::earlyret_state_offset(), G4_scratch);
|
||||
cmp(G4_scratch, JvmtiThreadState::earlyret_pending);
|
||||
br(Assembler::notEqual, false, pt, L);
|
||||
delayed()->nop();
|
||||
|
||||
// Call Interpreter::remove_activation_early_entry() to get the address of the
|
||||
// same-named entrypoint in the generated interpreter code
|
||||
Address tos_addr(thr_state, 0, in_bytes(JvmtiThreadState::earlyret_tos_offset()));
|
||||
ld(tos_addr, Otos_l1);
|
||||
ld(thr_state, JvmtiThreadState::earlyret_tos_offset(), Otos_l1);
|
||||
call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, Interpreter::remove_activation_early_entry), Otos_l1);
|
||||
|
||||
// Jump to Interpreter::_remove_activation_early_entry
|
||||
@ -294,10 +287,9 @@ void InterpreterMacroAssembler::dispatch_Lbyte_code(TosState state, address* tab
|
||||
} else {
|
||||
#endif
|
||||
// dispatch table to use
|
||||
Address tbl(G3_scratch, (address)table);
|
||||
|
||||
AddressLiteral tbl(table);
|
||||
sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize
|
||||
load_address(tbl); // compute addr of table
|
||||
set(tbl, G3_scratch); // compute addr of table
|
||||
ld_ptr(G3_scratch, Lbyte_code, G3_scratch); // get entry addr
|
||||
#ifdef FAST_DISPATCH
|
||||
}
|
||||
@ -601,26 +593,17 @@ void InterpreterMacroAssembler::empty_expression_stack() {
|
||||
|
||||
// Reset SP by subtracting more space from Lesp.
|
||||
Label done;
|
||||
|
||||
const Address max_stack (Lmethod, 0, in_bytes(methodOopDesc::max_stack_offset()));
|
||||
const Address access_flags(Lmethod, 0, in_bytes(methodOopDesc::access_flags_offset()));
|
||||
|
||||
verify_oop(Lmethod);
|
||||
|
||||
|
||||
assert( G4_scratch != Gframe_size,
|
||||
"Only you can prevent register aliasing!");
|
||||
assert(G4_scratch != Gframe_size, "Only you can prevent register aliasing!");
|
||||
|
||||
// A native does not need to do this, since its callee does not change SP.
|
||||
ld(access_flags, Gframe_size);
|
||||
ld(Lmethod, methodOopDesc::access_flags_offset(), Gframe_size); // Load access flags.
|
||||
btst(JVM_ACC_NATIVE, Gframe_size);
|
||||
br(Assembler::notZero, false, Assembler::pt, done);
|
||||
delayed()->nop();
|
||||
|
||||
//
|
||||
// Compute max expression stack+register save area
|
||||
//
|
||||
lduh( max_stack, Gframe_size );
|
||||
lduh(Lmethod, in_bytes(methodOopDesc::max_stack_offset()), Gframe_size); // Load max stack.
|
||||
if (TaggedStackInterpreter) sll ( Gframe_size, 1, Gframe_size); // max_stack * 2 for TAGS
|
||||
add( Gframe_size, frame::memory_parameter_word_sp_offset, Gframe_size );
|
||||
|
||||
@ -721,8 +704,7 @@ void InterpreterMacroAssembler::call_from_interpreter(Register target, Register
|
||||
verify_thread();
|
||||
Label skip_compiled_code;
|
||||
|
||||
const Address interp_only (G2_thread, 0, in_bytes(JavaThread::interp_only_mode_offset()));
|
||||
|
||||
const Address interp_only(G2_thread, JavaThread::interp_only_mode_offset());
|
||||
ld(interp_only, scratch);
|
||||
tst(scratch);
|
||||
br(Assembler::notZero, true, Assembler::pn, skip_compiled_code);
|
||||
@ -916,8 +898,8 @@ void InterpreterMacroAssembler::throw_if_not_2( address throw_entry_point,
|
||||
Register Rscratch,
|
||||
Label& ok ) {
|
||||
assert(throw_entry_point != NULL, "entry point must be generated by now");
|
||||
Address dest(Rscratch, throw_entry_point);
|
||||
jump_to(dest);
|
||||
AddressLiteral dest(throw_entry_point);
|
||||
jump_to(dest, Rscratch);
|
||||
delayed()->nop();
|
||||
bind(ok);
|
||||
}
|
||||
@ -1035,18 +1017,18 @@ void InterpreterMacroAssembler::unlock_if_synchronized_method(TosState state,
|
||||
Label unlocked, unlock, no_unlock;
|
||||
|
||||
// get the value of _do_not_unlock_if_synchronized into G1_scratch
|
||||
const Address do_not_unlock_if_synchronized(G2_thread, 0,
|
||||
in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()));
|
||||
const Address do_not_unlock_if_synchronized(G2_thread,
|
||||
JavaThread::do_not_unlock_if_synchronized_offset());
|
||||
ldbool(do_not_unlock_if_synchronized, G1_scratch);
|
||||
stbool(G0, do_not_unlock_if_synchronized); // reset the flag
|
||||
|
||||
// check if synchronized method
|
||||
const Address access_flags(Lmethod, 0, in_bytes(methodOopDesc::access_flags_offset()));
|
||||
const Address access_flags(Lmethod, methodOopDesc::access_flags_offset());
|
||||
interp_verify_oop(Otos_i, state, __FILE__, __LINE__);
|
||||
push(state); // save tos
|
||||
ld(access_flags, G3_scratch);
|
||||
ld(access_flags, G3_scratch); // Load access flags.
|
||||
btst(JVM_ACC_SYNCHRONIZED, G3_scratch);
|
||||
br( zero, false, pt, unlocked);
|
||||
br(zero, false, pt, unlocked);
|
||||
delayed()->nop();
|
||||
|
||||
// Don't unlock anything if the _do_not_unlock_if_synchronized flag
|
||||
@ -1236,8 +1218,8 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg, Register Object)
|
||||
Register obj_reg = Object;
|
||||
Register mark_reg = G4_scratch;
|
||||
Register temp_reg = G1_scratch;
|
||||
Address lock_addr = Address(lock_reg, 0, BasicObjectLock::lock_offset_in_bytes());
|
||||
Address mark_addr = Address(obj_reg, 0, oopDesc::mark_offset_in_bytes());
|
||||
Address lock_addr(lock_reg, BasicObjectLock::lock_offset_in_bytes());
|
||||
Address mark_addr(obj_reg, oopDesc::mark_offset_in_bytes());
|
||||
Label done;
|
||||
|
||||
Label slow_case;
|
||||
@ -1315,9 +1297,8 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) {
|
||||
Register obj_reg = G3_scratch;
|
||||
Register mark_reg = G4_scratch;
|
||||
Register displaced_header_reg = G1_scratch;
|
||||
Address lock_addr = Address(lock_reg, 0, BasicObjectLock::lock_offset_in_bytes());
|
||||
Address lockobj_addr = Address(lock_reg, 0, BasicObjectLock::obj_offset_in_bytes());
|
||||
Address mark_addr = Address(obj_reg, 0, oopDesc::mark_offset_in_bytes());
|
||||
Address lockobj_addr(lock_reg, BasicObjectLock::obj_offset_in_bytes());
|
||||
Address mark_addr(obj_reg, oopDesc::mark_offset_in_bytes());
|
||||
Label done;
|
||||
|
||||
if (UseBiasedLocking) {
|
||||
@ -1328,7 +1309,8 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) {
|
||||
}
|
||||
|
||||
// Test first if we are in the fast recursive case
|
||||
ld_ptr(lock_addr, displaced_header_reg, BasicLock::displaced_header_offset_in_bytes());
|
||||
Address lock_addr(lock_reg, BasicObjectLock::lock_offset_in_bytes() + BasicLock::displaced_header_offset_in_bytes());
|
||||
ld_ptr(lock_addr, displaced_header_reg);
|
||||
br_null(displaced_header_reg, true, Assembler::pn, done);
|
||||
delayed()->st_ptr(G0, lockobj_addr); // free entry
|
||||
|
||||
@ -1384,7 +1366,7 @@ void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() {
|
||||
Label zero_continue;
|
||||
|
||||
// Test MDO to avoid the call if it is NULL.
|
||||
ld_ptr(Lmethod, in_bytes(methodOopDesc::method_data_offset()), ImethodDataPtr);
|
||||
ld_ptr(Lmethod, methodOopDesc::method_data_offset(), ImethodDataPtr);
|
||||
test_method_data_pointer(zero_continue);
|
||||
call_VM_leaf(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::bcp_to_di), Lmethod, Lbcp);
|
||||
set_method_data_pointer_offset(O0);
|
||||
@ -1413,7 +1395,7 @@ void InterpreterMacroAssembler::verify_method_data_pointer() {
|
||||
// If the mdp is valid, it will point to a DataLayout header which is
|
||||
// consistent with the bcp. The converse is highly probable also.
|
||||
lduh(ImethodDataPtr, in_bytes(DataLayout::bci_offset()), G3_scratch);
|
||||
ld_ptr(Address(Lmethod, 0, in_bytes(methodOopDesc::const_offset())), O5);
|
||||
ld_ptr(Lmethod, methodOopDesc::const_offset(), O5);
|
||||
add(G3_scratch, in_bytes(constMethodOopDesc::codes_offset()), G3_scratch);
|
||||
add(G3_scratch, O5, G3_scratch);
|
||||
cmp(Lbcp, G3_scratch);
|
||||
@ -1424,7 +1406,7 @@ void InterpreterMacroAssembler::verify_method_data_pointer() {
|
||||
// %%% should use call_VM_leaf here?
|
||||
//call_VM_leaf(noreg, ..., Lmethod, Lbcp, ImethodDataPtr);
|
||||
save_frame_and_mov(sizeof(jdouble) / wordSize, Lmethod, O0, Lbcp, O1);
|
||||
Address d_save(FP, 0, -sizeof(jdouble) + STACK_BIAS);
|
||||
Address d_save(FP, -sizeof(jdouble) + STACK_BIAS);
|
||||
stf(FloatRegisterImpl::D, Ftos_d, d_save);
|
||||
mov(temp_reg->after_save(), O2);
|
||||
save_thread(L7_thread_cache);
|
||||
@ -1456,14 +1438,14 @@ void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocat
|
||||
#endif
|
||||
|
||||
// Test to see if we should create a method data oop
|
||||
Address profile_limit(Rtmp, (address)&InvocationCounter::InterpreterProfileLimit);
|
||||
AddressLiteral profile_limit((address) &InvocationCounter::InterpreterProfileLimit);
|
||||
#ifdef _LP64
|
||||
delayed()->nop();
|
||||
sethi(profile_limit);
|
||||
sethi(profile_limit, Rtmp);
|
||||
#else
|
||||
delayed()->sethi(profile_limit);
|
||||
delayed()->sethi(profile_limit, Rtmp);
|
||||
#endif
|
||||
ld(profile_limit, Rtmp);
|
||||
ld(Rtmp, profile_limit.low10(), Rtmp);
|
||||
cmp(invocation_count, Rtmp);
|
||||
br(Assembler::lessUnsigned, false, Assembler::pn, profile_continue);
|
||||
delayed()->nop();
|
||||
@ -1521,7 +1503,7 @@ void InterpreterMacroAssembler::increment_mdp_data_at(int constant,
|
||||
Register bumped_count,
|
||||
bool decrement) {
|
||||
// Locate the counter at a fixed offset from the mdp:
|
||||
Address counter(ImethodDataPtr, 0, constant);
|
||||
Address counter(ImethodDataPtr, constant);
|
||||
increment_mdp_data_at(counter, bumped_count, decrement);
|
||||
}
|
||||
|
||||
@ -1535,7 +1517,7 @@ void InterpreterMacroAssembler::increment_mdp_data_at(Register reg,
|
||||
bool decrement) {
|
||||
// Add the constant to reg to get the offset.
|
||||
add(ImethodDataPtr, reg, scratch2);
|
||||
Address counter(scratch2, 0, constant);
|
||||
Address counter(scratch2, constant);
|
||||
increment_mdp_data_at(counter, bumped_count, decrement);
|
||||
}
|
||||
|
||||
@ -2201,7 +2183,7 @@ int InterpreterMacroAssembler::top_most_monitor_byte_offset() {
|
||||
|
||||
|
||||
Address InterpreterMacroAssembler::top_most_monitor() {
|
||||
return Address(FP, 0, top_most_monitor_byte_offset());
|
||||
return Address(FP, top_most_monitor_byte_offset());
|
||||
}
|
||||
|
||||
|
||||
@ -2214,15 +2196,15 @@ void InterpreterMacroAssembler::compute_stack_base( Register Rdest ) {
|
||||
void InterpreterMacroAssembler::increment_invocation_counter( Register Rtmp, Register Rtmp2 ) {
|
||||
assert(UseCompiler, "incrementing must be useful");
|
||||
#ifdef CC_INTERP
|
||||
Address inv_counter(G5_method, 0, in_bytes(methodOopDesc::invocation_counter_offset()
|
||||
+ InvocationCounter::counter_offset()));
|
||||
Address be_counter(G5_method, 0, in_bytes(methodOopDesc::backedge_counter_offset()
|
||||
+ InvocationCounter::counter_offset()));
|
||||
Address inv_counter(G5_method, methodOopDesc::invocation_counter_offset() +
|
||||
InvocationCounter::counter_offset());
|
||||
Address be_counter (G5_method, methodOopDesc::backedge_counter_offset() +
|
||||
InvocationCounter::counter_offset());
|
||||
#else
|
||||
Address inv_counter(Lmethod, 0, in_bytes(methodOopDesc::invocation_counter_offset()
|
||||
+ InvocationCounter::counter_offset()));
|
||||
Address be_counter(Lmethod, 0, in_bytes(methodOopDesc::backedge_counter_offset()
|
||||
+ InvocationCounter::counter_offset()));
|
||||
Address inv_counter(Lmethod, methodOopDesc::invocation_counter_offset() +
|
||||
InvocationCounter::counter_offset());
|
||||
Address be_counter (Lmethod, methodOopDesc::backedge_counter_offset() +
|
||||
InvocationCounter::counter_offset());
|
||||
#endif /* CC_INTERP */
|
||||
int delta = InvocationCounter::count_increment;
|
||||
|
||||
@ -2250,15 +2232,15 @@ void InterpreterMacroAssembler::increment_invocation_counter( Register Rtmp, Reg
|
||||
void InterpreterMacroAssembler::increment_backedge_counter( Register Rtmp, Register Rtmp2 ) {
|
||||
assert(UseCompiler, "incrementing must be useful");
|
||||
#ifdef CC_INTERP
|
||||
Address be_counter(G5_method, 0, in_bytes(methodOopDesc::backedge_counter_offset()
|
||||
+ InvocationCounter::counter_offset()));
|
||||
Address inv_counter(G5_method, 0, in_bytes(methodOopDesc::invocation_counter_offset()
|
||||
+ InvocationCounter::counter_offset()));
|
||||
Address be_counter (G5_method, methodOopDesc::backedge_counter_offset() +
|
||||
InvocationCounter::counter_offset());
|
||||
Address inv_counter(G5_method, methodOopDesc::invocation_counter_offset() +
|
||||
InvocationCounter::counter_offset());
|
||||
#else
|
||||
Address be_counter(Lmethod, 0, in_bytes(methodOopDesc::backedge_counter_offset()
|
||||
+ InvocationCounter::counter_offset()));
|
||||
Address inv_counter(Lmethod, 0, in_bytes(methodOopDesc::invocation_counter_offset()
|
||||
+ InvocationCounter::counter_offset()));
|
||||
Address be_counter (Lmethod, methodOopDesc::backedge_counter_offset() +
|
||||
InvocationCounter::counter_offset());
|
||||
Address inv_counter(Lmethod, methodOopDesc::invocation_counter_offset() +
|
||||
InvocationCounter::counter_offset());
|
||||
#endif /* CC_INTERP */
|
||||
int delta = InvocationCounter::count_increment;
|
||||
// Load each counter in a register
|
||||
@ -2289,7 +2271,7 @@ void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_c
|
||||
assert_different_registers(backedge_count, Rtmp, branch_bcp);
|
||||
assert(UseOnStackReplacement,"Must UseOnStackReplacement to test_backedge_count_for_osr");
|
||||
|
||||
Address limit(Rtmp, address(&InvocationCounter::InterpreterBackwardBranchLimit));
|
||||
AddressLiteral limit(&InvocationCounter::InterpreterBackwardBranchLimit);
|
||||
load_contents(limit, Rtmp);
|
||||
cmp(backedge_count, Rtmp);
|
||||
br(Assembler::lessUnsigned, false, Assembler::pt, did_not_overflow);
|
||||
@ -2435,9 +2417,7 @@ void InterpreterMacroAssembler::notify_method_entry() {
|
||||
if (JvmtiExport::can_post_interpreter_events()) {
|
||||
Label L;
|
||||
Register temp_reg = O5;
|
||||
|
||||
const Address interp_only (G2_thread, 0, in_bytes(JavaThread::interp_only_mode_offset()));
|
||||
|
||||
const Address interp_only(G2_thread, JavaThread::interp_only_mode_offset());
|
||||
ld(interp_only, temp_reg);
|
||||
tst(temp_reg);
|
||||
br(zero, false, pt, L);
|
||||
@ -2489,9 +2469,7 @@ void InterpreterMacroAssembler::notify_method_exit(bool is_native_method,
|
||||
if (mode == NotifyJVMTI && JvmtiExport::can_post_interpreter_events()) {
|
||||
Label L;
|
||||
Register temp_reg = O5;
|
||||
|
||||
const Address interp_only (G2_thread, 0, in_bytes(JavaThread::interp_only_mode_offset()));
|
||||
|
||||
const Address interp_only(G2_thread, JavaThread::interp_only_mode_offset());
|
||||
ld(interp_only, temp_reg);
|
||||
tst(temp_reg);
|
||||
br(zero, false, pt, L);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2009 Sun Microsystems, Inc. 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
|
||||
@ -105,7 +105,7 @@ void InterpreterRuntime::SignatureHandlerGenerator::pass_object() {
|
||||
// the handle for a receiver will never be null
|
||||
bool do_NULL_check = offset() != 0 || is_static();
|
||||
|
||||
Address h_arg = Address(Llocals, 0, Interpreter::local_offset_in_bytes(offset()));
|
||||
Address h_arg = Address(Llocals, Interpreter::local_offset_in_bytes(offset()));
|
||||
__ ld_ptr(h_arg, Rtmp1);
|
||||
#ifdef ASSERT
|
||||
if (TaggedStackInterpreter) {
|
||||
@ -120,14 +120,14 @@ void InterpreterRuntime::SignatureHandlerGenerator::pass_object() {
|
||||
}
|
||||
#endif // ASSERT
|
||||
if (!do_NULL_check) {
|
||||
__ add(h_arg, Rtmp2);
|
||||
__ add(h_arg.base(), h_arg.disp(), Rtmp2);
|
||||
} else {
|
||||
if (Rtmp1 == Rtmp2)
|
||||
__ tst(Rtmp1);
|
||||
else __ addcc(G0, Rtmp1, Rtmp2); // optimize mov/test pair
|
||||
Label L;
|
||||
__ brx(Assembler::notZero, true, Assembler::pt, L);
|
||||
__ delayed()->add(h_arg, Rtmp2);
|
||||
__ delayed()->add(h_arg.base(), h_arg.disp(), Rtmp2);
|
||||
__ bind(L);
|
||||
}
|
||||
__ store_ptr_argument(Rtmp2, jni_arg); // this is often a no-op
|
||||
@ -140,10 +140,10 @@ void InterpreterRuntime::SignatureHandlerGenerator::generate(uint64_t fingerprin
|
||||
iterate(fingerprint);
|
||||
|
||||
// return result handler
|
||||
Address result_handler(Lscratch, Interpreter::result_handler(method()->result_type()));
|
||||
__ sethi(result_handler);
|
||||
AddressLiteral result_handler(Interpreter::result_handler(method()->result_type()));
|
||||
__ sethi(result_handler, Lscratch);
|
||||
__ retl();
|
||||
__ delayed()->add(result_handler, result_handler.base());
|
||||
__ delayed()->add(Lscratch, result_handler.low10(), Lscratch);
|
||||
|
||||
__ flush();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 2004-2009 Sun Microsystems, Inc. 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
|
||||
@ -57,10 +57,10 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
|
||||
|
||||
Label label1, label2;
|
||||
|
||||
address cnt_addr = SafepointSynchronize::safepoint_counter_addr();
|
||||
Address ca(O3, cnt_addr);
|
||||
__ sethi (ca);
|
||||
__ ld (ca, G4);
|
||||
AddressLiteral cnt_addrlit(SafepointSynchronize::safepoint_counter_addr());
|
||||
__ sethi (cnt_addrlit, O3);
|
||||
Address cnt_addr(O3, cnt_addrlit.low10());
|
||||
__ ld (cnt_addr, G4);
|
||||
__ andcc (G4, 1, G0);
|
||||
__ br (Assembler::notZero, false, Assembler::pn, label1);
|
||||
__ delayed()->srl (O2, 2, O4);
|
||||
@ -77,7 +77,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) {
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
|
||||
__ ld (ca, O5);
|
||||
__ ld (cnt_addr, O5);
|
||||
__ cmp (O5, G4);
|
||||
__ br (Assembler::notEqual, false, Assembler::pn, label2);
|
||||
__ delayed()->mov (O7, G1);
|
||||
@ -136,10 +136,10 @@ address JNI_FastGetField::generate_fast_get_long_field() {
|
||||
|
||||
Label label1, label2;
|
||||
|
||||
address cnt_addr = SafepointSynchronize::safepoint_counter_addr();
|
||||
Address ca(G3, cnt_addr);
|
||||
__ sethi (ca);
|
||||
__ ld (ca, G4);
|
||||
AddressLiteral cnt_addrlit(SafepointSynchronize::safepoint_counter_addr());
|
||||
__ sethi (cnt_addrlit, G3);
|
||||
Address cnt_addr(G3, cnt_addrlit.low10());
|
||||
__ ld (cnt_addr, G4);
|
||||
__ andcc (G4, 1, G0);
|
||||
__ br (Assembler::notZero, false, Assembler::pn, label1);
|
||||
__ delayed()->srl (O2, 2, O4);
|
||||
@ -159,7 +159,7 @@ address JNI_FastGetField::generate_fast_get_long_field() {
|
||||
__ ldx (O5, 0, O3);
|
||||
#endif
|
||||
|
||||
__ ld (ca, G1);
|
||||
__ ld (cnt_addr, G1);
|
||||
__ cmp (G1, G4);
|
||||
__ br (Assembler::notEqual, false, Assembler::pn, label2);
|
||||
__ delayed()->mov (O7, G1);
|
||||
@ -208,10 +208,10 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
|
||||
|
||||
Label label1, label2;
|
||||
|
||||
address cnt_addr = SafepointSynchronize::safepoint_counter_addr();
|
||||
Address ca(O3, cnt_addr);
|
||||
__ sethi (ca);
|
||||
__ ld (ca, G4);
|
||||
AddressLiteral cnt_addrlit(SafepointSynchronize::safepoint_counter_addr());
|
||||
__ sethi (cnt_addrlit, O3);
|
||||
Address cnt_addr(O3, cnt_addrlit.low10());
|
||||
__ ld (cnt_addr, G4);
|
||||
__ andcc (G4, 1, G0);
|
||||
__ br (Assembler::notZero, false, Assembler::pn, label1);
|
||||
__ delayed()->srl (O2, 2, O4);
|
||||
@ -225,7 +225,7 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) {
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
|
||||
__ ld (ca, O5);
|
||||
__ ld (cnt_addr, O5);
|
||||
__ cmp (O5, G4);
|
||||
__ br (Assembler::notEqual, false, Assembler::pn, label2);
|
||||
__ delayed()->mov (O7, G1);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||
@ -38,8 +38,7 @@ void NativeInstruction::set_data64_sethi(address instaddr, intptr_t x) {
|
||||
|
||||
destreg = inv_rd(*(unsigned int *)instaddr);
|
||||
// Generate a the new sequence
|
||||
Address dest( destreg, (address)x );
|
||||
_masm->sethi( dest, true );
|
||||
_masm->patchable_sethi(x, destreg);
|
||||
ICache::invalidate_range(instaddr, 7 * BytesPerInstWord);
|
||||
}
|
||||
|
||||
@ -227,8 +226,8 @@ void NativeFarCall::set_destination(address dest) {
|
||||
CodeBuffer buf(addr_at(0), instruction_size + 1);
|
||||
MacroAssembler* _masm = new MacroAssembler(&buf);
|
||||
// Generate the new sequence
|
||||
Address(O7, dest);
|
||||
_masm->jumpl_to(dest, O7);
|
||||
AddressLiteral(dest);
|
||||
_masm->jumpl_to(dest, O7, O7);
|
||||
ICache::invalidate_range(addr_at(0), instruction_size );
|
||||
#endif
|
||||
}
|
||||
@ -361,10 +360,12 @@ void NativeMovConstReg::test() {
|
||||
|
||||
VM_Version::allow_all();
|
||||
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none);
|
||||
a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->sethi(0xccccdddd, O2, true, RelocationHolder::none);
|
||||
a->add(O2, low10(0xccccdddd), O2);
|
||||
AddressLiteral al1(0xaaaabbbb, relocInfo::external_word_type);
|
||||
a->sethi(al1, I3);
|
||||
a->add(I3, al1.low10(), I3);
|
||||
AddressLiteral al2(0xccccdddd, relocInfo::external_word_type);
|
||||
a->sethi(al2, O2);
|
||||
a->add(O2, al2.low10(), O2);
|
||||
|
||||
nm = nativeMovConstReg_at( cb.code_begin() );
|
||||
nm->print();
|
||||
@ -468,12 +469,14 @@ void NativeMovConstRegPatching::test() {
|
||||
|
||||
VM_Version::allow_all();
|
||||
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none);
|
||||
AddressLiteral al1(0xaaaabbbb, relocInfo::external_word_type);
|
||||
a->sethi(al1, I3);
|
||||
a->nop();
|
||||
a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->sethi(0xccccdddd, O2, true, RelocationHolder::none);
|
||||
a->add(I3, al1.low10(), I3);
|
||||
AddressLiteral al2(0xccccdddd, relocInfo::external_word_type);
|
||||
a->sethi(al2, O2);
|
||||
a->nop();
|
||||
a->add(O2, low10(0xccccdddd), O2);
|
||||
a->add(O2, al2.low10(), O2);
|
||||
|
||||
nm = nativeMovConstRegPatching_at( cb.code_begin() );
|
||||
nm->print();
|
||||
@ -562,51 +565,53 @@ void NativeMovRegMem::test() {
|
||||
|
||||
VM_Version::allow_all();
|
||||
|
||||
a->ldsw( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
AddressLiteral al1(0xffffffff, relocInfo::external_word_type);
|
||||
AddressLiteral al2(0xaaaabbbb, relocInfo::external_word_type);
|
||||
a->ldsw( G5, al1.low10(), G4 ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->ldsw( G5, I3, G4 ); idx++;
|
||||
a->ldsb( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->ldsb( G5, al1.low10(), G4 ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->ldsb( G5, I3, G4 ); idx++;
|
||||
a->ldsh( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->ldsh( G5, al1.low10(), G4 ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->ldsh( G5, I3, G4 ); idx++;
|
||||
a->lduw( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->lduw( G5, al1.low10(), G4 ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->lduw( G5, I3, G4 ); idx++;
|
||||
a->ldub( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->ldub( G5, al1.low10(), G4 ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->ldub( G5, I3, G4 ); idx++;
|
||||
a->lduh( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->lduh( G5, al1.low10(), G4 ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->lduh( G5, I3, G4 ); idx++;
|
||||
a->ldx( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->ldx( G5, al1.low10(), G4 ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->ldx( G5, I3, G4 ); idx++;
|
||||
a->ldd( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->ldd( G5, al1.low10(), G4 ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->ldd( G5, I3, G4 ); idx++;
|
||||
a->ldf( FloatRegisterImpl::D, O2, -1, F14 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->ldf( FloatRegisterImpl::S, O0, I3, F15 ); idx++;
|
||||
|
||||
a->stw( G5, G4, low10(0xffffffff) ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->stw( G5, G4, al1.low10() ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->stw( G5, G4, I3 ); idx++;
|
||||
a->stb( G5, G4, low10(0xffffffff) ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->stb( G5, G4, al1.low10() ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->stb( G5, G4, I3 ); idx++;
|
||||
a->sth( G5, G4, low10(0xffffffff) ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->sth( G5, G4, al1.low10() ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->sth( G5, G4, I3 ); idx++;
|
||||
a->stx( G5, G4, low10(0xffffffff) ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->stx( G5, G4, al1.low10() ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->stx( G5, G4, I3 ); idx++;
|
||||
a->std( G5, G4, low10(0xffffffff) ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->std( G5, G4, al1.low10() ); idx++;
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->std( G5, G4, I3 ); idx++;
|
||||
a->stf( FloatRegisterImpl::S, F18, O2, -1 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->sethi(al2, I3); a->add(I3, al2.low10(), I3);
|
||||
a->stf( FloatRegisterImpl::S, F15, O0, I3 ); idx++;
|
||||
|
||||
nm = nativeMovRegMem_at( cb.code_begin() );
|
||||
@ -705,51 +710,52 @@ void NativeMovRegMemPatching::test() {
|
||||
|
||||
VM_Version::allow_all();
|
||||
|
||||
a->ldsw( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
AddressLiteral al(0xffffffff, relocInfo::external_word_type);
|
||||
a->ldsw( G5, al.low10(), G4); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->ldsw( G5, I3, G4 ); idx++;
|
||||
a->ldsb( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->ldsb( G5, al.low10(), G4); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->ldsb( G5, I3, G4 ); idx++;
|
||||
a->ldsh( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->ldsh( G5, al.low10(), G4); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->ldsh( G5, I3, G4 ); idx++;
|
||||
a->lduw( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->lduw( G5, al.low10(), G4); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->lduw( G5, I3, G4 ); idx++;
|
||||
a->ldub( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->ldub( G5, al.low10(), G4); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->ldub( G5, I3, G4 ); idx++;
|
||||
a->lduh( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->lduh( G5, al.low10(), G4); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->lduh( G5, I3, G4 ); idx++;
|
||||
a->ldx( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->ldx( G5, I3, G4 ); idx++;
|
||||
a->ldd( G5, low10(0xffffffff), G4 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->ldd( G5, I3, G4 ); idx++;
|
||||
a->ldf( FloatRegisterImpl::D, O2, -1, F14 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->ldf( FloatRegisterImpl::S, O0, I3, F15 ); idx++;
|
||||
a->ldx( G5, al.low10(), G4); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->ldx( G5, I3, G4 ); idx++;
|
||||
a->ldd( G5, al.low10(), G4); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->ldd( G5, I3, G4 ); idx++;
|
||||
a->ldf( FloatRegisterImpl::D, O2, -1, F14 ); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->ldf( FloatRegisterImpl::S, O0, I3, F15 ); idx++;
|
||||
|
||||
a->stw( G5, G4, low10(0xffffffff) ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->stw( G5, G4, al.low10()); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->stw( G5, G4, I3 ); idx++;
|
||||
a->stb( G5, G4, low10(0xffffffff) ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->stb( G5, G4, al.low10()); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->stb( G5, G4, I3 ); idx++;
|
||||
a->sth( G5, G4, low10(0xffffffff) ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->sth( G5, G4, al.low10()); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->sth( G5, G4, I3 ); idx++;
|
||||
a->stx( G5, G4, low10(0xffffffff) ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->stx( G5, G4, al.low10()); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->stx( G5, G4, I3 ); idx++;
|
||||
a->std( G5, G4, low10(0xffffffff) ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->std( G5, G4, al.low10()); idx++;
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->std( G5, G4, I3 ); idx++;
|
||||
a->stf( FloatRegisterImpl::S, F18, O2, -1 ); idx++;
|
||||
a->sethi(0xaaaabbbb, I3, true, RelocationHolder::none); a->nop(); a->add(I3, low10(0xaaaabbbb), I3);
|
||||
a->sethi(al, I3); a->nop(); a->add(I3, al.low10(), I3);
|
||||
a->stf( FloatRegisterImpl::S, F15, O0, I3 ); idx++;
|
||||
|
||||
nm = nativeMovRegMemPatching_at( cb.code_begin() );
|
||||
@ -833,11 +839,12 @@ void NativeJump::test() {
|
||||
|
||||
VM_Version::allow_all();
|
||||
|
||||
a->sethi(0x7fffbbbb, I3, true, RelocationHolder::none);
|
||||
a->jmpl(I3, low10(0x7fffbbbb), G0, RelocationHolder::none);
|
||||
AddressLiteral al(0x7fffbbbb, relocInfo::external_word_type);
|
||||
a->sethi(al, I3);
|
||||
a->jmpl(I3, al.low10(), G0, RelocationHolder::none);
|
||||
a->delayed()->nop();
|
||||
a->sethi(0x7fffbbbb, I3, true, RelocationHolder::none);
|
||||
a->jmpl(I3, low10(0x7fffbbbb), L3, RelocationHolder::none);
|
||||
a->sethi(al, I3);
|
||||
a->jmpl(I3, al.low10(), L3, RelocationHolder::none);
|
||||
a->delayed()->nop();
|
||||
|
||||
nj = nativeJump_at( cb.code_begin() );
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2009 Sun Microsystems, Inc. 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
|
||||
@ -99,13 +99,6 @@ void Relocation::pd_set_data_value(address x, intptr_t o) {
|
||||
break;
|
||||
}
|
||||
ip->set_data64_sethi( ip->addr_at(0), (intptr_t)x );
|
||||
#ifdef COMPILER2
|
||||
// [RGV] Someone must have missed putting in a reloc entry for the
|
||||
// add in compiler2.
|
||||
inst2 = ip->long_at( NativeMovConstReg::add_offset );
|
||||
guarantee(Assembler::inv_op(inst2)==Assembler::arith_op, "arith op");
|
||||
ip->set_long_at(NativeMovConstReg::add_offset,ip->set_data32_simm13( inst2, (intptr_t)x+o));
|
||||
#endif
|
||||
#else
|
||||
guarantee(Assembler::inv_op2(inst)==Assembler::sethi_op2, "must be sethi");
|
||||
inst &= ~Assembler::hi22( -1);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1998-2009 Sun Microsystems, Inc. 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
|
||||
@ -74,8 +74,8 @@ void OptoRuntime::generate_exception_blob() {
|
||||
int start = __ offset();
|
||||
|
||||
__ verify_thread();
|
||||
__ st_ptr(Oexception, Address(G2_thread, 0, in_bytes(JavaThread::exception_oop_offset())));
|
||||
__ st_ptr(Oissuing_pc, Address(G2_thread, 0, in_bytes(JavaThread::exception_pc_offset())));
|
||||
__ st_ptr(Oexception, G2_thread, JavaThread::exception_oop_offset());
|
||||
__ st_ptr(Oissuing_pc, G2_thread, JavaThread::exception_pc_offset());
|
||||
|
||||
// This call does all the hard work. It checks if an exception catch
|
||||
// exists in the method.
|
||||
@ -120,19 +120,19 @@ void OptoRuntime::generate_exception_blob() {
|
||||
// Since this may be the deopt blob we must set O7 to look like we returned
|
||||
// from the original pc that threw the exception
|
||||
|
||||
__ ld_ptr(Address(G2_thread, 0, in_bytes(JavaThread::exception_pc_offset())), O7);
|
||||
__ ld_ptr(G2_thread, JavaThread::exception_pc_offset(), O7);
|
||||
__ sub(O7, frame::pc_return_offset, O7);
|
||||
|
||||
|
||||
assert(Assembler::is_simm13(in_bytes(JavaThread::exception_oop_offset())), "exception offset overflows simm13, following ld instruction cannot be in delay slot");
|
||||
__ ld_ptr(Address(G2_thread, 0, in_bytes(JavaThread::exception_oop_offset())), Oexception); // O0
|
||||
__ ld_ptr(G2_thread, JavaThread::exception_oop_offset(), Oexception); // O0
|
||||
#ifdef ASSERT
|
||||
__ st_ptr(G0, Address(G2_thread, 0, in_bytes(JavaThread::exception_handler_pc_offset())));
|
||||
__ st_ptr(G0, Address(G2_thread, 0, in_bytes(JavaThread::exception_pc_offset())));
|
||||
__ st_ptr(G0, G2_thread, JavaThread::exception_handler_pc_offset());
|
||||
__ st_ptr(G0, G2_thread, JavaThread::exception_pc_offset());
|
||||
#endif
|
||||
__ JMP(G3_scratch, 0);
|
||||
// Clear the exception oop so GC no longer processes it as a root.
|
||||
__ delayed()->st_ptr(G0, Address(G2_thread, 0, in_bytes(JavaThread::exception_oop_offset())));
|
||||
__ delayed()->st_ptr(G0, G2_thread, JavaThread::exception_oop_offset());
|
||||
|
||||
// -------------
|
||||
// make sure all code is generated
|
||||
|
@ -625,9 +625,9 @@ void AdapterGenerator::patch_callers_callsite() {
|
||||
__ mov(I7, O1); // VM needs caller's callsite
|
||||
// Must be a leaf call...
|
||||
// can be very far once the blob has been relocated
|
||||
Address dest(O7, CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite));
|
||||
AddressLiteral dest(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite));
|
||||
__ relocate(relocInfo::runtime_call_type);
|
||||
__ jumpl_to(dest, O7);
|
||||
__ jumpl_to(dest, O7, O7);
|
||||
__ delayed()->mov(G2_thread, L7_thread_cache);
|
||||
__ mov(L7_thread_cache, G2_thread);
|
||||
__ mov(L1, G1);
|
||||
@ -1152,7 +1152,7 @@ void AdapterGenerator::gen_i2c_adapter(
|
||||
#ifndef _LP64
|
||||
if (g3_crushed) {
|
||||
// Rats load was wasted, at least it is in cache...
|
||||
__ ld_ptr(G5_method, in_bytes(methodOopDesc::from_compiled_offset()), G3);
|
||||
__ ld_ptr(G5_method, methodOopDesc::from_compiled_offset(), G3);
|
||||
}
|
||||
#endif /* _LP64 */
|
||||
|
||||
@ -1165,7 +1165,7 @@ void AdapterGenerator::gen_i2c_adapter(
|
||||
// we try and find the callee by normal means a safepoint
|
||||
// is possible. So we stash the desired callee in the thread
|
||||
// and the vm will find there should this case occur.
|
||||
Address callee_target_addr(G2_thread, 0, in_bytes(JavaThread::callee_target_offset()));
|
||||
Address callee_target_addr(G2_thread, JavaThread::callee_target_offset());
|
||||
__ st_ptr(G5_method, callee_target_addr);
|
||||
|
||||
if (StressNonEntrant) {
|
||||
@ -1218,7 +1218,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||
Register R_temp = G1; // another scratch register
|
||||
#endif
|
||||
|
||||
Address ic_miss(G3_scratch, SharedRuntime::get_ic_miss_stub());
|
||||
AddressLiteral ic_miss(SharedRuntime::get_ic_miss_stub());
|
||||
|
||||
__ verify_oop(O0);
|
||||
__ verify_oop(G5_method);
|
||||
@ -1240,7 +1240,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||
Label ok, ok2;
|
||||
__ brx(Assembler::equal, false, Assembler::pt, ok);
|
||||
__ delayed()->ld_ptr(G5_method, compiledICHolderOopDesc::holder_method_offset(), G5_method);
|
||||
__ jump_to(ic_miss);
|
||||
__ jump_to(ic_miss, G3_scratch);
|
||||
__ delayed()->nop();
|
||||
|
||||
__ bind(ok);
|
||||
@ -1251,7 +1251,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
|
||||
__ bind(ok2);
|
||||
__ br_null(G3_scratch, false, __ pt, skip_fixup);
|
||||
__ delayed()->ld_ptr(G5_method, in_bytes(methodOopDesc::interpreter_entry_offset()), G3_scratch);
|
||||
__ jump_to(ic_miss);
|
||||
__ jump_to(ic_miss, G3_scratch);
|
||||
__ delayed()->nop();
|
||||
|
||||
}
|
||||
@ -1444,8 +1444,8 @@ static void check_forward_pending_exception(MacroAssembler *masm, Register Rex_o
|
||||
// without calling into the VM: it's the empty function. Just pop this
|
||||
// frame and then jump to forward_exception_entry; O7 will contain the
|
||||
// native caller's return PC.
|
||||
Address exception_entry(G3_scratch, StubRoutines::forward_exception_entry());
|
||||
__ jump_to(exception_entry);
|
||||
AddressLiteral exception_entry(StubRoutines::forward_exception_entry());
|
||||
__ jump_to(exception_entry, G3_scratch);
|
||||
__ delayed()->restore(); // Pop this frame off.
|
||||
__ bind(L);
|
||||
}
|
||||
@ -1822,14 +1822,14 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
{
|
||||
Label L;
|
||||
const Register temp_reg = G3_scratch;
|
||||
Address ic_miss(temp_reg, SharedRuntime::get_ic_miss_stub());
|
||||
AddressLiteral ic_miss(SharedRuntime::get_ic_miss_stub());
|
||||
__ verify_oop(O0);
|
||||
__ load_klass(O0, temp_reg);
|
||||
__ cmp(temp_reg, G5_inline_cache_reg);
|
||||
__ brx(Assembler::equal, true, Assembler::pt, L);
|
||||
__ delayed()->nop();
|
||||
|
||||
__ jump_to(ic_miss, 0);
|
||||
__ jump_to(ic_miss, temp_reg);
|
||||
__ delayed()->nop();
|
||||
__ align(CodeEntryAlignment);
|
||||
__ bind(L);
|
||||
@ -2261,21 +2261,19 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
|
||||
// Transition from _thread_in_Java to _thread_in_native.
|
||||
__ set(_thread_in_native, G3_scratch);
|
||||
__ st(G3_scratch, G2_thread, in_bytes(JavaThread::thread_state_offset()));
|
||||
__ st(G3_scratch, G2_thread, JavaThread::thread_state_offset());
|
||||
|
||||
// We flushed the windows ages ago now mark them as flushed
|
||||
|
||||
// mark windows as flushed
|
||||
__ set(JavaFrameAnchor::flushed, G3_scratch);
|
||||
|
||||
Address flags(G2_thread,
|
||||
0,
|
||||
in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::flags_offset()));
|
||||
Address flags(G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::flags_offset());
|
||||
|
||||
#ifdef _LP64
|
||||
Address dest(O7, method->native_function());
|
||||
AddressLiteral dest(method->native_function());
|
||||
__ relocate(relocInfo::runtime_call_type);
|
||||
__ jumpl_to(dest, O7);
|
||||
__ jumpl_to(dest, O7, O7);
|
||||
#else
|
||||
__ call(method->native_function(), relocInfo::runtime_call_type);
|
||||
#endif
|
||||
@ -2316,7 +2314,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
// Block, if necessary, before resuming in _thread_in_Java state.
|
||||
// In order for GC to work, don't clear the last_Java_sp until after blocking.
|
||||
{ Label no_block;
|
||||
Address sync_state(G3_scratch, SafepointSynchronize::address_of_state());
|
||||
AddressLiteral sync_state(SafepointSynchronize::address_of_state());
|
||||
|
||||
// Switch thread to "native transition" state before reading the synchronization state.
|
||||
// This additional state is necessary because reading and testing the synchronization
|
||||
@ -2326,7 +2324,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
// Thread A is resumed to finish this native method, but doesn't block here since it
|
||||
// didn't see any synchronization is progress, and escapes.
|
||||
__ set(_thread_in_native_trans, G3_scratch);
|
||||
__ st(G3_scratch, G2_thread, in_bytes(JavaThread::thread_state_offset()));
|
||||
__ st(G3_scratch, G2_thread, JavaThread::thread_state_offset());
|
||||
if(os::is_MP()) {
|
||||
if (UseMembar) {
|
||||
// Force this write out before the read below
|
||||
@ -2343,10 +2341,9 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
__ cmp(G3_scratch, SafepointSynchronize::_not_synchronized);
|
||||
|
||||
Label L;
|
||||
Address suspend_state(G2_thread, 0, in_bytes(JavaThread::suspend_flags_offset()));
|
||||
Address suspend_state(G2_thread, JavaThread::suspend_flags_offset());
|
||||
__ br(Assembler::notEqual, false, Assembler::pn, L);
|
||||
__ delayed()->
|
||||
ld(suspend_state, G3_scratch);
|
||||
__ delayed()->ld(suspend_state, G3_scratch);
|
||||
__ cmp(G3_scratch, 0);
|
||||
__ br(Assembler::equal, false, Assembler::pt, no_block);
|
||||
__ delayed()->nop();
|
||||
@ -2372,11 +2369,11 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
|
||||
|
||||
__ set(_thread_in_Java, G3_scratch);
|
||||
__ st(G3_scratch, G2_thread, in_bytes(JavaThread::thread_state_offset()));
|
||||
__ st(G3_scratch, G2_thread, JavaThread::thread_state_offset());
|
||||
|
||||
|
||||
Label no_reguard;
|
||||
__ ld(G2_thread, in_bytes(JavaThread::stack_guard_state_offset()), G3_scratch);
|
||||
__ ld(G2_thread, JavaThread::stack_guard_state_offset(), G3_scratch);
|
||||
__ cmp(G3_scratch, JavaThread::stack_guard_yellow_disabled);
|
||||
__ br(Assembler::notEqual, false, Assembler::pt, no_reguard);
|
||||
__ delayed()->nop();
|
||||
@ -2684,14 +2681,14 @@ nmethod *SharedRuntime::generate_dtrace_nmethod(
|
||||
{
|
||||
Label L;
|
||||
const Register temp_reg = G3_scratch;
|
||||
Address ic_miss(temp_reg, SharedRuntime::get_ic_miss_stub());
|
||||
AddressLiteral ic_miss(SharedRuntime::get_ic_miss_stub());
|
||||
__ verify_oop(O0);
|
||||
__ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), temp_reg);
|
||||
__ cmp(temp_reg, G5_inline_cache_reg);
|
||||
__ brx(Assembler::equal, true, Assembler::pt, L);
|
||||
__ delayed()->nop();
|
||||
|
||||
__ jump_to(ic_miss, 0);
|
||||
__ jump_to(ic_miss, temp_reg);
|
||||
__ delayed()->nop();
|
||||
__ align(CodeEntryAlignment);
|
||||
__ bind(L);
|
||||
@ -3155,15 +3152,13 @@ static void make_new_frames(MacroAssembler* masm, bool deopt) {
|
||||
// Do this after the caller's return address is on top of stack
|
||||
if (UseStackBanging) {
|
||||
// Get total frame size for interpreted frames
|
||||
__ ld(Address(O2UnrollBlock, 0,
|
||||
Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes()), O4);
|
||||
__ ld(O2UnrollBlock, Deoptimization::UnrollBlock::total_frame_sizes_offset_in_bytes(), O4);
|
||||
__ bang_stack_size(O4, O3, G3_scratch);
|
||||
}
|
||||
|
||||
__ ld(Address(O2UnrollBlock, 0, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes()), O4array_size);
|
||||
__ ld_ptr(Address(O2UnrollBlock, 0, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes()), G3pcs);
|
||||
|
||||
__ ld_ptr(Address(O2UnrollBlock, 0, Deoptimization::UnrollBlock::frame_sizes_offset_in_bytes()), O3array);
|
||||
__ ld(O2UnrollBlock, Deoptimization::UnrollBlock::number_of_frames_offset_in_bytes(), O4array_size);
|
||||
__ ld_ptr(O2UnrollBlock, Deoptimization::UnrollBlock::frame_pcs_offset_in_bytes(), G3pcs);
|
||||
__ ld_ptr(O2UnrollBlock, Deoptimization::UnrollBlock::frame_sizes_offset_in_bytes(), O3array);
|
||||
|
||||
// Adjust old interpreter frame to make space for new frame's extra java locals
|
||||
//
|
||||
@ -3176,7 +3171,7 @@ static void make_new_frames(MacroAssembler* masm, bool deopt) {
|
||||
// for each frame we create and keep up the illusion every where.
|
||||
//
|
||||
|
||||
__ ld(Address(O2UnrollBlock, 0, Deoptimization::UnrollBlock::caller_adjustment_offset_in_bytes()), O7);
|
||||
__ ld(O2UnrollBlock, Deoptimization::UnrollBlock::caller_adjustment_offset_in_bytes(), O7);
|
||||
__ mov(SP, O5_savedSP); // remember initial sender's original sp before adjustment
|
||||
__ sub(SP, O7, SP);
|
||||
|
||||
@ -3225,9 +3220,9 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
Register I5exception_tmp = I5;
|
||||
Register G4exception_tmp = G4_scratch;
|
||||
int frame_size_words;
|
||||
Address saved_Freturn0_addr(FP, 0, -sizeof(double) + STACK_BIAS);
|
||||
Address saved_Freturn0_addr(FP, -sizeof(double) + STACK_BIAS);
|
||||
#if !defined(_LP64) && defined(COMPILER2)
|
||||
Address saved_Greturn1_addr(FP, 0, -sizeof(double) -sizeof(jlong) + STACK_BIAS);
|
||||
Address saved_Greturn1_addr(FP, -sizeof(double) -sizeof(jlong) + STACK_BIAS);
|
||||
#endif
|
||||
Label cont;
|
||||
|
||||
@ -3289,7 +3284,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
// save exception oop in JavaThread and fall through into the
|
||||
// exception_in_tls case since they are handled in same way except
|
||||
// for where the pending exception is kept.
|
||||
__ st_ptr(Oexception, G2_thread, in_bytes(JavaThread::exception_oop_offset()));
|
||||
__ st_ptr(Oexception, G2_thread, JavaThread::exception_oop_offset());
|
||||
|
||||
//
|
||||
// Vanilla deoptimization with an exception pending in exception_oop
|
||||
@ -3306,7 +3301,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
{
|
||||
// verify that there is really an exception oop in exception_oop
|
||||
Label has_exception;
|
||||
__ ld_ptr(G2_thread, in_bytes(JavaThread::exception_oop_offset()), Oexception);
|
||||
__ ld_ptr(G2_thread, JavaThread::exception_oop_offset(), Oexception);
|
||||
__ br_notnull(Oexception, false, Assembler::pt, has_exception);
|
||||
__ delayed()-> nop();
|
||||
__ stop("no exception in thread");
|
||||
@ -3314,7 +3309,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||
|
||||
// verify that there is no pending exception
|
||||
Label no_pending_exception;
|
||||
Address exception_addr(G2_thread, 0, in_bytes(Thread::pending_exception_offset()));
|
||||
Address exception_addr(G2_thread, Thread::pending_exception_offset());
|
||||
__ ld_ptr(exception_addr, Oexception);
|
||||
__ br_null(Oexception, false, Assembler::pt, no_pending_exception);
|
||||
__ delayed()->nop();
|
||||
|
@ -980,8 +980,8 @@ void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocTyp
|
||||
// This code sequence is relocatable to any address, even on LP64.
|
||||
if ( force_far_call ) {
|
||||
__ relocate(rtype);
|
||||
Address dest(O7, (address)entry_point);
|
||||
__ jumpl_to(dest, O7);
|
||||
AddressLiteral dest(entry_point);
|
||||
__ jumpl_to(dest, O7, O7);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -1031,17 +1031,6 @@ void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, relocInfo::relocTyp
|
||||
void emit_lo(CodeBuffer &cbuf, int val) { }
|
||||
void emit_hi(CodeBuffer &cbuf, int val) { }
|
||||
|
||||
void emit_ptr(CodeBuffer &cbuf, intptr_t val, Register reg, bool ForceRelocatable) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
if (ForceRelocatable) {
|
||||
Address addr(reg, (address)val);
|
||||
__ sethi(addr, ForceRelocatable);
|
||||
__ add(addr, reg);
|
||||
} else {
|
||||
__ set(val, reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
||||
@ -1149,8 +1138,8 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
|
||||
// If this does safepoint polling, then do it here
|
||||
if( do_polling() && ra_->C->is_method_compilation() ) {
|
||||
Address polling_page(L0, (address)os::get_polling_page());
|
||||
__ sethi(polling_page, false);
|
||||
AddressLiteral polling_page(os::get_polling_page());
|
||||
__ sethi(polling_page, L0);
|
||||
__ relocate(relocInfo::poll_return_type);
|
||||
__ ld_ptr( L0, 0, G0 );
|
||||
}
|
||||
@ -1576,8 +1565,8 @@ void emit_java_to_interp(CodeBuffer &cbuf ) {
|
||||
__ set_oop(NULL, reg_to_register_object(Matcher::inline_cache_reg_encode()));
|
||||
|
||||
__ set_inst_mark();
|
||||
Address a(G3, (address)-1);
|
||||
__ JUMP(a, 0);
|
||||
AddressLiteral addrlit(-1);
|
||||
__ JUMP(addrlit, G3, 0);
|
||||
|
||||
__ delayed()->nop();
|
||||
|
||||
@ -1662,7 +1651,7 @@ uint size_deopt_handler() {
|
||||
// Emit exception handler code.
|
||||
int emit_exception_handler(CodeBuffer& cbuf) {
|
||||
Register temp_reg = G3;
|
||||
Address exception_blob(temp_reg, OptoRuntime::exception_blob()->instructions_begin());
|
||||
AddressLiteral exception_blob(OptoRuntime::exception_blob()->instructions_begin());
|
||||
MacroAssembler _masm(&cbuf);
|
||||
|
||||
address base =
|
||||
@ -1671,7 +1660,7 @@ int emit_exception_handler(CodeBuffer& cbuf) {
|
||||
|
||||
int offset = __ offset();
|
||||
|
||||
__ JUMP(exception_blob, 0); // sethi;jmp
|
||||
__ JUMP(exception_blob, temp_reg, 0); // sethi;jmp
|
||||
__ delayed()->nop();
|
||||
|
||||
assert(__ offset() - offset <= (int) size_exception_handler(), "overflow");
|
||||
@ -1685,7 +1674,7 @@ int emit_deopt_handler(CodeBuffer& cbuf) {
|
||||
// Can't use any of the current frame's registers as we may have deopted
|
||||
// at a poll and everything (including G3) can be live.
|
||||
Register temp_reg = L0;
|
||||
Address deopt_blob(temp_reg, SharedRuntime::deopt_blob()->unpack());
|
||||
AddressLiteral deopt_blob(SharedRuntime::deopt_blob()->unpack());
|
||||
MacroAssembler _masm(&cbuf);
|
||||
|
||||
address base =
|
||||
@ -1694,7 +1683,7 @@ int emit_deopt_handler(CodeBuffer& cbuf) {
|
||||
|
||||
int offset = __ offset();
|
||||
__ save_frame(0);
|
||||
__ JUMP(deopt_blob, 0); // sethi;jmp
|
||||
__ JUMP(deopt_blob, temp_reg, 0); // sethi;jmp
|
||||
__ delayed()->restore();
|
||||
|
||||
assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow");
|
||||
@ -2261,9 +2250,8 @@ encode %{
|
||||
address table_base = __ address_table_constant(_index2label);
|
||||
RelocationHolder rspec = internal_word_Relocation::spec(table_base);
|
||||
|
||||
// Load table address
|
||||
Address the_pc(table_reg, table_base, rspec);
|
||||
__ load_address(the_pc);
|
||||
// Move table address into a register.
|
||||
__ set(table_base, table_reg, rspec);
|
||||
|
||||
// Jump to base address + switch value
|
||||
__ ld_ptr(table_reg, switch_reg, table_reg);
|
||||
@ -2402,13 +2390,13 @@ encode %{
|
||||
// The 64 bit pointer is stored in the generated code stream
|
||||
enc_class SetPtr( immP src, iRegP rd ) %{
|
||||
Register dest = reg_to_register_object($rd$$reg);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
// [RGV] This next line should be generated from ADLC
|
||||
if ( _opnds[1]->constant_is_oop() ) {
|
||||
intptr_t val = $src$$constant;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
__ set_oop_constant((jobject)val, dest);
|
||||
} else { // non-oop pointers, e.g. card mark base, heap top
|
||||
emit_ptr(cbuf, $src$$constant, dest, /*ForceRelocatable=*/ false);
|
||||
__ set($src$$constant, dest);
|
||||
}
|
||||
%}
|
||||
|
||||
@ -2789,46 +2777,6 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
__ set64( $src$$constant, dest, temp );
|
||||
%}
|
||||
|
||||
enc_class LdImmF(immF src, regF dst, o7RegP tmp) %{ // Load Immediate
|
||||
address float_address = MacroAssembler(&cbuf).float_constant($src$$constant);
|
||||
RelocationHolder rspec = internal_word_Relocation::spec(float_address);
|
||||
#ifdef _LP64
|
||||
Register tmp_reg = reg_to_register_object($tmp$$reg);
|
||||
cbuf.relocate(cbuf.code_end(), rspec, 0);
|
||||
emit_ptr(cbuf, (intptr_t)float_address, tmp_reg, /*ForceRelocatable=*/ true);
|
||||
emit3_simm10( cbuf, Assembler::ldst_op, $dst$$reg, Assembler::ldf_op3, $tmp$$reg, 0 );
|
||||
#else // _LP64
|
||||
uint *code;
|
||||
int tmp_reg = $tmp$$reg;
|
||||
|
||||
cbuf.relocate(cbuf.code_end(), rspec, 0);
|
||||
emit2_22( cbuf, Assembler::branch_op, tmp_reg, Assembler::sethi_op2, (intptr_t) float_address );
|
||||
|
||||
cbuf.relocate(cbuf.code_end(), rspec, 0);
|
||||
emit3_simm10( cbuf, Assembler::ldst_op, $dst$$reg, Assembler::ldf_op3, tmp_reg, (intptr_t) float_address );
|
||||
#endif // _LP64
|
||||
%}
|
||||
|
||||
enc_class LdImmD(immD src, regD dst, o7RegP tmp) %{ // Load Immediate
|
||||
address double_address = MacroAssembler(&cbuf).double_constant($src$$constant);
|
||||
RelocationHolder rspec = internal_word_Relocation::spec(double_address);
|
||||
#ifdef _LP64
|
||||
Register tmp_reg = reg_to_register_object($tmp$$reg);
|
||||
cbuf.relocate(cbuf.code_end(), rspec, 0);
|
||||
emit_ptr(cbuf, (intptr_t)double_address, tmp_reg, /*ForceRelocatable=*/ true);
|
||||
emit3_simm10( cbuf, Assembler::ldst_op, $dst$$reg, Assembler::lddf_op3, $tmp$$reg, 0 );
|
||||
#else // _LP64
|
||||
uint *code;
|
||||
int tmp_reg = $tmp$$reg;
|
||||
|
||||
cbuf.relocate(cbuf.code_end(), rspec, 0);
|
||||
emit2_22( cbuf, Assembler::branch_op, tmp_reg, Assembler::sethi_op2, (intptr_t) double_address );
|
||||
|
||||
cbuf.relocate(cbuf.code_end(), rspec, 0);
|
||||
emit3_simm10( cbuf, Assembler::ldst_op, $dst$$reg, Assembler::lddf_op3, tmp_reg, (intptr_t) double_address );
|
||||
#endif // _LP64
|
||||
%}
|
||||
|
||||
enc_class LdReplImmI(immI src, regD dst, o7RegP tmp, int count, int width) %{
|
||||
// Load a constant replicated "count" times with width "width"
|
||||
int bit_width = $width$$constant * 8;
|
||||
@ -2840,28 +2788,15 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
val |= elt_val;
|
||||
}
|
||||
jdouble dval = *(jdouble*)&val; // coerce to double type
|
||||
address double_address = MacroAssembler(&cbuf).double_constant(dval);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
address double_address = __ double_constant(dval);
|
||||
RelocationHolder rspec = internal_word_Relocation::spec(double_address);
|
||||
#ifdef _LP64
|
||||
Register tmp_reg = reg_to_register_object($tmp$$reg);
|
||||
cbuf.relocate(cbuf.code_end(), rspec, 0);
|
||||
emit_ptr(cbuf, (intptr_t)double_address, tmp_reg, /*ForceRelocatable=*/ true);
|
||||
emit3_simm10( cbuf, Assembler::ldst_op, $dst$$reg, Assembler::lddf_op3, $tmp$$reg, 0 );
|
||||
#else // _LP64
|
||||
uint *code;
|
||||
int tmp_reg = $tmp$$reg;
|
||||
AddressLiteral addrlit(double_address, rspec);
|
||||
|
||||
cbuf.relocate(cbuf.code_end(), rspec, 0);
|
||||
emit2_22( cbuf, Assembler::branch_op, tmp_reg, Assembler::sethi_op2, (intptr_t) double_address );
|
||||
|
||||
cbuf.relocate(cbuf.code_end(), rspec, 0);
|
||||
emit3_simm10( cbuf, Assembler::ldst_op, $dst$$reg, Assembler::lddf_op3, tmp_reg, (intptr_t) double_address );
|
||||
#endif // _LP64
|
||||
%}
|
||||
|
||||
|
||||
enc_class ShouldNotEncodeThis ( ) %{
|
||||
ShouldNotCallThis();
|
||||
__ sethi(addrlit, $tmp$$Register);
|
||||
// XXX This is a quick fix for 6833573.
|
||||
//__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec);
|
||||
__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), as_DoubleFloatRegister($dst$$reg), rspec);
|
||||
%}
|
||||
|
||||
// Compiler ensures base is doubleword aligned and cnt is count of doublewords
|
||||
@ -2901,19 +2836,19 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
int count_offset = java_lang_String:: count_offset_in_bytes();
|
||||
|
||||
// load str1 (jchar*) base address into tmp1_reg
|
||||
__ load_heap_oop(Address(str1_reg, 0, value_offset), tmp1_reg);
|
||||
__ ld(Address(str1_reg, 0, offset_offset), result_reg);
|
||||
__ load_heap_oop(str1_reg, value_offset, tmp1_reg);
|
||||
__ ld(str1_reg, offset_offset, result_reg);
|
||||
__ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg);
|
||||
__ ld(Address(str1_reg, 0, count_offset), str1_reg); // hoisted
|
||||
__ ld(str1_reg, count_offset, str1_reg); // hoisted
|
||||
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
|
||||
__ load_heap_oop(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted
|
||||
__ load_heap_oop(str2_reg, value_offset, tmp2_reg); // hoisted
|
||||
__ add(result_reg, tmp1_reg, tmp1_reg);
|
||||
|
||||
// load str2 (jchar*) base address into tmp2_reg
|
||||
// __ ld_ptr(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted
|
||||
__ ld(Address(str2_reg, 0, offset_offset), result_reg);
|
||||
// __ ld_ptr(str2_reg, value_offset, tmp2_reg); // hoisted
|
||||
__ ld(str2_reg, offset_offset, result_reg);
|
||||
__ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg);
|
||||
__ ld(Address(str2_reg, 0, count_offset), str2_reg); // hoisted
|
||||
__ ld(str2_reg, count_offset, str2_reg); // hoisted
|
||||
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
|
||||
__ subcc(str1_reg, str2_reg, O7); // hoisted
|
||||
__ add(result_reg, tmp2_reg, tmp2_reg);
|
||||
@ -2922,8 +2857,8 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
// difference of the string lengths (stack)
|
||||
|
||||
// discard string base pointers, after loading up the lengths
|
||||
// __ ld(Address(str1_reg, 0, count_offset), str1_reg); // hoisted
|
||||
// __ ld(Address(str2_reg, 0, count_offset), str2_reg); // hoisted
|
||||
// __ ld(str1_reg, count_offset, str1_reg); // hoisted
|
||||
// __ ld(str2_reg, count_offset, str2_reg); // hoisted
|
||||
|
||||
// See if the lengths are different, and calculate min in str1_reg.
|
||||
// Stash diff in O7 in case we need it for a tie-breaker.
|
||||
@ -3020,19 +2955,19 @@ enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2,
|
||||
int count_offset = java_lang_String:: count_offset_in_bytes();
|
||||
|
||||
// load str1 (jchar*) base address into tmp1_reg
|
||||
__ load_heap_oop(Address(str1_reg, 0, value_offset), tmp1_reg);
|
||||
__ ld(Address(str1_reg, 0, offset_offset), result_reg);
|
||||
__ load_heap_oop(Address(str1_reg, value_offset), tmp1_reg);
|
||||
__ ld(Address(str1_reg, offset_offset), result_reg);
|
||||
__ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg);
|
||||
__ ld(Address(str1_reg, 0, count_offset), str1_reg); // hoisted
|
||||
__ ld(Address(str1_reg, count_offset), str1_reg); // hoisted
|
||||
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
|
||||
__ load_heap_oop(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted
|
||||
__ load_heap_oop(Address(str2_reg, value_offset), tmp2_reg); // hoisted
|
||||
__ add(result_reg, tmp1_reg, tmp1_reg);
|
||||
|
||||
// load str2 (jchar*) base address into tmp2_reg
|
||||
// __ ld_ptr(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted
|
||||
__ ld(Address(str2_reg, 0, offset_offset), result_reg);
|
||||
// __ ld_ptr(Address(str2_reg, value_offset), tmp2_reg); // hoisted
|
||||
__ ld(Address(str2_reg, offset_offset), result_reg);
|
||||
__ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg);
|
||||
__ ld(Address(str2_reg, 0, count_offset), str2_reg); // hoisted
|
||||
__ ld(Address(str2_reg, count_offset), str2_reg); // hoisted
|
||||
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
|
||||
__ cmp(str1_reg, str2_reg); // hoisted
|
||||
__ add(result_reg, tmp2_reg, tmp2_reg);
|
||||
@ -3139,8 +3074,8 @@ enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, n
|
||||
__ delayed()->mov(G0, result_reg); // not equal
|
||||
|
||||
//load the lengths of arrays
|
||||
__ ld(Address(ary1_reg, 0, length_offset), tmp1_reg);
|
||||
__ ld(Address(ary2_reg, 0, length_offset), tmp2_reg);
|
||||
__ ld(Address(ary1_reg, length_offset), tmp1_reg);
|
||||
__ ld(Address(ary2_reg, length_offset), tmp2_reg);
|
||||
|
||||
// return false if the two arrays are not equal length
|
||||
__ cmp(tmp1_reg, tmp2_reg);
|
||||
@ -3202,19 +3137,20 @@ enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, n
|
||||
enc_class enc_rethrow() %{
|
||||
cbuf.set_inst_mark();
|
||||
Register temp_reg = G3;
|
||||
Address rethrow_stub(temp_reg, OptoRuntime::rethrow_stub());
|
||||
AddressLiteral rethrow_stub(OptoRuntime::rethrow_stub());
|
||||
assert(temp_reg != reg_to_register_object(R_I0_num), "temp must not break oop_reg");
|
||||
MacroAssembler _masm(&cbuf);
|
||||
#ifdef ASSERT
|
||||
__ save_frame(0);
|
||||
Address last_rethrow_addr(L1, (address)&last_rethrow);
|
||||
__ sethi(last_rethrow_addr);
|
||||
AddressLiteral last_rethrow_addrlit(&last_rethrow);
|
||||
__ sethi(last_rethrow_addrlit, L1);
|
||||
Address addr(L1, last_rethrow_addrlit.low10());
|
||||
__ get_pc(L2);
|
||||
__ inc(L2, 3 * BytesPerInstWord); // skip this & 2 more insns to point at jump_to
|
||||
__ st_ptr(L2, last_rethrow_addr);
|
||||
__ st_ptr(L2, addr);
|
||||
__ restore();
|
||||
#endif
|
||||
__ JUMP(rethrow_stub, 0); // sethi;jmp
|
||||
__ JUMP(rethrow_stub, temp_reg, 0); // sethi;jmp
|
||||
__ delayed()->nop();
|
||||
%}
|
||||
|
||||
@ -5493,8 +5429,9 @@ instruct loadB(iRegI dst, memory mem) %{
|
||||
|
||||
size(4);
|
||||
format %{ "LDSB $mem,$dst\t! byte" %}
|
||||
opcode(Assembler::ldsb_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_encode %{
|
||||
__ ldsb($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
@ -5505,8 +5442,9 @@ instruct loadB2L(iRegL dst, memory mem) %{
|
||||
|
||||
size(4);
|
||||
format %{ "LDSB $mem,$dst\t! byte -> long" %}
|
||||
opcode(Assembler::ldsb_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_encode %{
|
||||
__ ldsb($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
@ -5517,8 +5455,9 @@ instruct loadUB(iRegI dst, memory mem) %{
|
||||
|
||||
size(4);
|
||||
format %{ "LDUB $mem,$dst\t! ubyte" %}
|
||||
opcode(Assembler::ldub_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_encode %{
|
||||
__ ldub($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
@ -5529,8 +5468,9 @@ instruct loadUB2L(iRegL dst, memory mem) %{
|
||||
|
||||
size(4);
|
||||
format %{ "LDUB $mem,$dst\t! ubyte -> long" %}
|
||||
opcode(Assembler::ldub_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_encode %{
|
||||
__ ldub($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
@ -5541,8 +5481,9 @@ instruct loadS(iRegI dst, memory mem) %{
|
||||
|
||||
size(4);
|
||||
format %{ "LDSH $mem,$dst\t! short" %}
|
||||
opcode(Assembler::ldsh_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_encode %{
|
||||
__ ldsh($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
@ -5553,8 +5494,9 @@ instruct loadS2L(iRegL dst, memory mem) %{
|
||||
|
||||
size(4);
|
||||
format %{ "LDSH $mem,$dst\t! short -> long" %}
|
||||
opcode(Assembler::ldsh_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_encode %{
|
||||
__ ldsh($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
@ -5565,8 +5507,9 @@ instruct loadUS(iRegI dst, memory mem) %{
|
||||
|
||||
size(4);
|
||||
format %{ "LDUH $mem,$dst\t! ushort/char" %}
|
||||
opcode(Assembler::lduh_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_encode %{
|
||||
__ lduh($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
@ -5577,8 +5520,9 @@ instruct loadUS2L(iRegL dst, memory mem) %{
|
||||
|
||||
size(4);
|
||||
format %{ "LDUH $mem,$dst\t! ushort/char -> long" %}
|
||||
opcode(Assembler::lduh_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_encode %{
|
||||
__ lduh($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mask_mem);
|
||||
%}
|
||||
|
||||
@ -5589,8 +5533,9 @@ instruct loadI(iRegI dst, memory mem) %{
|
||||
|
||||
size(4);
|
||||
format %{ "LDUW $mem,$dst\t! int" %}
|
||||
opcode(Assembler::lduw_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_encode %{
|
||||
__ lduw($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
@ -5601,8 +5546,9 @@ instruct loadI2L(iRegL dst, memory mem) %{
|
||||
|
||||
size(4);
|
||||
format %{ "LDSW $mem,$dst\t! int -> long" %}
|
||||
opcode(Assembler::ldsw_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_encode %{
|
||||
__ ldsw($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
@ -5613,8 +5559,9 @@ instruct loadUI2L(iRegL dst, memory mem) %{
|
||||
|
||||
size(4);
|
||||
format %{ "LDUW $mem,$dst\t! uint -> long" %}
|
||||
opcode(Assembler::lduw_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_encode %{
|
||||
__ lduw($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
@ -5625,8 +5572,9 @@ instruct loadL(iRegL dst, memory mem ) %{
|
||||
|
||||
size(4);
|
||||
format %{ "LDX $mem,$dst\t! long" %}
|
||||
opcode(Assembler::ldx_op3);
|
||||
ins_encode(simple_form3_mem_reg( mem, dst ) );
|
||||
ins_encode %{
|
||||
__ ldx($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
@ -5721,31 +5669,29 @@ instruct loadP(iRegP dst, memory mem) %{
|
||||
|
||||
#ifndef _LP64
|
||||
format %{ "LDUW $mem,$dst\t! ptr" %}
|
||||
opcode(Assembler::lduw_op3, 0, REGP_OP);
|
||||
ins_encode %{
|
||||
__ lduw($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
#else
|
||||
format %{ "LDX $mem,$dst\t! ptr" %}
|
||||
opcode(Assembler::ldx_op3, 0, REGP_OP);
|
||||
ins_encode %{
|
||||
__ ldx($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
#endif
|
||||
ins_encode( form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
// Load Compressed Pointer
|
||||
instruct loadN(iRegN dst, memory mem) %{
|
||||
match(Set dst (LoadN mem));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
size(4);
|
||||
match(Set dst (LoadN mem));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
size(4);
|
||||
|
||||
format %{ "LDUW $mem,$dst\t! compressed ptr" %}
|
||||
ins_encode %{
|
||||
Register index = $mem$$index$$Register;
|
||||
if (index != G0) {
|
||||
__ lduw($mem$$base$$Register, index, $dst$$Register);
|
||||
} else {
|
||||
__ lduw($mem$$base$$Register, $mem$$disp, $dst$$Register);
|
||||
}
|
||||
%}
|
||||
ins_pipe(iload_mem);
|
||||
format %{ "LDUW $mem,$dst\t! compressed ptr" %}
|
||||
ins_encode %{
|
||||
__ lduw($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
// Load Klass Pointer
|
||||
@ -5756,12 +5702,15 @@ instruct loadKlass(iRegP dst, memory mem) %{
|
||||
|
||||
#ifndef _LP64
|
||||
format %{ "LDUW $mem,$dst\t! klass ptr" %}
|
||||
opcode(Assembler::lduw_op3, 0, REGP_OP);
|
||||
ins_encode %{
|
||||
__ lduw($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
#else
|
||||
format %{ "LDX $mem,$dst\t! klass ptr" %}
|
||||
opcode(Assembler::ldx_op3, 0, REGP_OP);
|
||||
ins_encode %{
|
||||
__ ldx($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
#endif
|
||||
ins_encode( form3_mem_reg( mem, dst ) );
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
|
||||
@ -5772,16 +5721,8 @@ instruct loadNKlass(iRegN dst, memory mem) %{
|
||||
size(4);
|
||||
|
||||
format %{ "LDUW $mem,$dst\t! compressed klass ptr" %}
|
||||
|
||||
ins_encode %{
|
||||
Register base = as_Register($mem$$base);
|
||||
Register index = as_Register($mem$$index);
|
||||
Register dst = $dst$$Register;
|
||||
if (index != G0) {
|
||||
__ lduw(base, index, dst);
|
||||
} else {
|
||||
__ lduw(base, $mem$$disp, dst);
|
||||
}
|
||||
__ lduw($mem$$Address, $dst$$Register);
|
||||
%}
|
||||
ins_pipe(iload_mem);
|
||||
%}
|
||||
@ -5867,8 +5808,8 @@ instruct loadConP_poll(iRegP dst, immP_poll src) %{
|
||||
ins_cost(DEFAULT_COST);
|
||||
format %{ "SET $src,$dst\t!ptr" %}
|
||||
ins_encode %{
|
||||
Address polling_page(reg_to_register_object($dst$$reg), (address)os::get_polling_page());
|
||||
__ sethi(polling_page, false );
|
||||
AddressLiteral polling_page(os::get_polling_page());
|
||||
__ sethi(polling_page, reg_to_register_object($dst$$reg));
|
||||
%}
|
||||
ins_pipe(loadConP_poll);
|
||||
%}
|
||||
@ -5927,14 +5868,21 @@ instruct loadConF(regF dst, immF src, o7RegP tmp) %{
|
||||
effect(KILL tmp);
|
||||
|
||||
#ifdef _LP64
|
||||
size(36);
|
||||
size(8*4);
|
||||
#else
|
||||
size(8);
|
||||
size(2*4);
|
||||
#endif
|
||||
|
||||
format %{ "SETHI hi(&$src),$tmp\t!get float $src from table\n\t"
|
||||
"LDF [$tmp+lo(&$src)],$dst" %}
|
||||
ins_encode( LdImmF(src, dst, tmp) );
|
||||
ins_encode %{
|
||||
address float_address = __ float_constant($src$$constant);
|
||||
RelocationHolder rspec = internal_word_Relocation::spec(float_address);
|
||||
AddressLiteral addrlit(float_address, rspec);
|
||||
|
||||
__ sethi(addrlit, $tmp$$Register);
|
||||
__ ldf(FloatRegisterImpl::S, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec);
|
||||
%}
|
||||
ins_pipe(loadConFD);
|
||||
%}
|
||||
|
||||
@ -5943,14 +5891,23 @@ instruct loadConD(regD dst, immD src, o7RegP tmp) %{
|
||||
effect(KILL tmp);
|
||||
|
||||
#ifdef _LP64
|
||||
size(36);
|
||||
size(8*4);
|
||||
#else
|
||||
size(8);
|
||||
size(2*4);
|
||||
#endif
|
||||
|
||||
format %{ "SETHI hi(&$src),$tmp\t!get double $src from table\n\t"
|
||||
"LDDF [$tmp+lo(&$src)],$dst" %}
|
||||
ins_encode( LdImmD(src, dst, tmp) );
|
||||
ins_encode %{
|
||||
address double_address = __ double_constant($src$$constant);
|
||||
RelocationHolder rspec = internal_word_Relocation::spec(double_address);
|
||||
AddressLiteral addrlit(double_address, rspec);
|
||||
|
||||
__ sethi(addrlit, $tmp$$Register);
|
||||
// XXX This is a quick fix for 6833573.
|
||||
//__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), $dst$$FloatRegister, rspec);
|
||||
__ ldf(FloatRegisterImpl::D, $tmp$$Register, addrlit.low10(), as_DoubleFloatRegister($dst$$reg), rspec);
|
||||
%}
|
||||
ins_pipe(loadConFD);
|
||||
%}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||
@ -68,16 +68,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||
#ifdef PRODUCT
|
||||
#define inc_counter_np(a,b,c) (0)
|
||||
#else
|
||||
void inc_counter_np_(int& counter, Register t1, Register t2) {
|
||||
Address counter_addr(t2, (address) &counter);
|
||||
__ sethi(counter_addr);
|
||||
__ ld(counter_addr, t1);
|
||||
__ inc(t1);
|
||||
__ st(t1, counter_addr);
|
||||
}
|
||||
#define inc_counter_np(counter, t1, t2) \
|
||||
BLOCK_COMMENT("inc_counter " #counter); \
|
||||
inc_counter_np_(counter, t1, t2);
|
||||
__ inc_counter(&counter, t1, t2);
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
@ -325,9 +318,9 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ verify_thread();
|
||||
|
||||
const Register& temp_reg = Gtemp;
|
||||
Address pending_exception_addr (G2_thread, 0, in_bytes(Thread::pending_exception_offset()));
|
||||
Address exception_file_offset_addr(G2_thread, 0, in_bytes(Thread::exception_file_offset ()));
|
||||
Address exception_line_offset_addr(G2_thread, 0, in_bytes(Thread::exception_line_offset ()));
|
||||
Address pending_exception_addr (G2_thread, Thread::pending_exception_offset());
|
||||
Address exception_file_offset_addr(G2_thread, Thread::exception_file_offset ());
|
||||
Address exception_line_offset_addr(G2_thread, Thread::exception_line_offset ());
|
||||
|
||||
// set pending exception
|
||||
__ verify_oop(Oexception);
|
||||
@ -340,8 +333,8 @@ class StubGenerator: public StubCodeGenerator {
|
||||
// complete return to VM
|
||||
assert(StubRoutines::_call_stub_return_address != NULL, "must have been generated before");
|
||||
|
||||
Address stub_ret(temp_reg, StubRoutines::_call_stub_return_address);
|
||||
__ jump_to(stub_ret);
|
||||
AddressLiteral stub_ret(StubRoutines::_call_stub_return_address);
|
||||
__ jump_to(stub_ret, temp_reg);
|
||||
__ delayed()->nop();
|
||||
|
||||
return start;
|
||||
@ -366,7 +359,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
const Register& handler_reg = Gtemp;
|
||||
|
||||
Address exception_addr (G2_thread, 0, in_bytes(Thread::pending_exception_offset()));
|
||||
Address exception_addr(G2_thread, Thread::pending_exception_offset());
|
||||
|
||||
#ifdef ASSERT
|
||||
// make sure that this code is only executed if there is a pending exception
|
||||
@ -456,8 +449,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
int frame_complete = __ offset();
|
||||
|
||||
if (restore_saved_exception_pc) {
|
||||
Address saved_exception_pc(G2_thread, 0, in_bytes(JavaThread::saved_exception_pc_offset()));
|
||||
__ ld_ptr(saved_exception_pc, I7);
|
||||
__ ld_ptr(G2_thread, JavaThread::saved_exception_pc_offset(), I7);
|
||||
__ sub(I7, frame::pc_return_offset, I7);
|
||||
}
|
||||
|
||||
@ -481,7 +473,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
#ifdef ASSERT
|
||||
Label L;
|
||||
|
||||
Address exception_addr(G2_thread, 0, in_bytes(Thread::pending_exception_offset()));
|
||||
Address exception_addr(G2_thread, Thread::pending_exception_offset());
|
||||
Register scratch_reg = Gtemp;
|
||||
__ ld_ptr(exception_addr, scratch_reg);
|
||||
__ br_notnull(scratch_reg, false, Assembler::pt, L);
|
||||
@ -835,7 +827,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
address start = __ pc();
|
||||
|
||||
const int preserve_register_words = (64 * 2);
|
||||
Address preserve_addr(FP, 0, (-preserve_register_words * wordSize) + STACK_BIAS);
|
||||
Address preserve_addr(FP, (-preserve_register_words * wordSize) + STACK_BIAS);
|
||||
|
||||
Register Lthread = L7_thread_cache;
|
||||
int i;
|
||||
@ -1106,21 +1098,19 @@ class StubGenerator: public StubCodeGenerator {
|
||||
__ srl_ptr(addr, CardTableModRefBS::card_shift, addr);
|
||||
__ srl_ptr(count, CardTableModRefBS::card_shift, count);
|
||||
__ sub(count, addr, count);
|
||||
Address rs(tmp, (address)ct->byte_map_base);
|
||||
__ load_address(rs);
|
||||
AddressLiteral rs(ct->byte_map_base);
|
||||
__ set(rs, tmp);
|
||||
__ BIND(L_loop);
|
||||
__ stb(G0, rs.base(), addr);
|
||||
__ stb(G0, tmp, addr);
|
||||
__ subcc(count, 1, count);
|
||||
__ brx(Assembler::greaterEqual, false, Assembler::pt, L_loop);
|
||||
__ delayed()->add(addr, 1, addr);
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BarrierSet::ModRef:
|
||||
break;
|
||||
default :
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,8 +87,8 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch
|
||||
}
|
||||
// throw exception
|
||||
assert(Interpreter::throw_exception_entry() != NULL, "generate it first");
|
||||
Address thrower(G3_scratch, Interpreter::throw_exception_entry());
|
||||
__ jump_to (thrower);
|
||||
AddressLiteral thrower(Interpreter::throw_exception_entry());
|
||||
__ jump_to(thrower, G3_scratch);
|
||||
__ delayed()->nop();
|
||||
return entry;
|
||||
}
|
||||
@ -150,7 +150,8 @@ address TemplateInterpreterGenerator::generate_StackOverflowError_handler() {
|
||||
}
|
||||
|
||||
|
||||
address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) {
|
||||
address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, bool unbox) {
|
||||
assert(!unbox, "NYI");//6815692//
|
||||
address compiled_entry = __ pc();
|
||||
Label cont;
|
||||
|
||||
@ -186,8 +187,8 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
|
||||
const Register cache = G3_scratch;
|
||||
const Register size = G1_scratch;
|
||||
__ get_cache_and_index_at_bcp(cache, G1_scratch, 1);
|
||||
__ ld_ptr(Address(cache, 0, in_bytes(constantPoolCacheOopDesc::base_offset()) +
|
||||
in_bytes(ConstantPoolCacheEntry::flags_offset())), size);
|
||||
__ ld_ptr(cache, constantPoolCacheOopDesc::base_offset() +
|
||||
ConstantPoolCacheEntry::flags_offset(), size);
|
||||
__ and3(size, 0xFF, size); // argument size in words
|
||||
__ sll(size, Interpreter::logStackElementSize(), size); // each argument size in bytes
|
||||
__ add(Lesp, size, Lesp); // pop arguments
|
||||
@ -201,9 +202,8 @@ address TemplateInterpreterGenerator::generate_deopt_entry_for(TosState state, i
|
||||
address entry = __ pc();
|
||||
__ get_constant_pool_cache(LcpoolCache); // load LcpoolCache
|
||||
{ Label L;
|
||||
Address exception_addr (G2_thread, 0, in_bytes(Thread::pending_exception_offset()));
|
||||
|
||||
__ ld_ptr(exception_addr, Gtemp);
|
||||
Address exception_addr(G2_thread, Thread::pending_exception_offset());
|
||||
__ ld_ptr(exception_addr, Gtemp); // Load pending exception.
|
||||
__ tst(Gtemp);
|
||||
__ brx(Assembler::equal, false, Assembler::pt, L);
|
||||
__ delayed()->nop();
|
||||
@ -282,7 +282,7 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
|
||||
// Update standard invocation counters
|
||||
__ increment_invocation_counter(O0, G3_scratch);
|
||||
if (ProfileInterpreter) { // %%% Merge this into methodDataOop
|
||||
Address interpreter_invocation_counter(Lmethod, 0, in_bytes(methodOopDesc::interpreter_invocation_counter_offset()));
|
||||
Address interpreter_invocation_counter(Lmethod, methodOopDesc::interpreter_invocation_counter_offset());
|
||||
__ ld(interpreter_invocation_counter, G3_scratch);
|
||||
__ inc(G3_scratch);
|
||||
__ st(G3_scratch, interpreter_invocation_counter);
|
||||
@ -290,9 +290,9 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
|
||||
|
||||
if (ProfileInterpreter && profile_method != NULL) {
|
||||
// Test to see if we should create a method data oop
|
||||
Address profile_limit(G3_scratch, (address)&InvocationCounter::InterpreterProfileLimit);
|
||||
__ sethi(profile_limit);
|
||||
__ ld(profile_limit, G3_scratch);
|
||||
AddressLiteral profile_limit(&InvocationCounter::InterpreterProfileLimit);
|
||||
__ sethi(profile_limit, G3_scratch);
|
||||
__ ld(G3_scratch, profile_limit.low10(), G3_scratch);
|
||||
__ cmp(O0, G3_scratch);
|
||||
__ br(Assembler::lessUnsigned, false, Assembler::pn, *profile_method_continue);
|
||||
__ delayed()->nop();
|
||||
@ -301,9 +301,9 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
|
||||
__ test_method_data_pointer(*profile_method);
|
||||
}
|
||||
|
||||
Address invocation_limit(G3_scratch, (address)&InvocationCounter::InterpreterInvocationLimit);
|
||||
__ sethi(invocation_limit);
|
||||
__ ld(invocation_limit, G3_scratch);
|
||||
AddressLiteral invocation_limit(&InvocationCounter::InterpreterInvocationLimit);
|
||||
__ sethi(invocation_limit, G3_scratch);
|
||||
__ ld(G3_scratch, invocation_limit.low10(), G3_scratch);
|
||||
__ cmp(O0, G3_scratch);
|
||||
__ br(Assembler::greaterEqualUnsigned, false, Assembler::pn, *overflow);
|
||||
__ delayed()->nop();
|
||||
@ -314,8 +314,7 @@ void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile
|
||||
// ebx - methodOop
|
||||
//
|
||||
void InterpreterGenerator::lock_method(void) {
|
||||
const Address access_flags (Lmethod, 0, in_bytes(methodOopDesc::access_flags_offset()));
|
||||
__ ld(access_flags, O0);
|
||||
__ ld(Lmethod, in_bytes(methodOopDesc::access_flags_offset()), O0); // Load access flags.
|
||||
|
||||
#ifdef ASSERT
|
||||
{ Label ok;
|
||||
@ -359,8 +358,7 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe
|
||||
Register Rscratch,
|
||||
Register Rscratch2) {
|
||||
const int page_size = os::vm_page_size();
|
||||
Address saved_exception_pc(G2_thread, 0,
|
||||
in_bytes(JavaThread::saved_exception_pc_offset()));
|
||||
Address saved_exception_pc(G2_thread, JavaThread::saved_exception_pc_offset());
|
||||
Label after_frame_check;
|
||||
|
||||
assert_different_registers(Rframe_size, Rscratch, Rscratch2);
|
||||
@ -372,7 +370,7 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe
|
||||
__ delayed()->nop();
|
||||
|
||||
// get the stack base, and in debug, verify it is non-zero
|
||||
__ ld_ptr( G2_thread, in_bytes(Thread::stack_base_offset()), Rscratch );
|
||||
__ ld_ptr( G2_thread, Thread::stack_base_offset(), Rscratch );
|
||||
#ifdef ASSERT
|
||||
Label base_not_zero;
|
||||
__ cmp( Rscratch, G0 );
|
||||
@ -384,7 +382,7 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe
|
||||
|
||||
// get the stack size, and in debug, verify it is non-zero
|
||||
assert( sizeof(size_t) == sizeof(intptr_t), "wrong load size" );
|
||||
__ ld_ptr( G2_thread, in_bytes(Thread::stack_size_offset()), Rscratch2 );
|
||||
__ ld_ptr( G2_thread, Thread::stack_size_offset(), Rscratch2 );
|
||||
#ifdef ASSERT
|
||||
Label size_not_zero;
|
||||
__ cmp( Rscratch2, G0 );
|
||||
@ -459,9 +457,9 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
// (gri - 2/25/2000)
|
||||
|
||||
|
||||
const Address size_of_parameters(G5_method, 0, in_bytes(methodOopDesc::size_of_parameters_offset()));
|
||||
const Address size_of_locals (G5_method, 0, in_bytes(methodOopDesc::size_of_locals_offset()));
|
||||
const Address max_stack (G5_method, 0, in_bytes(methodOopDesc::max_stack_offset()));
|
||||
const Address size_of_parameters(G5_method, methodOopDesc::size_of_parameters_offset());
|
||||
const Address size_of_locals (G5_method, methodOopDesc::size_of_locals_offset());
|
||||
const Address max_stack (G5_method, methodOopDesc::max_stack_offset());
|
||||
int rounded_vm_local_words = round_to( frame::interpreter_frame_vm_local_words, WordsPerLong );
|
||||
|
||||
const int extra_space =
|
||||
@ -538,8 +536,8 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
if (native_call) {
|
||||
__ mov(G0, Lbcp);
|
||||
} else {
|
||||
__ ld_ptr(Address(G5_method, 0, in_bytes(methodOopDesc::const_offset())), Lbcp );
|
||||
__ add(Address(Lbcp, 0, in_bytes(constMethodOopDesc::codes_offset())), Lbcp );
|
||||
__ ld_ptr(G5_method, methodOopDesc::const_offset(), Lbcp);
|
||||
__ add(Lbcp, in_bytes(constMethodOopDesc::codes_offset()), Lbcp);
|
||||
}
|
||||
__ mov( G5_method, Lmethod); // set Lmethod
|
||||
__ get_constant_pool_cache( LcpoolCache ); // set LcpoolCache
|
||||
@ -577,8 +575,8 @@ address InterpreterGenerator::generate_empty_entry(void) {
|
||||
// do nothing for empty methods (do not even increment invocation counter)
|
||||
if ( UseFastEmptyMethods) {
|
||||
// If we need a safepoint check, generate full interpreter entry.
|
||||
Address sync_state(G3_scratch, SafepointSynchronize::address_of_state());
|
||||
__ load_contents(sync_state, G3_scratch);
|
||||
AddressLiteral sync_state(SafepointSynchronize::address_of_state());
|
||||
__ set(sync_state, G3_scratch);
|
||||
__ cmp(G3_scratch, SafepointSynchronize::_not_synchronized);
|
||||
__ br(Assembler::notEqual, false, Assembler::pn, slow_path);
|
||||
__ delayed()->nop();
|
||||
@ -616,7 +614,7 @@ address InterpreterGenerator::generate_accessor_entry(void) {
|
||||
if ( UseFastAccessorMethods && !UseCompressedOops ) {
|
||||
// Check if we need to reach a safepoint and generate full interpreter
|
||||
// frame if so.
|
||||
Address sync_state(G3_scratch, SafepointSynchronize::address_of_state());
|
||||
AddressLiteral sync_state(SafepointSynchronize::address_of_state());
|
||||
__ load_contents(sync_state, G3_scratch);
|
||||
__ cmp(G3_scratch, SafepointSynchronize::_not_synchronized);
|
||||
__ br(Assembler::notEqual, false, Assembler::pn, slow_path);
|
||||
@ -631,8 +629,8 @@ address InterpreterGenerator::generate_accessor_entry(void) {
|
||||
|
||||
// read first instruction word and extract bytecode @ 1 and index @ 2
|
||||
// get first 4 bytes of the bytecodes (big endian!)
|
||||
__ ld_ptr(Address(G5_method, 0, in_bytes(methodOopDesc::const_offset())), G1_scratch);
|
||||
__ ld(Address(G1_scratch, 0, in_bytes(constMethodOopDesc::codes_offset())), G1_scratch);
|
||||
__ ld_ptr(G5_method, methodOopDesc::const_offset(), G1_scratch);
|
||||
__ ld(G1_scratch, constMethodOopDesc::codes_offset(), G1_scratch);
|
||||
|
||||
// move index @ 2 far left then to the right most two bytes.
|
||||
__ sll(G1_scratch, 2*BitsPerByte, G1_scratch);
|
||||
@ -640,7 +638,7 @@ address InterpreterGenerator::generate_accessor_entry(void) {
|
||||
ConstantPoolCacheEntry::size()) * BytesPerWord), G1_scratch);
|
||||
|
||||
// get constant pool cache
|
||||
__ ld_ptr(G5_method, in_bytes(methodOopDesc::constants_offset()), G3_scratch);
|
||||
__ ld_ptr(G5_method, methodOopDesc::constants_offset(), G3_scratch);
|
||||
__ ld_ptr(G3_scratch, constantPoolOopDesc::cache_offset_in_bytes(), G3_scratch);
|
||||
|
||||
// get specific constant pool cache entry
|
||||
@ -649,7 +647,7 @@ address InterpreterGenerator::generate_accessor_entry(void) {
|
||||
// Check the constant Pool cache entry to see if it has been resolved.
|
||||
// If not, need the slow path.
|
||||
ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset();
|
||||
__ ld_ptr(G3_scratch, in_bytes(cp_base_offset + ConstantPoolCacheEntry::indices_offset()), G1_scratch);
|
||||
__ ld_ptr(G3_scratch, cp_base_offset + ConstantPoolCacheEntry::indices_offset(), G1_scratch);
|
||||
__ srl(G1_scratch, 2*BitsPerByte, G1_scratch);
|
||||
__ and3(G1_scratch, 0xFF, G1_scratch);
|
||||
__ cmp(G1_scratch, Bytecodes::_getfield);
|
||||
@ -657,8 +655,8 @@ address InterpreterGenerator::generate_accessor_entry(void) {
|
||||
__ delayed()->nop();
|
||||
|
||||
// Get the type and return field offset from the constant pool cache
|
||||
__ ld_ptr(G3_scratch, in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset()), G1_scratch);
|
||||
__ ld_ptr(G3_scratch, in_bytes(cp_base_offset + ConstantPoolCacheEntry::f2_offset()), G3_scratch);
|
||||
__ ld_ptr(G3_scratch, cp_base_offset + ConstantPoolCacheEntry::flags_offset(), G1_scratch);
|
||||
__ ld_ptr(G3_scratch, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), G3_scratch);
|
||||
|
||||
Label xreturn_path;
|
||||
// Need to differentiate between igetfield, agetfield, bgetfield etc.
|
||||
@ -717,7 +715,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
// make sure registers are different!
|
||||
assert_different_registers(G2_thread, G5_method, Gargs, Gtmp1, Gtmp2);
|
||||
|
||||
const Address Laccess_flags (Lmethod, 0, in_bytes(methodOopDesc::access_flags_offset()));
|
||||
const Address Laccess_flags(Lmethod, methodOopDesc::access_flags_offset());
|
||||
|
||||
__ verify_oop(G5_method);
|
||||
|
||||
@ -727,7 +725,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
// make sure method is native & not abstract
|
||||
// rethink these assertions - they can be simplified and shared (gri 2/25/2000)
|
||||
#ifdef ASSERT
|
||||
__ ld(G5_method, in_bytes(methodOopDesc::access_flags_offset()), Gtmp1);
|
||||
__ ld(G5_method, methodOopDesc::access_flags_offset(), Gtmp1);
|
||||
{
|
||||
Label L;
|
||||
__ btst(JVM_ACC_NATIVE, Gtmp1);
|
||||
@ -754,10 +752,10 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
|
||||
// this slot will be set later, we initialize it to null here just in
|
||||
// case we get a GC before the actual value is stored later
|
||||
__ st_ptr(G0, Address(FP, 0, (frame::interpreter_frame_oop_temp_offset*wordSize) + STACK_BIAS));
|
||||
__ st_ptr(G0, FP, (frame::interpreter_frame_oop_temp_offset * wordSize) + STACK_BIAS);
|
||||
|
||||
const Address do_not_unlock_if_synchronized(G2_thread, 0,
|
||||
in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()));
|
||||
const Address do_not_unlock_if_synchronized(G2_thread,
|
||||
JavaThread::do_not_unlock_if_synchronized_offset());
|
||||
// Since at this point in the method invocation the exception handler
|
||||
// would try to exit the monitor of synchronized methods which hasn't
|
||||
// been entered yet, we set the thread local variable
|
||||
@ -824,12 +822,13 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
|
||||
// get signature handler
|
||||
{ Label L;
|
||||
__ ld_ptr(Address(Lmethod, 0, in_bytes(methodOopDesc::signature_handler_offset())), G3_scratch);
|
||||
Address signature_handler(Lmethod, methodOopDesc::signature_handler_offset());
|
||||
__ ld_ptr(signature_handler, G3_scratch);
|
||||
__ tst(G3_scratch);
|
||||
__ brx(Assembler::notZero, false, Assembler::pt, L);
|
||||
__ delayed()->nop();
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::prepare_native_call), Lmethod);
|
||||
__ ld_ptr(Address(Lmethod, 0, in_bytes(methodOopDesc::signature_handler_offset())), G3_scratch);
|
||||
__ ld_ptr(signature_handler, G3_scratch);
|
||||
__ bind(L);
|
||||
}
|
||||
|
||||
@ -842,10 +841,9 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
// Flush the method pointer to the register save area
|
||||
__ st_ptr(Lmethod, SP, (Lmethod->sp_offset_in_saved_window() * wordSize) + STACK_BIAS);
|
||||
__ mov(Llocals, O1);
|
||||
// calculate where the mirror handle body is allocated in the interpreter frame:
|
||||
|
||||
Address mirror(FP, 0, (frame::interpreter_frame_oop_temp_offset*wordSize) + STACK_BIAS);
|
||||
__ add(mirror, O2);
|
||||
// calculate where the mirror handle body is allocated in the interpreter frame:
|
||||
__ add(FP, (frame::interpreter_frame_oop_temp_offset * wordSize) + STACK_BIAS, O2);
|
||||
|
||||
// Calculate current frame size
|
||||
__ sub(SP, FP, O3); // Calculate negative of current frame size
|
||||
@ -882,14 +880,13 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
__ ld(Laccess_flags, O0);
|
||||
__ btst(JVM_ACC_STATIC, O0);
|
||||
__ br( Assembler::zero, false, Assembler::pt, not_static);
|
||||
__ delayed()->
|
||||
// get native function entry point(O0 is a good temp until the very end)
|
||||
ld_ptr(Address(Lmethod, 0, in_bytes(methodOopDesc::native_function_offset())), O0);
|
||||
// get native function entry point(O0 is a good temp until the very end)
|
||||
__ delayed()->ld_ptr(Lmethod, in_bytes(methodOopDesc::native_function_offset()), O0);
|
||||
// for static methods insert the mirror argument
|
||||
const int mirror_offset = klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes();
|
||||
|
||||
__ ld_ptr(Address(Lmethod, 0, in_bytes(methodOopDesc:: constants_offset())), O1);
|
||||
__ ld_ptr(Address(O1, 0, constantPoolOopDesc::pool_holder_offset_in_bytes()), O1);
|
||||
__ ld_ptr(Lmethod, methodOopDesc:: constants_offset(), O1);
|
||||
__ ld_ptr(O1, constantPoolOopDesc::pool_holder_offset_in_bytes(), O1);
|
||||
__ ld_ptr(O1, mirror_offset, O1);
|
||||
#ifdef ASSERT
|
||||
if (!PrintSignatureHandlers) // do not dirty the output with this
|
||||
@ -944,15 +941,13 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
__ flush_windows();
|
||||
|
||||
// mark windows as flushed
|
||||
Address flags(G2_thread,
|
||||
0,
|
||||
in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::flags_offset()));
|
||||
Address flags(G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::flags_offset());
|
||||
__ set(JavaFrameAnchor::flushed, G3_scratch);
|
||||
__ st(G3_scratch, flags);
|
||||
|
||||
// Transition from _thread_in_Java to _thread_in_native. We are already safepoint ready.
|
||||
|
||||
Address thread_state(G2_thread, 0, in_bytes(JavaThread::thread_state_offset()));
|
||||
Address thread_state(G2_thread, JavaThread::thread_state_offset());
|
||||
#ifdef ASSERT
|
||||
{ Label L;
|
||||
__ ld(thread_state, G3_scratch);
|
||||
@ -982,7 +977,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
// Block, if necessary, before resuming in _thread_in_Java state.
|
||||
// In order for GC to work, don't clear the last_Java_sp until after blocking.
|
||||
{ Label no_block;
|
||||
Address sync_state(G3_scratch, SafepointSynchronize::address_of_state());
|
||||
AddressLiteral sync_state(SafepointSynchronize::address_of_state());
|
||||
|
||||
// Switch thread to "native transition" state before reading the synchronization state.
|
||||
// This additional state is necessary because reading and testing the synchronization
|
||||
@ -1009,10 +1004,8 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
__ cmp(G3_scratch, SafepointSynchronize::_not_synchronized);
|
||||
|
||||
Label L;
|
||||
Address suspend_state(G2_thread, 0, in_bytes(JavaThread::suspend_flags_offset()));
|
||||
__ br(Assembler::notEqual, false, Assembler::pn, L);
|
||||
__ delayed()->
|
||||
ld(suspend_state, G3_scratch);
|
||||
__ delayed()->ld(G2_thread, JavaThread::suspend_flags_offset(), G3_scratch);
|
||||
__ cmp(G3_scratch, 0);
|
||||
__ br(Assembler::equal, false, Assembler::pt, no_block);
|
||||
__ delayed()->nop();
|
||||
@ -1054,7 +1047,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
__ st(G3_scratch, thread_state);
|
||||
|
||||
// reset handle block
|
||||
__ ld_ptr(G2_thread, in_bytes(JavaThread::active_handles_offset()), G3_scratch);
|
||||
__ ld_ptr(G2_thread, JavaThread::active_handles_offset(), G3_scratch);
|
||||
__ st_ptr(G0, G3_scratch, JNIHandleBlock::top_offset_in_bytes());
|
||||
|
||||
// If we have an oop result store it where it will be safe for any further gc
|
||||
@ -1083,8 +1076,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
|
||||
|
||||
// handle exceptions (exception handling will handle unlocking!)
|
||||
{ Label L;
|
||||
Address exception_addr (G2_thread, 0, in_bytes(Thread::pending_exception_offset()));
|
||||
|
||||
Address exception_addr(G2_thread, Thread::pending_exception_offset());
|
||||
__ ld_ptr(exception_addr, Gtemp);
|
||||
__ tst(Gtemp);
|
||||
__ brx(Assembler::equal, false, Assembler::pt, L);
|
||||
@ -1170,11 +1162,11 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
// make sure registers are different!
|
||||
assert_different_registers(G2_thread, G5_method, Gargs, Gtmp1, Gtmp2);
|
||||
|
||||
const Address size_of_parameters(G5_method, 0, in_bytes(methodOopDesc::size_of_parameters_offset()));
|
||||
const Address size_of_locals (G5_method, 0, in_bytes(methodOopDesc::size_of_locals_offset()));
|
||||
const Address size_of_parameters(G5_method, methodOopDesc::size_of_parameters_offset());
|
||||
const Address size_of_locals (G5_method, methodOopDesc::size_of_locals_offset());
|
||||
// Seems like G5_method is live at the point this is used. So we could make this look consistent
|
||||
// and use in the asserts.
|
||||
const Address access_flags (Lmethod, 0, in_bytes(methodOopDesc::access_flags_offset()));
|
||||
const Address access_flags (Lmethod, methodOopDesc::access_flags_offset());
|
||||
|
||||
__ verify_oop(G5_method);
|
||||
|
||||
@ -1184,7 +1176,7 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
// make sure method is not native & not abstract
|
||||
// rethink these assertions - they can be simplified and shared (gri 2/25/2000)
|
||||
#ifdef ASSERT
|
||||
__ ld(G5_method, in_bytes(methodOopDesc::access_flags_offset()), Gtmp1);
|
||||
__ ld(G5_method, methodOopDesc::access_flags_offset(), Gtmp1);
|
||||
{
|
||||
Label L;
|
||||
__ btst(JVM_ACC_NATIVE, Gtmp1);
|
||||
@ -1239,8 +1231,8 @@ address InterpreterGenerator::generate_normal_entry(bool synchronized) {
|
||||
__ brx( Assembler::lessEqualUnsigned, true, Assembler::pt, clear_loop );
|
||||
__ delayed()->st_ptr( init_value, O2, 0 );
|
||||
|
||||
const Address do_not_unlock_if_synchronized(G2_thread, 0,
|
||||
in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()));
|
||||
const Address do_not_unlock_if_synchronized(G2_thread,
|
||||
JavaThread::do_not_unlock_if_synchronized_offset());
|
||||
// Since at this point in the method invocation the exception handler
|
||||
// would try to exit the monitor of synchronized methods which hasn't
|
||||
// been entered yet, we set the thread local variable
|
||||
@ -1716,7 +1708,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
|
||||
//
|
||||
|
||||
Interpreter::_remove_activation_preserving_args_entry = __ pc();
|
||||
Address popframe_condition_addr (G2_thread, 0, in_bytes(JavaThread::popframe_condition_offset()));
|
||||
Address popframe_condition_addr(G2_thread, JavaThread::popframe_condition_offset());
|
||||
// Set the popframe_processing bit in popframe_condition indicating that we are
|
||||
// currently handling popframe, so that call_VMs that may happen later do not trigger new
|
||||
// popframe handling cycles.
|
||||
@ -1758,7 +1750,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
|
||||
__ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::popframe_preserve_args), G2_thread, Gtmp1, Gtmp2);
|
||||
// Inform deoptimization that it is responsible for restoring these arguments
|
||||
__ set(JavaThread::popframe_force_deopt_reexecution_bit, Gtmp1);
|
||||
Address popframe_condition_addr(G2_thread, 0, in_bytes(JavaThread::popframe_condition_offset()));
|
||||
Address popframe_condition_addr(G2_thread, JavaThread::popframe_condition_offset());
|
||||
__ st(Gtmp1, popframe_condition_addr);
|
||||
|
||||
// Return from the current method
|
||||
@ -1807,7 +1799,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
|
||||
__ verify_oop(Oexception);
|
||||
|
||||
const int return_reg_adjustment = frame::pc_return_offset;
|
||||
Address issuing_pc_addr(I7, 0, return_reg_adjustment);
|
||||
Address issuing_pc_addr(I7, return_reg_adjustment);
|
||||
|
||||
// We are done with this activation frame; find out where to go next.
|
||||
// The continuation point will be an exception handler, which expects
|
||||
@ -1853,8 +1845,8 @@ address TemplateInterpreterGenerator::generate_earlyret_entry_for(TosState state
|
||||
__ empty_expression_stack();
|
||||
__ load_earlyret_value(state);
|
||||
|
||||
__ ld_ptr(Address(G2_thread, 0, in_bytes(JavaThread::jvmti_thread_state_offset())), G3_scratch);
|
||||
Address cond_addr(G3_scratch, 0, in_bytes(JvmtiThreadState::earlyret_state_offset()));
|
||||
__ ld_ptr(G2_thread, JavaThread::jvmti_thread_state_offset(), G3_scratch);
|
||||
Address cond_addr(G3_scratch, JvmtiThreadState::earlyret_state_offset());
|
||||
|
||||
// Clear the earlyret state
|
||||
__ stw(G0 /* JvmtiThreadState::earlyret_inactive */, cond_addr);
|
||||
@ -1921,43 +1913,33 @@ address TemplateInterpreterGenerator::generate_trace_code(TosState state) {
|
||||
// helpers for generate_and_dispatch
|
||||
|
||||
void TemplateInterpreterGenerator::count_bytecode() {
|
||||
Address c(G3_scratch, (address)&BytecodeCounter::_counter_value);
|
||||
__ load_contents(c, G4_scratch);
|
||||
__ inc(G4_scratch);
|
||||
__ st(G4_scratch, c);
|
||||
__ inc_counter(&BytecodeCounter::_counter_value, G3_scratch, G4_scratch);
|
||||
}
|
||||
|
||||
|
||||
void TemplateInterpreterGenerator::histogram_bytecode(Template* t) {
|
||||
Address bucket( G3_scratch, (address) &BytecodeHistogram::_counters[t->bytecode()] );
|
||||
__ load_contents(bucket, G4_scratch);
|
||||
__ inc(G4_scratch);
|
||||
__ st(G4_scratch, bucket);
|
||||
__ inc_counter(&BytecodeHistogram::_counters[t->bytecode()], G3_scratch, G4_scratch);
|
||||
}
|
||||
|
||||
|
||||
void TemplateInterpreterGenerator::histogram_bytecode_pair(Template* t) {
|
||||
address index_addr = (address)&BytecodePairHistogram::_index;
|
||||
Address index(G3_scratch, index_addr);
|
||||
|
||||
address counters_addr = (address)&BytecodePairHistogram::_counters;
|
||||
Address counters(G3_scratch, counters_addr);
|
||||
AddressLiteral index (&BytecodePairHistogram::_index);
|
||||
AddressLiteral counters((address) &BytecodePairHistogram::_counters);
|
||||
|
||||
// get index, shift out old bytecode, bring in new bytecode, and store it
|
||||
// _index = (_index >> log2_number_of_codes) |
|
||||
// (bytecode << log2_number_of_codes);
|
||||
|
||||
|
||||
__ load_contents( index, G4_scratch );
|
||||
__ load_contents(index, G4_scratch);
|
||||
__ srl( G4_scratch, BytecodePairHistogram::log2_number_of_codes, G4_scratch );
|
||||
__ set( ((int)t->bytecode()) << BytecodePairHistogram::log2_number_of_codes, G3_scratch );
|
||||
__ or3( G3_scratch, G4_scratch, G4_scratch );
|
||||
__ store_contents( G4_scratch, index );
|
||||
__ store_contents(G4_scratch, index, G3_scratch);
|
||||
|
||||
// bump bucket contents
|
||||
// _counters[_index] ++;
|
||||
|
||||
__ load_address( counters ); // loads into G3_scratch
|
||||
__ set(counters, G3_scratch); // loads into G3_scratch
|
||||
__ sll( G4_scratch, LogBytesPerWord, G4_scratch ); // Index is word address
|
||||
__ add (G3_scratch, G4_scratch, G3_scratch); // Add in index
|
||||
__ ld (G3_scratch, 0, G4_scratch);
|
||||
@ -1978,9 +1960,9 @@ void TemplateInterpreterGenerator::trace_bytecode(Template* t) {
|
||||
|
||||
|
||||
void TemplateInterpreterGenerator::stop_interpreter_at() {
|
||||
Address counter(G3_scratch , (address)&BytecodeCounter::_counter_value);
|
||||
__ load_contents (counter, G3_scratch );
|
||||
Address stop_at(G4_scratch, (address)&StopInterpreterAt);
|
||||
AddressLiteral counter(&BytecodeCounter::_counter_value);
|
||||
__ load_contents(counter, G3_scratch);
|
||||
AddressLiteral stop_at(&StopInterpreterAt);
|
||||
__ load_ptr_contents(stop_at, G4_scratch);
|
||||
__ cmp(G3_scratch, G4_scratch);
|
||||
__ breakpoint_trap(Assembler::equal);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||
@ -131,7 +131,7 @@ Assembler::Condition ccNot(TemplateTable::Condition cc) {
|
||||
|
||||
Address TemplateTable::at_bcp(int offset) {
|
||||
assert(_desc->uses_bcp(), "inconsistent uses_bcp information");
|
||||
return Address( Lbcp, 0, offset);
|
||||
return Address(Lbcp, offset);
|
||||
}
|
||||
|
||||
|
||||
@ -217,9 +217,9 @@ void TemplateTable::fconst(int value) {
|
||||
case 1: p = &one; break;
|
||||
case 2: p = &two; break;
|
||||
}
|
||||
Address a(G3_scratch, (address)p);
|
||||
__ sethi(a);
|
||||
__ ldf(FloatRegisterImpl::S, a, Ftos_f);
|
||||
AddressLiteral a(p);
|
||||
__ sethi(a, G3_scratch);
|
||||
__ ldf(FloatRegisterImpl::S, G3_scratch, a.low10(), Ftos_f);
|
||||
}
|
||||
|
||||
|
||||
@ -232,9 +232,9 @@ void TemplateTable::dconst(int value) {
|
||||
case 0: p = &zero; break;
|
||||
case 1: p = &one; break;
|
||||
}
|
||||
Address a(G3_scratch, (address)p);
|
||||
__ sethi(a);
|
||||
__ ldf(FloatRegisterImpl::D, a, Ftos_d);
|
||||
AddressLiteral a(p);
|
||||
__ sethi(a, G3_scratch);
|
||||
__ ldf(FloatRegisterImpl::D, G3_scratch, a.low10(), Ftos_d);
|
||||
}
|
||||
|
||||
|
||||
@ -1548,7 +1548,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) {
|
||||
// non-JSR normal-branch stuff occurring below.
|
||||
if( is_jsr ) {
|
||||
// compute return address as bci in Otos_i
|
||||
__ ld_ptr(Address(Lmethod, 0, in_bytes(methodOopDesc::const_offset())), G3_scratch);
|
||||
__ ld_ptr(Lmethod, methodOopDesc::const_offset(), G3_scratch);
|
||||
__ sub(Lbcp, G3_scratch, G3_scratch);
|
||||
__ sub(G3_scratch, in_bytes(constMethodOopDesc::codes_offset()) - (is_wide ? 5 : 3), Otos_i);
|
||||
|
||||
@ -1665,7 +1665,7 @@ void TemplateTable::ret() {
|
||||
|
||||
__ profile_ret(vtos, Otos_i, G4_scratch);
|
||||
|
||||
__ ld_ptr(Address(Lmethod, 0, in_bytes(methodOopDesc::const_offset())), G3_scratch);
|
||||
__ ld_ptr(Lmethod, methodOopDesc::const_offset(), G3_scratch);
|
||||
__ add(G3_scratch, Otos_i, G3_scratch);
|
||||
__ add(G3_scratch, in_bytes(constMethodOopDesc::codes_offset()), Lbcp);
|
||||
__ dispatch_next(vtos);
|
||||
@ -1680,7 +1680,7 @@ void TemplateTable::wide_ret() {
|
||||
|
||||
__ profile_ret(vtos, Otos_i, G4_scratch);
|
||||
|
||||
__ ld_ptr(Address(Lmethod, 0, in_bytes(methodOopDesc::const_offset())), G3_scratch);
|
||||
__ ld_ptr(Lmethod, methodOopDesc::const_offset(), G3_scratch);
|
||||
__ add(G3_scratch, Otos_i, G3_scratch);
|
||||
__ add(G3_scratch, in_bytes(constMethodOopDesc::codes_offset()), Lbcp);
|
||||
__ dispatch_next(vtos);
|
||||
@ -1968,8 +1968,8 @@ void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Regist
|
||||
Label resolved;
|
||||
|
||||
__ get_cache_and_index_at_bcp(Rcache, index, 1);
|
||||
__ ld_ptr(Address(Rcache, 0, in_bytes(constantPoolCacheOopDesc::base_offset() +
|
||||
ConstantPoolCacheEntry::indices_offset())), Lbyte_code);
|
||||
__ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() +
|
||||
ConstantPoolCacheEntry::indices_offset(), Lbyte_code);
|
||||
|
||||
__ srl( Lbyte_code, shift_count, Lbyte_code );
|
||||
__ and3( Lbyte_code, 0xFF, Lbyte_code );
|
||||
@ -2029,11 +2029,11 @@ void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
|
||||
resolve_cache_and_index(byte_no, Rcache, Rscratch);
|
||||
}
|
||||
|
||||
__ ld_ptr(Address(Rcache, 0, method_offset), Rmethod);
|
||||
__ ld_ptr(Rcache, method_offset, Rmethod);
|
||||
if (Ritable_index != noreg) {
|
||||
__ ld_ptr(Address(Rcache, 0, index_offset), Ritable_index);
|
||||
__ ld_ptr(Rcache, index_offset, Ritable_index);
|
||||
}
|
||||
__ ld_ptr(Address(Rcache, 0, flags_offset), Rflags);
|
||||
__ ld_ptr(Rcache, flags_offset, Rflags);
|
||||
}
|
||||
|
||||
// The Rcache register must be set before call
|
||||
@ -2047,13 +2047,10 @@ void TemplateTable::load_field_cp_cache_entry(Register Robj,
|
||||
|
||||
ByteSize cp_base_offset = constantPoolCacheOopDesc::base_offset();
|
||||
|
||||
__ ld_ptr(Address(Rcache, 0, in_bytes(cp_base_offset +
|
||||
ConstantPoolCacheEntry::flags_offset())), Rflags);
|
||||
__ ld_ptr(Address(Rcache, 0, in_bytes(cp_base_offset +
|
||||
ConstantPoolCacheEntry::f2_offset())), Roffset);
|
||||
__ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::flags_offset(), Rflags);
|
||||
__ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), Roffset);
|
||||
if (is_static) {
|
||||
__ ld_ptr(Address(Rcache, 0, in_bytes(cp_base_offset +
|
||||
ConstantPoolCacheEntry::f1_offset())), Robj);
|
||||
__ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::f1_offset(), Robj);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2070,9 +2067,7 @@ void TemplateTable::jvmti_post_field_access(Register Rcache,
|
||||
// the time to call into the VM.
|
||||
Label Label1;
|
||||
assert_different_registers(Rcache, index, G1_scratch);
|
||||
Address get_field_access_count_addr(G1_scratch,
|
||||
(address)JvmtiExport::get_field_access_count_addr(),
|
||||
relocInfo::none);
|
||||
AddressLiteral get_field_access_count_addr(JvmtiExport::get_field_access_count_addr());
|
||||
__ load_contents(get_field_access_count_addr, G1_scratch);
|
||||
__ tst(G1_scratch);
|
||||
__ br(Assembler::zero, false, Assembler::pt, Label1);
|
||||
@ -2293,7 +2288,7 @@ void TemplateTable::fast_accessfield(TosState state) {
|
||||
__ get_cache_and_index_at_bcp(Rcache, index, 1);
|
||||
jvmti_post_field_access(Rcache, index, /*is_static*/false, /*has_tos*/true);
|
||||
|
||||
__ ld_ptr(Address(Rcache, 0, in_bytes(cp_base_offset + ConstantPoolCacheEntry::f2_offset())), Roffset);
|
||||
__ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), Roffset);
|
||||
|
||||
__ null_check(Otos_i);
|
||||
__ verify_oop(Otos_i);
|
||||
@ -2304,7 +2299,7 @@ void TemplateTable::fast_accessfield(TosState state) {
|
||||
Assembler::Membar_mask_bits(Assembler::LoadLoad | Assembler::LoadStore);
|
||||
if (__ membar_has_effect(membar_bits)) {
|
||||
// Get volatile flag
|
||||
__ ld_ptr(Address(Rcache, 0, in_bytes(cp_base_offset + ConstantPoolCacheEntry::f2_offset())), Rflags);
|
||||
__ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), Rflags);
|
||||
__ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch);
|
||||
}
|
||||
|
||||
@ -2355,7 +2350,7 @@ void TemplateTable::jvmti_post_fast_field_mod() {
|
||||
// Check to see if a field modification watch has been set before we take
|
||||
// the time to call into the VM.
|
||||
Label done;
|
||||
Address get_field_modification_count_addr(G4_scratch, (address)JvmtiExport::get_field_modification_count_addr(), relocInfo::none);
|
||||
AddressLiteral get_field_modification_count_addr(JvmtiExport::get_field_modification_count_addr());
|
||||
__ load_contents(get_field_modification_count_addr, G4_scratch);
|
||||
__ tst(G4_scratch);
|
||||
__ br(Assembler::zero, false, Assembler::pt, done);
|
||||
@ -2408,9 +2403,7 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register index, bool i
|
||||
// the time to call into the VM.
|
||||
Label Label1;
|
||||
assert_different_registers(Rcache, index, G1_scratch);
|
||||
Address get_field_modification_count_addr(G1_scratch,
|
||||
(address)JvmtiExport::get_field_modification_count_addr(),
|
||||
relocInfo::none);
|
||||
AddressLiteral get_field_modification_count_addr(JvmtiExport::get_field_modification_count_addr());
|
||||
__ load_contents(get_field_modification_count_addr, G1_scratch);
|
||||
__ tst(G1_scratch);
|
||||
__ br(Assembler::zero, false, Assembler::pt, Label1);
|
||||
@ -2433,7 +2426,7 @@ void TemplateTable::jvmti_post_field_mod(Register Rcache, Register index, bool i
|
||||
// the type to determine where the object is.
|
||||
|
||||
Label two_word, valsizeknown;
|
||||
__ ld_ptr(Address(G1_scratch, 0, in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset())), Rflags);
|
||||
__ ld_ptr(G1_scratch, cp_base_offset + ConstantPoolCacheEntry::flags_offset(), Rflags);
|
||||
__ mov(Lesp, G4_scratch);
|
||||
__ srl(Rflags, ConstantPoolCacheEntry::tosBits, Rflags);
|
||||
// Make sure we don't need to mask Rflags for tosBits after the above shift
|
||||
@ -2689,8 +2682,7 @@ void TemplateTable::fast_storefield(TosState state) {
|
||||
|
||||
Label notVolatile, checkVolatile, exit;
|
||||
if (__ membar_has_effect(read_bits) || __ membar_has_effect(write_bits)) {
|
||||
__ ld_ptr(Address(Rcache, 0, in_bytes(cp_base_offset +
|
||||
ConstantPoolCacheEntry::flags_offset())), Rflags);
|
||||
__ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::flags_offset(), Rflags);
|
||||
__ set((1 << ConstantPoolCacheEntry::volatileField), Lscratch);
|
||||
__ and3(Rflags, Lscratch, Lscratch);
|
||||
if (__ membar_has_effect(read_bits)) {
|
||||
@ -2702,8 +2694,7 @@ void TemplateTable::fast_storefield(TosState state) {
|
||||
}
|
||||
}
|
||||
|
||||
__ ld_ptr(Address(Rcache, 0, in_bytes(cp_base_offset +
|
||||
ConstantPoolCacheEntry::f2_offset())), Roffset);
|
||||
__ ld_ptr(Rcache, cp_base_offset + ConstantPoolCacheEntry::f2_offset(), Roffset);
|
||||
pop_and_check_object(Rclass);
|
||||
|
||||
switch (bytecode()) {
|
||||
@ -2755,7 +2746,7 @@ void TemplateTable::fast_xaccess(TosState state) {
|
||||
|
||||
// access constant pool cache (is resolved)
|
||||
__ get_cache_and_index_at_bcp(Rcache, G4_scratch, 2);
|
||||
__ ld_ptr(Address(Rcache, 0, in_bytes(constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f2_offset())), Roffset);
|
||||
__ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f2_offset(), Roffset);
|
||||
__ add(Lbcp, 1, Lbcp); // needed to report exception at the correct bcp
|
||||
|
||||
__ verify_oop(Rreceiver);
|
||||
@ -2775,7 +2766,7 @@ void TemplateTable::fast_xaccess(TosState state) {
|
||||
if (__ membar_has_effect(membar_bits)) {
|
||||
|
||||
// Get is_volatile value in Rflags and check if membar is needed
|
||||
__ ld_ptr(Address(Rcache, 0, in_bytes(constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::flags_offset())), Rflags);
|
||||
__ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::flags_offset(), Rflags);
|
||||
|
||||
// Test volatile
|
||||
Label notVolatile;
|
||||
@ -2853,8 +2844,8 @@ void TemplateTable::invokevirtual(int byte_no) {
|
||||
__ verify_oop(O0);
|
||||
|
||||
// get return address
|
||||
Address table(Rtemp, (address)Interpreter::return_3_addrs_by_index_table());
|
||||
__ load_address(table);
|
||||
AddressLiteral table(Interpreter::return_3_addrs_by_index_table());
|
||||
__ set(table, Rtemp);
|
||||
__ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret); // get return type
|
||||
// Make sure we don't need to mask Rret for tosBits after the above shift
|
||||
ConstantPoolCacheEntry::verify_tosBits();
|
||||
@ -2886,7 +2877,7 @@ void TemplateTable::invokevfinal_helper(Register Rscratch, Register Rret) {
|
||||
__ verify_oop(G5_method);
|
||||
|
||||
// Load receiver from stack slot
|
||||
__ lduh(Address(G5_method, 0, in_bytes(methodOopDesc::size_of_parameters_offset())), G4_scratch);
|
||||
__ lduh(G5_method, in_bytes(methodOopDesc::size_of_parameters_offset()), G4_scratch);
|
||||
__ load_receiver(G4_scratch, O0);
|
||||
|
||||
// receiver NULL check
|
||||
@ -2895,8 +2886,8 @@ void TemplateTable::invokevfinal_helper(Register Rscratch, Register Rret) {
|
||||
__ profile_final_call(O4);
|
||||
|
||||
// get return address
|
||||
Address table(Rtemp, (address)Interpreter::return_3_addrs_by_index_table());
|
||||
__ load_address(table);
|
||||
AddressLiteral table(Interpreter::return_3_addrs_by_index_table());
|
||||
__ set(table, Rtemp);
|
||||
__ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret); // get return type
|
||||
// Make sure we don't need to mask Rret for tosBits after the above shift
|
||||
ConstantPoolCacheEntry::verify_tosBits();
|
||||
@ -2920,7 +2911,7 @@ void TemplateTable::invokespecial(int byte_no) {
|
||||
|
||||
__ verify_oop(G5_method);
|
||||
|
||||
__ lduh(Address(G5_method, 0, in_bytes(methodOopDesc::size_of_parameters_offset())), G4_scratch);
|
||||
__ lduh(G5_method, in_bytes(methodOopDesc::size_of_parameters_offset()), G4_scratch);
|
||||
__ load_receiver(G4_scratch, O0);
|
||||
|
||||
// receiver NULL check
|
||||
@ -2929,8 +2920,8 @@ void TemplateTable::invokespecial(int byte_no) {
|
||||
__ profile_call(O4);
|
||||
|
||||
// get return address
|
||||
Address table(Rtemp, (address)Interpreter::return_3_addrs_by_index_table());
|
||||
__ load_address(table);
|
||||
AddressLiteral table(Interpreter::return_3_addrs_by_index_table());
|
||||
__ set(table, Rtemp);
|
||||
__ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret); // get return type
|
||||
// Make sure we don't need to mask Rret for tosBits after the above shift
|
||||
ConstantPoolCacheEntry::verify_tosBits();
|
||||
@ -2956,8 +2947,8 @@ void TemplateTable::invokestatic(int byte_no) {
|
||||
__ profile_call(O4);
|
||||
|
||||
// get return address
|
||||
Address table(Rtemp, (address)Interpreter::return_3_addrs_by_index_table());
|
||||
__ load_address(table);
|
||||
AddressLiteral table(Interpreter::return_3_addrs_by_index_table());
|
||||
__ set(table, Rtemp);
|
||||
__ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret); // get return type
|
||||
// Make sure we don't need to mask Rret for tosBits after the above shift
|
||||
ConstantPoolCacheEntry::verify_tosBits();
|
||||
@ -3021,8 +3012,8 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
__ mov(Rflags, Rret);
|
||||
|
||||
// get return address
|
||||
Address table(Rscratch, (address)Interpreter::return_5_addrs_by_index_table());
|
||||
__ load_address(table);
|
||||
AddressLiteral table(Interpreter::return_5_addrs_by_index_table());
|
||||
__ set(table, Rscratch);
|
||||
__ srl(Rret, ConstantPoolCacheEntry::tosBits, Rret); // get return type
|
||||
// Make sure we don't need to mask Rret for tosBits after the above shift
|
||||
ConstantPoolCacheEntry::verify_tosBits();
|
||||
@ -3059,7 +3050,7 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
Label search;
|
||||
Register Rtemp = Rflags;
|
||||
|
||||
__ ld(Address(RklassOop, 0, instanceKlass::vtable_length_offset() * wordSize), Rtemp);
|
||||
__ ld(RklassOop, instanceKlass::vtable_length_offset() * wordSize, Rtemp);
|
||||
if (align_object_offset(1) > 1) {
|
||||
__ round_to(Rtemp, align_object_offset(1));
|
||||
}
|
||||
@ -3125,6 +3116,24 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
}
|
||||
|
||||
|
||||
void TemplateTable::invokedynamic(int byte_no) {
|
||||
transition(vtos, vtos);
|
||||
|
||||
if (!EnableInvokeDynamic) {
|
||||
// We should not encounter this bytecode if !EnableInvokeDynamic.
|
||||
// The verifier will stop it. However, if we get past the verifier,
|
||||
// this will stop the thread in a reasonable way, without crashing the JVM.
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address,
|
||||
InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||
// the call_VM checks for exception, so we should never return here.
|
||||
__ should_not_reach_here();
|
||||
return;
|
||||
}
|
||||
|
||||
__ stop("invokedynamic NYI");//6815692//
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// Allocation
|
||||
|
||||
@ -3624,9 +3633,9 @@ void TemplateTable::wide() {
|
||||
transition(vtos, vtos);
|
||||
__ ldub(Lbcp, 1, G3_scratch);// get next bc
|
||||
__ sll(G3_scratch, LogBytesPerWord, G3_scratch);
|
||||
Address ep(G4_scratch, (address)Interpreter::_wentry_point);
|
||||
__ load_address(ep);
|
||||
__ ld_ptr(ep.base(), G3_scratch, G3_scratch);
|
||||
AddressLiteral ep(Interpreter::_wentry_point);
|
||||
__ set(ep, G4_scratch);
|
||||
__ ld_ptr(G4_scratch, G3_scratch, G3_scratch);
|
||||
__ jmp(G3_scratch, G0);
|
||||
__ delayed()->nop();
|
||||
// Note: the Lbcp increment step is part of the individual wide bytecode implementations
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Copyright 1997-2009 Sun Microsystems, Inc. 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
|
||||
@ -48,11 +48,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (CountCompiledCalls) {
|
||||
Address ctr(G5, SharedRuntime::nof_megamorphic_calls_addr());
|
||||
__ sethi(ctr);
|
||||
__ ld(ctr, G3_scratch);
|
||||
__ inc(G3_scratch);
|
||||
__ st(G3_scratch, ctr);
|
||||
__ inc_counter(SharedRuntime::nof_megamorphic_calls_addr(), G5, G3_scratch);
|
||||
}
|
||||
#endif /* PRODUCT */
|
||||
|
||||
@ -154,11 +150,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (CountCompiledCalls) {
|
||||
Address ctr(L0, SharedRuntime::nof_megamorphic_calls_addr());
|
||||
__ sethi(ctr);
|
||||
__ ld(ctr, L1);
|
||||
__ inc(L1);
|
||||
__ st(L1, ctr);
|
||||
__ inc_counter(SharedRuntime::nof_megamorphic_calls_addr(), L0, L1);
|
||||
}
|
||||
#endif /* PRODUCT */
|
||||
|
||||
@ -198,8 +190,8 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
|
||||
__ delayed()->nop();
|
||||
|
||||
__ bind(throw_icce);
|
||||
Address icce(G3_scratch, StubRoutines::throw_IncompatibleClassChangeError_entry());
|
||||
__ jump_to(icce, 0);
|
||||
AddressLiteral icce(StubRoutines::throw_IncompatibleClassChangeError_entry());
|
||||
__ jump_to(icce, G3_scratch);
|
||||
__ delayed()->restore();
|
||||
|
||||
masm->flush();
|
||||
|
@ -189,20 +189,33 @@ void InterpreterMacroAssembler::get_unsigned_2_byte_index_at_bcp(Register reg, i
|
||||
}
|
||||
|
||||
|
||||
void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset) {
|
||||
void InterpreterMacroAssembler::get_cache_index_at_bcp(Register reg, int bcp_offset, bool giant_index) {
|
||||
assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
|
||||
if (!giant_index) {
|
||||
load_unsigned_short(reg, Address(rsi, bcp_offset));
|
||||
} else {
|
||||
assert(EnableInvokeDynamic, "giant index used only for EnableInvokeDynamic");
|
||||
movl(reg, Address(rsi, bcp_offset));
|
||||
assert(constantPoolCacheOopDesc::decode_secondary_index(~123) == 123, "else change next line");
|
||||
notl(reg); // convert to plain index
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index,
|
||||
int bcp_offset, bool giant_index) {
|
||||
assert(cache != index, "must use different registers");
|
||||
load_unsigned_short(index, Address(rsi, bcp_offset));
|
||||
get_cache_index_at_bcp(index, bcp_offset, giant_index);
|
||||
movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
|
||||
assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
|
||||
shlptr(index, 2); // convert from field index to ConstantPoolCacheEntry index
|
||||
}
|
||||
|
||||
|
||||
void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset) {
|
||||
assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
|
||||
void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
|
||||
int bcp_offset, bool giant_index) {
|
||||
assert(cache != tmp, "must use different register");
|
||||
load_unsigned_short(tmp, Address(rsi, bcp_offset));
|
||||
get_cache_index_at_bcp(tmp, bcp_offset, giant_index);
|
||||
assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
|
||||
// convert from field index to ConstantPoolCacheEntry index
|
||||
// and from word offset to byte offset
|
||||
@ -1214,7 +1227,9 @@ void InterpreterMacroAssembler::profile_final_call(Register mdp) {
|
||||
}
|
||||
|
||||
|
||||
void InterpreterMacroAssembler::profile_virtual_call(Register receiver, Register mdp, Register reg2) {
|
||||
void InterpreterMacroAssembler::profile_virtual_call(Register receiver, Register mdp,
|
||||
Register reg2,
|
||||
bool receiver_can_be_null) {
|
||||
if (ProfileInterpreter) {
|
||||
Label profile_continue;
|
||||
|
||||
@ -1224,8 +1239,15 @@ void InterpreterMacroAssembler::profile_virtual_call(Register receiver, Register
|
||||
// We are making a call. Increment the count.
|
||||
increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset()));
|
||||
|
||||
Label skip_receiver_profile;
|
||||
if (receiver_can_be_null) {
|
||||
testptr(receiver, receiver);
|
||||
jcc(Assembler::zero, skip_receiver_profile);
|
||||
}
|
||||
|
||||
// Record the receiver type.
|
||||
record_klass_in_profile(receiver, mdp, reg2);
|
||||
bind(skip_receiver_profile);
|
||||
|
||||
// The method data pointer needs to be updated to reflect the new target.
|
||||
update_mdp_by_constant(mdp,
|
||||
|
@ -76,8 +76,9 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||
void get_cpool_and_tags(Register cpool, Register tags) { get_constant_pool(cpool); movptr(tags, Address(cpool, constantPoolOopDesc::tags_offset_in_bytes()));
|
||||
}
|
||||
void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
|
||||
void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset);
|
||||
void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset);
|
||||
void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, bool giant_index = false);
|
||||
void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, bool giant_index = false);
|
||||
void get_cache_index_at_bcp(Register index, int bcp_offset, bool giant_index = false);
|
||||
|
||||
// Expression stack
|
||||
void f2ieee(); // truncate ftos to 32bits
|
||||
@ -226,7 +227,8 @@ class InterpreterMacroAssembler: public MacroAssembler {
|
||||
void profile_not_taken_branch(Register mdp);
|
||||
void profile_call(Register mdp);
|
||||
void profile_final_call(Register mdp);
|
||||
void profile_virtual_call(Register receiver, Register mdp, Register scratch2);
|
||||
void profile_virtual_call(Register receiver, Register mdp, Register scratch2,
|
||||
bool receiver_can_be_null = false);
|
||||
void profile_ret(Register return_bci, Register mdp);
|
||||
void profile_null_seen(Register mdp);
|
||||
void profile_typecheck(Register mdp, Register klass, Register scratch);
|
||||
|
@ -156,13 +156,22 @@ address TemplateInterpreterGenerator::generate_continuation_for(TosState state)
|
||||
}
|
||||
|
||||
|
||||
address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step) {
|
||||
address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, bool unbox) {
|
||||
TosState incoming_state = state;
|
||||
if (EnableInvokeDynamic) {
|
||||
if (unbox) {
|
||||
incoming_state = atos;
|
||||
}
|
||||
} else {
|
||||
assert(!unbox, "old behavior");
|
||||
}
|
||||
|
||||
Label interpreter_entry;
|
||||
address compiled_entry = __ pc();
|
||||
|
||||
#ifdef COMPILER2
|
||||
// The FPU stack is clean if UseSSE >= 2 but must be cleaned in other cases
|
||||
if ((state == ftos && UseSSE < 1) || (state == dtos && UseSSE < 2)) {
|
||||
if ((incoming_state == ftos && UseSSE < 1) || (incoming_state == dtos && UseSSE < 2)) {
|
||||
for (int i = 1; i < 8; i++) {
|
||||
__ ffree(i);
|
||||
}
|
||||
@ -170,7 +179,7 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
|
||||
__ empty_FPU_stack();
|
||||
}
|
||||
#endif
|
||||
if ((state == ftos && UseSSE < 1) || (state == dtos && UseSSE < 2)) {
|
||||
if ((incoming_state == ftos && UseSSE < 1) || (incoming_state == dtos && UseSSE < 2)) {
|
||||
__ MacroAssembler::verify_FPU(1, "generate_return_entry_for compiled");
|
||||
} else {
|
||||
__ MacroAssembler::verify_FPU(0, "generate_return_entry_for compiled");
|
||||
@ -186,12 +195,12 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
|
||||
|
||||
// In SSE mode, interpreter returns FP results in xmm0 but they need
|
||||
// to end up back on the FPU so it can operate on them.
|
||||
if (state == ftos && UseSSE >= 1) {
|
||||
if (incoming_state == ftos && UseSSE >= 1) {
|
||||
__ subptr(rsp, wordSize);
|
||||
__ movflt(Address(rsp, 0), xmm0);
|
||||
__ fld_s(Address(rsp, 0));
|
||||
__ addptr(rsp, wordSize);
|
||||
} else if (state == dtos && UseSSE >= 2) {
|
||||
} else if (incoming_state == dtos && UseSSE >= 2) {
|
||||
__ subptr(rsp, 2*wordSize);
|
||||
__ movdbl(Address(rsp, 0), xmm0);
|
||||
__ fld_d(Address(rsp, 0));
|
||||
@ -207,13 +216,102 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
|
||||
|
||||
__ restore_bcp();
|
||||
__ restore_locals();
|
||||
__ get_cache_and_index_at_bcp(rbx, rcx, 1);
|
||||
|
||||
Label L_fail;
|
||||
|
||||
if (unbox && state != atos) {
|
||||
// cast and unbox
|
||||
BasicType type = as_BasicType(state);
|
||||
if (type == T_BYTE) type = T_BOOLEAN; // FIXME
|
||||
KlassHandle boxk = SystemDictionaryHandles::box_klass(type);
|
||||
__ mov32(rbx, ExternalAddress((address) boxk.raw_value()));
|
||||
__ testl(rax, rax);
|
||||
Label L_got_value, L_get_value;
|
||||
// convert nulls to zeroes (avoid NPEs here)
|
||||
if (!(type == T_FLOAT || type == T_DOUBLE)) {
|
||||
// if rax already contains zero bits, forge ahead
|
||||
__ jcc(Assembler::zero, L_got_value);
|
||||
} else {
|
||||
__ jcc(Assembler::notZero, L_get_value);
|
||||
__ fldz();
|
||||
__ jmp(L_got_value);
|
||||
}
|
||||
__ bind(L_get_value);
|
||||
__ cmp32(rbx, Address(rax, oopDesc::klass_offset_in_bytes()));
|
||||
__ jcc(Assembler::notEqual, L_fail);
|
||||
int offset = java_lang_boxing_object::value_offset_in_bytes(type);
|
||||
// Cf. TemplateTable::getfield_or_static
|
||||
switch (type) {
|
||||
case T_BYTE: // fall through:
|
||||
case T_BOOLEAN: __ load_signed_byte(rax, Address(rax, offset)); break;
|
||||
case T_CHAR: __ load_unsigned_short(rax, Address(rax, offset)); break;
|
||||
case T_SHORT: __ load_signed_short(rax, Address(rax, offset)); break;
|
||||
case T_INT: __ movl(rax, Address(rax, offset)); break;
|
||||
case T_FLOAT: __ fld_s(Address(rax, offset)); break;
|
||||
case T_DOUBLE: __ fld_d(Address(rax, offset)); break;
|
||||
// Access to java.lang.Double.value does not need to be atomic:
|
||||
case T_LONG: { __ movl(rdx, Address(rax, offset + 4));
|
||||
__ movl(rax, Address(rax, offset + 0)); } break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
__ bind(L_got_value);
|
||||
}
|
||||
|
||||
Label L_got_cache, L_giant_index;
|
||||
if (EnableInvokeDynamic) {
|
||||
__ cmpb(Address(rsi, 0), Bytecodes::_invokedynamic);
|
||||
__ jcc(Assembler::equal, L_giant_index);
|
||||
}
|
||||
__ get_cache_and_index_at_bcp(rbx, rcx, 1, false);
|
||||
__ bind(L_got_cache);
|
||||
if (unbox && state == atos) {
|
||||
// insert a casting conversion, to keep verifier sane
|
||||
Label L_ok, L_ok_pops;
|
||||
__ testl(rax, rax);
|
||||
__ jcc(Assembler::zero, L_ok);
|
||||
__ push(rax); // save the object to check
|
||||
__ push(rbx); // save CP cache reference
|
||||
__ movl(rdx, Address(rax, oopDesc::klass_offset_in_bytes()));
|
||||
__ movl(rbx, Address(rbx, rcx,
|
||||
Address::times_4, constantPoolCacheOopDesc::base_offset() +
|
||||
ConstantPoolCacheEntry::f1_offset()));
|
||||
__ movl(rbx, Address(rbx, __ delayed_value(sun_dyn_CallSiteImpl::type_offset_in_bytes, rcx)));
|
||||
__ movl(rbx, Address(rbx, __ delayed_value(java_dyn_MethodType::rtype_offset_in_bytes, rcx)));
|
||||
__ movl(rax, Address(rbx, __ delayed_value(java_lang_Class::klass_offset_in_bytes, rcx)));
|
||||
__ check_klass_subtype(rdx, rax, rbx, L_ok_pops);
|
||||
__ pop(rcx); // pop and discard CP cache
|
||||
__ mov(rbx, rax); // target supertype into rbx for L_fail
|
||||
__ pop(rax); // failed object into rax for L_fail
|
||||
__ jmp(L_fail);
|
||||
|
||||
__ bind(L_ok_pops);
|
||||
// restore pushed temp regs:
|
||||
__ pop(rbx);
|
||||
__ pop(rax);
|
||||
__ bind(L_ok);
|
||||
}
|
||||
__ movl(rbx, Address(rbx, rcx,
|
||||
Address::times_ptr, constantPoolCacheOopDesc::base_offset() +
|
||||
ConstantPoolCacheEntry::flags_offset()));
|
||||
__ andptr(rbx, 0xFF);
|
||||
__ lea(rsp, Address(rsp, rbx, Interpreter::stackElementScale()));
|
||||
__ dispatch_next(state, step);
|
||||
|
||||
// out of the main line of code...
|
||||
if (EnableInvokeDynamic) {
|
||||
__ bind(L_giant_index);
|
||||
__ get_cache_and_index_at_bcp(rbx, rcx, 1, true);
|
||||
__ jmp(L_got_cache);
|
||||
|
||||
if (unbox) {
|
||||
__ bind(L_fail);
|
||||
__ push(rbx); // missed klass (required)
|
||||
__ push(rax); // bad object (actual)
|
||||
__ movptr(rdx, ExternalAddress((address) &Interpreter::_throw_WrongMethodType_entry));
|
||||
__ call(rdx);
|
||||
}
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,8 @@ address TemplateInterpreterGenerator::generate_continuation_for(TosState state)
|
||||
|
||||
|
||||
address TemplateInterpreterGenerator::generate_return_entry_for(TosState state,
|
||||
int step) {
|
||||
int step, bool unbox) {
|
||||
assert(!unbox, "NYI");//6815692//
|
||||
|
||||
// amd64 doesn't need to do anything special about compiled returns
|
||||
// to the interpreter so the code that exists on x86 to place a sentinel
|
||||
|
@ -206,12 +206,12 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bytecode, Register bc,
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), scratch, rsi, bc);
|
||||
#ifndef ASSERT
|
||||
__ jmpb(patch_done);
|
||||
__ bind(fast_patch);
|
||||
}
|
||||
#else
|
||||
__ jmp(patch_done);
|
||||
#endif
|
||||
__ bind(fast_patch);
|
||||
}
|
||||
#ifdef ASSERT
|
||||
Label okay;
|
||||
__ load_unsigned_byte(scratch, at_bcp(0));
|
||||
__ cmpl(scratch, (int)Bytecodes::java_code(bytecode));
|
||||
@ -2105,6 +2105,7 @@ void TemplateTable::volatile_barrier(Assembler::Membar_mask_bits order_constrain
|
||||
|
||||
void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Register index) {
|
||||
assert(byte_no == 1 || byte_no == 2, "byte_no out of range");
|
||||
bool is_invokedynamic = (bytecode() == Bytecodes::_invokedynamic);
|
||||
|
||||
Register temp = rbx;
|
||||
|
||||
@ -2112,16 +2113,19 @@ void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Regist
|
||||
|
||||
const int shift_count = (1 + byte_no)*BitsPerByte;
|
||||
Label resolved;
|
||||
__ get_cache_and_index_at_bcp(Rcache, index, 1);
|
||||
__ movl(temp, Address(Rcache,
|
||||
index,
|
||||
Address::times_ptr,
|
||||
constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
|
||||
__ shrl(temp, shift_count);
|
||||
// have we resolved this bytecode?
|
||||
__ andptr(temp, 0xFF);
|
||||
__ cmpl(temp, (int)bytecode());
|
||||
__ jcc(Assembler::equal, resolved);
|
||||
__ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
|
||||
if (is_invokedynamic) {
|
||||
// we are resolved if the f1 field contains a non-null CallSite object
|
||||
__ cmpptr(Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()), (int32_t) NULL_WORD);
|
||||
__ jcc(Assembler::notEqual, resolved);
|
||||
} else {
|
||||
__ movl(temp, Address(Rcache, index, Address::times_4, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
|
||||
__ shrl(temp, shift_count);
|
||||
// have we resolved this bytecode?
|
||||
__ andl(temp, 0xFF);
|
||||
__ cmpl(temp, (int)bytecode());
|
||||
__ jcc(Assembler::equal, resolved);
|
||||
}
|
||||
|
||||
// resolve first time through
|
||||
address entry;
|
||||
@ -2134,12 +2138,13 @@ void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Regist
|
||||
case Bytecodes::_invokespecial : // fall through
|
||||
case Bytecodes::_invokestatic : // fall through
|
||||
case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke); break;
|
||||
case Bytecodes::_invokedynamic : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic); break;
|
||||
default : ShouldNotReachHere(); break;
|
||||
}
|
||||
__ movl(temp, (int)bytecode());
|
||||
__ call_VM(noreg, entry, temp);
|
||||
// Update registers with resolved info
|
||||
__ get_cache_and_index_at_bcp(Rcache, index, 1);
|
||||
__ get_cache_and_index_at_bcp(Rcache, index, 1, is_invokedynamic);
|
||||
__ bind(resolved);
|
||||
}
|
||||
|
||||
@ -2884,12 +2889,17 @@ void TemplateTable::count_calls(Register method, Register temp) {
|
||||
}
|
||||
|
||||
|
||||
void TemplateTable::prepare_invoke(Register method, Register index, int byte_no, Bytecodes::Code code) {
|
||||
void TemplateTable::prepare_invoke(Register method, Register index, int byte_no) {
|
||||
bool is_invdyn_bootstrap = (byte_no < 0);
|
||||
if (is_invdyn_bootstrap) byte_no = -byte_no;
|
||||
|
||||
// determine flags
|
||||
Bytecodes::Code code = bytecode();
|
||||
const bool is_invokeinterface = code == Bytecodes::_invokeinterface;
|
||||
const bool is_invokedynamic = code == Bytecodes::_invokedynamic;
|
||||
const bool is_invokevirtual = code == Bytecodes::_invokevirtual;
|
||||
const bool is_invokespecial = code == Bytecodes::_invokespecial;
|
||||
const bool load_receiver = code != Bytecodes::_invokestatic;
|
||||
const bool load_receiver = (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic);
|
||||
const bool receiver_null_check = is_invokespecial;
|
||||
const bool save_flags = is_invokeinterface || is_invokevirtual;
|
||||
// setup registers & access constant pool cache
|
||||
@ -2897,6 +2907,8 @@ void TemplateTable::prepare_invoke(Register method, Register index, int byte_no,
|
||||
const Register flags = rdx;
|
||||
assert_different_registers(method, index, recv, flags);
|
||||
|
||||
assert(!is_invdyn_bootstrap || is_invokedynamic, "byte_no<0 hack only for invdyn");
|
||||
|
||||
// save 'interpreter return address'
|
||||
__ save_bcp();
|
||||
|
||||
@ -2907,8 +2919,13 @@ void TemplateTable::prepare_invoke(Register method, Register index, int byte_no,
|
||||
__ movl(recv, flags);
|
||||
__ andl(recv, 0xFF);
|
||||
// recv count is 0 based?
|
||||
__ movptr(recv, Address(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1)));
|
||||
__ verify_oop(recv);
|
||||
Address recv_addr(rsp, recv, Interpreter::stackElementScale(), -Interpreter::expr_offset_in_bytes(1));
|
||||
if (is_invokedynamic) {
|
||||
__ lea(recv, recv_addr);
|
||||
} else {
|
||||
__ movptr(recv, recv_addr);
|
||||
__ verify_oop(recv);
|
||||
}
|
||||
}
|
||||
|
||||
// do null check if needed
|
||||
@ -2926,8 +2943,14 @@ void TemplateTable::prepare_invoke(Register method, Register index, int byte_no,
|
||||
ConstantPoolCacheEntry::verify_tosBits();
|
||||
// load return address
|
||||
{
|
||||
ExternalAddress table(is_invokeinterface ? (address)Interpreter::return_5_addrs_by_index_table() :
|
||||
(address)Interpreter::return_3_addrs_by_index_table());
|
||||
address table_addr;
|
||||
if (is_invdyn_bootstrap)
|
||||
table_addr = (address)Interpreter::return_5_unbox_addrs_by_index_table();
|
||||
else if (is_invokeinterface || is_invokedynamic)
|
||||
table_addr = (address)Interpreter::return_5_addrs_by_index_table();
|
||||
else
|
||||
table_addr = (address)Interpreter::return_3_addrs_by_index_table();
|
||||
ExternalAddress table(table_addr);
|
||||
__ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr)));
|
||||
}
|
||||
|
||||
@ -2990,7 +3013,7 @@ void TemplateTable::invokevirtual_helper(Register index, Register recv,
|
||||
|
||||
void TemplateTable::invokevirtual(int byte_no) {
|
||||
transition(vtos, vtos);
|
||||
prepare_invoke(rbx, noreg, byte_no, bytecode());
|
||||
prepare_invoke(rbx, noreg, byte_no);
|
||||
|
||||
// rbx,: index
|
||||
// rcx: receiver
|
||||
@ -3002,7 +3025,7 @@ void TemplateTable::invokevirtual(int byte_no) {
|
||||
|
||||
void TemplateTable::invokespecial(int byte_no) {
|
||||
transition(vtos, vtos);
|
||||
prepare_invoke(rbx, noreg, byte_no, bytecode());
|
||||
prepare_invoke(rbx, noreg, byte_no);
|
||||
// do the call
|
||||
__ verify_oop(rbx);
|
||||
__ profile_call(rax);
|
||||
@ -3012,7 +3035,7 @@ void TemplateTable::invokespecial(int byte_no) {
|
||||
|
||||
void TemplateTable::invokestatic(int byte_no) {
|
||||
transition(vtos, vtos);
|
||||
prepare_invoke(rbx, noreg, byte_no, bytecode());
|
||||
prepare_invoke(rbx, noreg, byte_no);
|
||||
// do the call
|
||||
__ verify_oop(rbx);
|
||||
__ profile_call(rax);
|
||||
@ -3028,7 +3051,7 @@ void TemplateTable::fast_invokevfinal(int byte_no) {
|
||||
|
||||
void TemplateTable::invokeinterface(int byte_no) {
|
||||
transition(vtos, vtos);
|
||||
prepare_invoke(rax, rbx, byte_no, bytecode());
|
||||
prepare_invoke(rax, rbx, byte_no);
|
||||
|
||||
// rax,: Interface
|
||||
// rbx,: index
|
||||
@ -3102,6 +3125,84 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
__ should_not_reach_here();
|
||||
}
|
||||
|
||||
void TemplateTable::invokedynamic(int byte_no) {
|
||||
transition(vtos, vtos);
|
||||
|
||||
if (!EnableInvokeDynamic) {
|
||||
// We should not encounter this bytecode if !EnableInvokeDynamic.
|
||||
// The verifier will stop it. However, if we get past the verifier,
|
||||
// this will stop the thread in a reasonable way, without crashing the JVM.
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address,
|
||||
InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||
// the call_VM checks for exception, so we should never return here.
|
||||
__ should_not_reach_here();
|
||||
return;
|
||||
}
|
||||
|
||||
prepare_invoke(rax, rbx, byte_no);
|
||||
|
||||
// rax: CallSite object (f1)
|
||||
// rbx: unused (f2)
|
||||
// rcx: receiver address
|
||||
// rdx: flags (unused)
|
||||
|
||||
if (ProfileInterpreter) {
|
||||
Label L;
|
||||
// %%% should make a type profile for any invokedynamic that takes a ref argument
|
||||
// profile this call
|
||||
__ profile_call(rsi);
|
||||
}
|
||||
|
||||
Label handle_unlinked_site;
|
||||
__ movptr(rcx, Address(rax, __ delayed_value(sun_dyn_CallSiteImpl::target_offset_in_bytes, rcx)));
|
||||
__ testptr(rcx, rcx);
|
||||
__ jcc(Assembler::zero, handle_unlinked_site);
|
||||
|
||||
__ prepare_to_jump_from_interpreted();
|
||||
__ jump_to_method_handle_entry(rcx, rdx);
|
||||
|
||||
// Initial calls come here...
|
||||
__ bind(handle_unlinked_site);
|
||||
__ pop(rcx); // remove return address pushed by prepare_invoke
|
||||
|
||||
// box stacked arguments into an array for the bootstrap method
|
||||
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::bootstrap_invokedynamic);
|
||||
__ restore_bcp(); // rsi must be correct for call_VM
|
||||
__ call_VM(rax, entry, rax);
|
||||
__ movl(rdi, rax); // protect bootstrap MH from prepare_invoke
|
||||
|
||||
// recompute return address
|
||||
__ restore_bcp(); // rsi must be correct for prepare_invoke
|
||||
prepare_invoke(rax, rbx, -byte_no); // smashes rcx, rdx
|
||||
// rax: CallSite object (f1)
|
||||
// rbx: unused (f2)
|
||||
// rdi: bootstrap MH
|
||||
// rdx: flags
|
||||
|
||||
// now load up the arglist, which has been neatly boxed
|
||||
__ get_thread(rcx);
|
||||
__ movptr(rdx, Address(rcx, JavaThread::vm_result_2_offset()));
|
||||
__ movptr(Address(rcx, JavaThread::vm_result_2_offset()), NULL_WORD);
|
||||
__ verify_oop(rdx);
|
||||
// rdx = arglist
|
||||
|
||||
// save SP now, before we add the bootstrap call to the stack
|
||||
// We must preserve a fiction that the original arguments are outgoing,
|
||||
// because the return sequence will reset the stack to this point
|
||||
// and then pop all those arguments. It seems error-prone to use
|
||||
// a different argument list size just for bootstrapping.
|
||||
__ prepare_to_jump_from_interpreted();
|
||||
|
||||
// Now let's play adapter, pushing the real arguments on the stack.
|
||||
__ pop(rbx); // return PC
|
||||
__ push(rdi); // boot MH
|
||||
__ push(rax); // call site
|
||||
__ push(rdx); // arglist
|
||||
__ push(rbx); // return PC, again
|
||||
__ mov(rcx, rdi);
|
||||
__ jump_to_method_handle_entry(rcx, rdx);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// Allocation
|
||||
|
||||
|
@ -22,8 +22,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
static void prepare_invoke(Register method, Register index, int byte_no,
|
||||
Bytecodes::Code code);
|
||||
static void prepare_invoke(Register method, Register index, int byte_no);
|
||||
static void invokevirtual_helper(Register index, Register recv,
|
||||
Register flags);
|
||||
static void volatile_barrier(Assembler::Membar_mask_bits order_constraint );
|
||||
|
@ -3058,6 +3058,23 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||
return;
|
||||
}
|
||||
|
||||
void TemplateTable::invokedynamic(int byte_no) {
|
||||
transition(vtos, vtos);
|
||||
|
||||
if (!EnableInvokeDynamic) {
|
||||
// We should not encounter this bytecode if !EnableInvokeDynamic.
|
||||
// The verifier will stop it. However, if we get past the verifier,
|
||||
// this will stop the thread in a reasonable way, without crashing the JVM.
|
||||
__ call_VM(noreg, CAST_FROM_FN_PTR(address,
|
||||
InterpreterRuntime::throw_IncompatibleClassChangeError));
|
||||
// the call_VM checks for exception, so we should never return here.
|
||||
__ should_not_reach_here();
|
||||
return;
|
||||
}
|
||||
|
||||
__ stop("invokedynamic NYI");//6815692//
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Allocation
|
||||
|
@ -2632,6 +2632,8 @@ bool os::can_execute_large_page_memory() {
|
||||
|
||||
char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) {
|
||||
|
||||
const DWORD prot = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
|
||||
|
||||
if (UseLargePagesIndividualAllocation) {
|
||||
if (TracePageSizes && Verbose) {
|
||||
tty->print_cr("Reserving large pages individually.");
|
||||
@ -2694,13 +2696,7 @@ char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) {
|
||||
p_new = (char *) VirtualAlloc(next_alloc_addr,
|
||||
bytes_to_rq,
|
||||
MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES,
|
||||
PAGE_READWRITE);
|
||||
if (p_new != NULL && exec) {
|
||||
DWORD oldprot;
|
||||
// Windows doc says to use VirtualProtect to get execute permissions
|
||||
VirtualProtect(next_alloc_addr, bytes_to_rq,
|
||||
PAGE_EXECUTE_READWRITE, &oldprot);
|
||||
}
|
||||
prot);
|
||||
}
|
||||
|
||||
if (p_new == NULL) {
|
||||
@ -2729,12 +2725,7 @@ char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) {
|
||||
} else {
|
||||
// normal policy just allocate it all at once
|
||||
DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
|
||||
char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_READWRITE);
|
||||
if (res != NULL && exec) {
|
||||
DWORD oldprot;
|
||||
// Windows doc says to use VirtualProtect to get execute permissions
|
||||
VirtualProtect(res, bytes, PAGE_EXECUTE_READWRITE, &oldprot);
|
||||
}
|
||||
char * res = (char *)VirtualAlloc(NULL, bytes, flag, prot);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ define_pd_global(uintx, JVMInvokeMethodSlack, 8*K);
|
||||
// ThreadStackSize 320 allows TaggedStackInterpreter and a couple of test cases
|
||||
// to run while keeping the number of threads that can be created high.
|
||||
define_pd_global(intx, ThreadStackSize, 320);
|
||||
define_pd_global(intx, VMThreadStackSize, 256);
|
||||
define_pd_global(intx, VMThreadStackSize, 512);
|
||||
define_pd_global(intx, SurvivorRatio, 8);
|
||||
define_pd_global(uintx, JVMInvokeMethodSlack, 10*K);
|
||||
#endif // AMD64
|
||||
|
@ -247,7 +247,7 @@ class BuildConfig {
|
||||
sysDefines.add("HOTSPOT_BUILD_USER="+System.getProperty("user.name"));
|
||||
sysDefines.add("HOTSPOT_BUILD_TARGET=\\\""+get("Build")+"\\\"");
|
||||
sysDefines.add("_JNI_IMPLEMENTATION_");
|
||||
sysDefines.add("HOTSPOT_LIB_ARCH=\\\"i486\\\"");
|
||||
sysDefines.add("HOTSPOT_LIB_ARCH=\\\"i386\\\"");
|
||||
|
||||
sysDefines.addAll(defines);
|
||||
|
||||
|
@ -22,61 +22,75 @@
|
||||
#
|
||||
#
|
||||
|
||||
# Single gnu makefile for solaris, linux and windows (windows requires mks or
|
||||
# cygwin).
|
||||
|
||||
ifeq ($(BINUTILS),)
|
||||
# Pop all the way out of the workspace to look for binutils.
|
||||
# ...You probably want to override this setting.
|
||||
BINUTILS = $(shell cd ../../../../..;pwd)/binutils-2.17-$(LIBARCH)
|
||||
endif
|
||||
# Single gnu makefile for solaris, linux and windows (windows requires cygwin and mingw)
|
||||
|
||||
# Default arch; it is changed below as needed.
|
||||
ARCH = i386
|
||||
OS = $(shell uname)
|
||||
|
||||
CPPFLAGS += -I$(BINUTILS)/include -I$(BINUTILS)/bfd
|
||||
CPPFLAGS += -DHOTSPOT_LIB_ARCH=\"$(LIBARCH)\" -DLIBARCH_$(LIBARCH)
|
||||
CPPFLAGS += -DHOTSPOT_OS=\"$(OS)\" -DOS_$(OS)
|
||||
|
||||
## OS = SunOS ##
|
||||
ifeq ($(OS),SunOS)
|
||||
ARCH = $(shell uname -p)
|
||||
CPU = $(shell uname -p)
|
||||
ARCH1=$(CPU:i586=i386)
|
||||
ARCH=$(ARCH1:i686=i386)
|
||||
OS = solaris
|
||||
CC = cc
|
||||
CCFLAGS += -Kpic -g
|
||||
CCFLAGS/amd64 += -xarch=amd64
|
||||
CCFLAGS/sparcv9 += -xarch=v9
|
||||
CCFLAGS += $(CCFLAGS/$(LIBARCH))
|
||||
CFLAGS += -KPIC
|
||||
ifdef LP64
|
||||
ifeq ($(ARCH),sparc)
|
||||
ARCH = sparcv9
|
||||
endif
|
||||
ifeq ($(ARCH),i386)
|
||||
ARCH = amd64
|
||||
endif
|
||||
endif
|
||||
CFLAGS/sparcv9 += -xarch=v9
|
||||
CFLAGS/amd64 += -m64
|
||||
CFLAGS += $(CFLAGS/$(ARCH))
|
||||
DLDFLAGS += -G
|
||||
LDFLAGS += -ldl
|
||||
OUTFLAGS += -o $@
|
||||
LIB_EXT = .so
|
||||
else
|
||||
## OS = Linux ##
|
||||
ifeq ($(OS),Linux)
|
||||
CPU = $(shell uname -m)
|
||||
ifeq ($(CPU),ia64)
|
||||
ARCH = ia64
|
||||
ifneq ($(MINGW),)
|
||||
LIB_EXT = .dll
|
||||
CPPFLAGS += -I$(TARGET_DIR)/include
|
||||
LDFLAGS += -L$(TARGET_DIR)/lib
|
||||
OS=windows
|
||||
ifneq ($(findstring x86_64-,$(MINGW)),)
|
||||
ARCH=amd64
|
||||
else
|
||||
ifeq ($(CPU),x86_64)
|
||||
CCFLAGS += -fPIC
|
||||
endif # x86_64
|
||||
endif # ia64
|
||||
ARCH=i386
|
||||
endif
|
||||
CC = $(MINGW)-gcc
|
||||
CONFIGURE_ARGS= --host=$(MINGW) --target=$(MINGW)
|
||||
else
|
||||
CPU = $(shell uname -m)
|
||||
ARCH1=$(CPU:x86_64=amd64)
|
||||
ARCH=$(ARCH1:i686=i386)
|
||||
CFLAGS/i386 += -m32
|
||||
CFLAGS/sparc += -m32
|
||||
CFLAGS/sparcv9 += -m64
|
||||
CFLAGS/amd64 += -m64
|
||||
CFLAGS += $(CFLAGS/$(ARCH))
|
||||
CFLAGS += -fPIC
|
||||
OS = linux
|
||||
CC = gcc
|
||||
CCFLAGS += -O
|
||||
DLDFLAGS += -shared
|
||||
OUTFLAGS += -o $@
|
||||
LIB_EXT = .so
|
||||
CPPFLAGS += -Iinclude -Iinclude/$(OS)_$(ARCH)/
|
||||
CC = gcc
|
||||
endif
|
||||
CFLAGS += -O
|
||||
DLDFLAGS += -shared
|
||||
LDFLAGS += -ldl
|
||||
OUTFLAGS += -o $@
|
||||
## OS = Windows ##
|
||||
else # !SunOS, !Linux => Windows
|
||||
OS = win
|
||||
CC = cl
|
||||
OS = windows
|
||||
CC = gcc
|
||||
#CPPFLAGS += /D"WIN32" /D"_WINDOWS" /D"DEBUG" /D"NDEBUG"
|
||||
CCFLAGS += /nologo /MD /W3 /WX /O2 /Fo$(@:.dll=.obj) /Gi-
|
||||
CCFLAGS += -Iinclude -Iinclude/gnu -Iinclude/$(OS)_$(ARCH)
|
||||
CCFLAGS += /D"HOTSPOT_LIB_ARCH=\"$(LIBARCH)\""
|
||||
CFLAGS += /nologo /MD /W3 /WX /O2 /Fo$(@:.dll=.obj) /Gi-
|
||||
CFLAGS += LIBARCH=\"$(LIBARCH)\""
|
||||
DLDFLAGS += /dll /subsystem:windows /incremental:no \
|
||||
/export:decode_instruction
|
||||
OUTFLAGS += /link /out:$@
|
||||
@ -94,21 +108,34 @@ LIBARCH = $(LIBARCH64)
|
||||
endif # LIBARCH64/$(ARCH)
|
||||
endif # LP64
|
||||
|
||||
TARGET_DIR = bin/$(OS)
|
||||
JDKARCH=$(LIBARCH:i386=i586)
|
||||
|
||||
ifeq ($(BINUTILS),)
|
||||
# Pop all the way out of the workspace to look for binutils.
|
||||
# ...You probably want to override this setting.
|
||||
BINUTILSDIR = $(shell cd build/binutils;pwd)
|
||||
else
|
||||
BINUTILSDIR = $(shell cd $(BINUTILS);pwd)
|
||||
endif
|
||||
|
||||
CPPFLAGS += -I$(BINUTILSDIR)/include -I$(BINUTILS)/bfd -I$(TARGET_DIR)/bfd
|
||||
CPPFLAGS += -DLIBARCH_$(LIBARCH) -DLIBARCH=\"$(LIBARCH)\" -DLIB_EXT=\"$(LIB_EXT)\"
|
||||
|
||||
TARGET_DIR = build/$(OS)-$(JDKARCH)
|
||||
TARGET = $(TARGET_DIR)/hsdis-$(LIBARCH)$(LIB_EXT)
|
||||
|
||||
SOURCE = hsdis.c
|
||||
|
||||
LIBRARIES = $(BINUTILS)/bfd/libbfd.a \
|
||||
$(BINUTILS)/opcodes/libopcodes.a \
|
||||
$(BINUTILS)/libiberty/libiberty.a
|
||||
LIBRARIES = $(TARGET_DIR)/bfd/libbfd.a \
|
||||
$(TARGET_DIR)/opcodes/libopcodes.a \
|
||||
$(TARGET_DIR)/libiberty/libiberty.a
|
||||
|
||||
DEMO_TARGET = $(TARGET_DIR)/hsdis-demo-$(LIBARCH)
|
||||
DEMO_TARGET = $(TARGET_DIR)/hsdis-demo
|
||||
DEMO_SOURCE = hsdis-demo.c
|
||||
|
||||
.PHONY: all clean demo both
|
||||
|
||||
all: $(TARGET) demo
|
||||
all: $(TARGET)
|
||||
|
||||
both: all all64
|
||||
|
||||
@ -117,16 +144,17 @@ both: all all64
|
||||
|
||||
demo: $(TARGET) $(DEMO_TARGET)
|
||||
|
||||
$(LIBRARIES):
|
||||
@echo "*** Please build binutils first; see ./README: ***"
|
||||
@sed < ./README '1,/__________/d' | head -20
|
||||
@echo "..."; exit 1
|
||||
$(LIBRARIES): $(TARGET_DIR) $(TARGET_DIR)/Makefile
|
||||
if [ ! -f $@ ]; then cd $(TARGET_DIR); make all-opcodes; fi
|
||||
|
||||
$(TARGET_DIR)/Makefile:
|
||||
(cd $(TARGET_DIR); CC=$(CC) CFLAGS="$(CFLAGS)" $(BINUTILSDIR)/configure --disable-nls $(CONFIGURE_ARGS))
|
||||
|
||||
$(TARGET): $(SOURCE) $(LIBS) $(LIBRARIES) $(TARGET_DIR)
|
||||
$(CC) $(OUTFLAGS) $(CPPFLAGS) $(CCFLAGS) $(SOURCE) $(DLDFLAGS) $(LIBRARIES)
|
||||
$(CC) $(OUTFLAGS) $(CPPFLAGS) $(CFLAGS) $(SOURCE) $(DLDFLAGS) $(LIBRARIES)
|
||||
|
||||
$(DEMO_TARGET): $(DEMO_SOURCE) $(TARGET) $(TARGET_DIR)
|
||||
$(CC) $(OUTFLAGS) $(CPPFLAGS) $(CCFLAGS) $(DEMO_SOURCE) $(LDFLAGS)
|
||||
$(CC) $(OUTFLAGS) -DTARGET_DIR=\"$(TARGET_DIR)\" $(CPPFLAGS) -g $(CFLAGS/$(ARCH)) $(DEMO_SOURCE) $(LDFLAGS)
|
||||
|
||||
$(TARGET_DIR):
|
||||
[ -d $@ ] || mkdir -p $@
|
||||
|
@ -32,61 +32,55 @@ you do not have a version that is new enough.
|
||||
|
||||
* Building
|
||||
|
||||
To build this project you need a build of Gnu binutils to link against.
|
||||
It is known to work with binutils 2.17.
|
||||
To build this project you a copy of GNU binutils to build against. It
|
||||
is known to work with binutils 2.17 and binutils 2.19.1. Download a
|
||||
copy of the software from http://directory.fsf.org/project/binutils or
|
||||
one of it's mirrors. Builds targetting windows should use at least
|
||||
2.19 and currently requires the use of a cross compiler.
|
||||
|
||||
The makefile looks for this build in $BINUTILS, or (if that is not set),
|
||||
in .../binutils-2.17-$LIBARCH, where LIBARCH (as in HotSpot) is one of
|
||||
the jre subdirectory keywords i386, amd64, sparc, sparcv9, etc.
|
||||
The makefile looks for the sources in build/binutils or you can
|
||||
specify it's location to the makefile using BINTUILS=path. It will
|
||||
configure binutils and build it first and then build and link the
|
||||
disasembly adapter. Make all will build the default target for your
|
||||
platform. If you platform support both 32 and 64 simultaneously then
|
||||
"make both" will build them both at once. "make all64" will
|
||||
explicitly build the 64 bit version. By default this will build the
|
||||
disassembler library only. If you build demo it will build a demo
|
||||
program that attempts to exercise the library.
|
||||
|
||||
To build Gnu binutils, first download a copy of the software:
|
||||
http://directory.fsf.org/project/binutils/
|
||||
Windows
|
||||
|
||||
Unpack the binutils tarball into an empty directory:
|
||||
chdir ../../../../..
|
||||
tar -xzf - < ../binutils-2.17.tar.gz
|
||||
mv binutils-2.17 binutils-2.17-i386 #or binutils-2.17-sparc
|
||||
cd binutils-2.17-i386
|
||||
In theory this should be buildable on Windows but getting a working
|
||||
GNU build environment on Windows has proven difficult. MINGW should
|
||||
be able to do it but at the time of this writing I was unable to get
|
||||
this working. Instead you can use the mingw cross compiler on linux
|
||||
to produce the windows binaries. For 32-bit windows you can install
|
||||
mingw32 using your package manager and it will be added to your path
|
||||
automatically. For 64-bit you need to download the 64 bit mingw from
|
||||
http://sourceforge.net/projects/mingw-w64. Grab a copy of the
|
||||
complete toolchain and unpack it somewhere. Put the bin directory of
|
||||
the toolchain in your path. The mingw installs contain cross compile
|
||||
versions of gcc that are named with a prefix to indicate what they are
|
||||
targetting and you must tell the Makefile which one to use. This
|
||||
should either be i586-mingw32msvc or x86_64-pc-mingw32 depending on
|
||||
which on you are targetting and there should be a version of gcc in
|
||||
your path named i586-mingw32msvc-gcc or x86_64-pc-mingw32-gcc. Tell
|
||||
the makefile what prefix to use to find the mingw tools by using
|
||||
MINGW=. For example:
|
||||
|
||||
From inside that directory, run configure and make:
|
||||
( export CFLAGS='-fPIC'
|
||||
./configure i386-pc-elf )
|
||||
gnumake
|
||||
make MINGW=i586-mingw32msvc BINTUILS=build/binutils-2.19.1
|
||||
|
||||
(Leave out or change the argument to configure if not on an i386 system.)
|
||||
|
||||
Next, untar again into another empty directory for the LP64 version:
|
||||
chdir ..
|
||||
tar -xzf - < ../binutils-2.17.tar.gz
|
||||
mv binutils-2.17 binutils-2.17-amd64 #or binutils-2.17-sparcv9
|
||||
cd binutils-2.17-amd64
|
||||
|
||||
From inside that directory, run configure for LP64 and make:
|
||||
( export ac_cv_c_bigendian=no CFLAGS='-m64 -fPIC' LDFLAGS=-m64
|
||||
./configure amd64-pc-elf )
|
||||
gnumake
|
||||
|
||||
The -fPIC option is needed because the generated code will be
|
||||
linked into the hsdid-$LIBARCH.so binary. If you miss the
|
||||
option, the JVM will fail to load the disassembler.
|
||||
|
||||
You probably want two builds, one for 32 and one for 64 bits.
|
||||
To build the 64-bit variation of a platforn, add LP64=1 to
|
||||
the make command line for hsdis.
|
||||
|
||||
So, go back to the hsdis project and build:
|
||||
chdir .../hsdis
|
||||
gnumake
|
||||
gnumake LP64=1
|
||||
will build the Win32 cross compiled version of hsdis based on 2.19.1.
|
||||
|
||||
* Installing
|
||||
|
||||
Products are named like bin/$OS/hsdis-$LIBARCH.so.
|
||||
You can install them on your LD_LIBRARY_PATH,
|
||||
or inside of your JRE next to $LIBARCH/libjvm.so.
|
||||
Products are named like build/$OS-$LIBARCH/hsdis-$LIBARCH.so. You can
|
||||
install them on your LD_LIBRARY_PATH, or inside of your JRE next to
|
||||
$LIBARCH/libjvm.so.
|
||||
|
||||
Now test:
|
||||
export LD_LIBRARY_PATH .../hsdis/bin/solaris:$LD_LIBRARY_PATH
|
||||
|
||||
export LD_LIBRARY_PATH .../hsdis/build/$OS-$LIBARCH:$LD_LIBRARY_PATH
|
||||
dargs='-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly'
|
||||
dargs=$dargs' -XX:PrintAssemblyOptions=hsdis-print-bytes'
|
||||
java $dargs -Xbatch CompileCommand=print,*String.hashCode HelloWorld
|
||||
|
@ -53,7 +53,7 @@ int main(int ac, char** av) {
|
||||
else if (!strncmp(arg, "-options=", 9))
|
||||
options = arg+9;
|
||||
else
|
||||
{ printf("Usage: %s [-xml] [name...]\n"); exit(2); }
|
||||
{ printf("Usage: %s [-xml] [name...]\n", av[0]); exit(2); }
|
||||
continue;
|
||||
}
|
||||
greet(arg);
|
||||
@ -76,26 +76,14 @@ void end_of_file() { }
|
||||
|
||||
#include "dlfcn.h"
|
||||
|
||||
#ifdef HOTSPOT_LIB_ARCH
|
||||
#define LIBARCH HOTSPOT_LIB_ARCH
|
||||
#endif
|
||||
#ifdef HOTSPOT_OS
|
||||
#define OS HOTSPOT_OS
|
||||
#endif
|
||||
|
||||
#define DECODE_INSTRUCTIONS_NAME "decode_instructions"
|
||||
#define HSDIS_NAME "hsdis"
|
||||
static void* decode_instructions_pv = 0;
|
||||
static const char* hsdis_path[] = {
|
||||
HSDIS_NAME".so",
|
||||
#ifdef OS
|
||||
"bin/"OS"/"HSDIS_NAME".so",
|
||||
#endif
|
||||
#ifdef LIBARCH
|
||||
HSDIS_NAME"-"LIBARCH".so",
|
||||
#ifdef OS
|
||||
"bin/"OS"/"HSDIS_NAME"-"LIBARCH".so",
|
||||
#endif
|
||||
HSDIS_NAME"-"LIBARCH LIB_EXT,
|
||||
"./" HSDIS_NAME"-"LIBARCH LIB_EXT,
|
||||
#ifdef TARGET_DIR
|
||||
TARGET_DIR"/"HSDIS_NAME"-"LIBARCH LIB_EXT,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@ -112,7 +100,7 @@ static const char* load_decode_instructions() {
|
||||
for (dllib = NULL; dllib == NULL; ) {
|
||||
const char* next_lib = (*next_in_path++);
|
||||
if (next_lib == NULL)
|
||||
return "cannot find plugin "HSDIS_NAME".so";
|
||||
return "cannot find plugin "HSDIS_NAME LIB_EXT;
|
||||
dllib = dlopen(next_lib, RTLD_LAZY);
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <libiberty.h>
|
||||
#include <bfd.h>
|
||||
#include <dis-asm.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifndef bool
|
||||
#define bool int
|
||||
@ -404,21 +405,21 @@ static const bfd_arch_info_type* find_arch_info(const char* arch_name) {
|
||||
}
|
||||
|
||||
static const char* native_arch_name() {
|
||||
const char* res = HOTSPOT_LIB_ARCH;
|
||||
const char* res = NULL;
|
||||
#ifdef LIBARCH_i386
|
||||
res = "i386";
|
||||
#endif
|
||||
#ifdef LIBARCH_amd64
|
||||
res = "i386:x86-64";
|
||||
#endif
|
||||
#ifdef LIBARCH_sparc
|
||||
res = "sparc:v8plusb";
|
||||
#endif
|
||||
#ifdef LIBARCH_sparc
|
||||
res = "sparc:v8plusb";
|
||||
#endif
|
||||
#ifdef LIBARCH_sparcv9
|
||||
res = "sparc:v9b";
|
||||
#endif
|
||||
if (res == NULL)
|
||||
res = "HOTSPOT_LIB_ARCH is not set in Makefile!";
|
||||
res = "architecture not set in Makefile!";
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1524,6 +1524,11 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
|
||||
code = Bytecodes::_invokespecial;
|
||||
}
|
||||
|
||||
if (code == Bytecodes::_invokedynamic) {
|
||||
BAILOUT("invokedynamic NYI"); // FIXME
|
||||
return;
|
||||
}
|
||||
|
||||
// NEEDS_CLEANUP
|
||||
// I've added the target-is_loaded() test below but I don't really understand
|
||||
// how klass->is_loaded() can be true and yet target->is_loaded() is false.
|
||||
@ -2431,8 +2436,8 @@ BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) {
|
||||
case Bytecodes::_invokevirtual : // fall through
|
||||
case Bytecodes::_invokespecial : // fall through
|
||||
case Bytecodes::_invokestatic : // fall through
|
||||
case Bytecodes::_invokedynamic : // fall through
|
||||
case Bytecodes::_invokeinterface: invoke(code); break;
|
||||
case Bytecodes::_xxxunusedxxx : ShouldNotReachHere(); break;
|
||||
case Bytecodes::_new : new_instance(s.get_index_big()); break;
|
||||
case Bytecodes::_newarray : new_type_array(); break;
|
||||
case Bytecodes::_anewarray : new_object_array(); break;
|
||||
@ -2571,6 +2576,7 @@ void GraphBuilder::initialize() {
|
||||
, Bytecodes::_invokevirtual
|
||||
, Bytecodes::_invokespecial
|
||||
, Bytecodes::_invokestatic
|
||||
, Bytecodes::_invokedynamic
|
||||
, Bytecodes::_invokeinterface
|
||||
, Bytecodes::_new
|
||||
, Bytecodes::_newarray
|
||||
|
@ -2956,9 +2956,11 @@ void LinearScan::do_linear_scan() {
|
||||
|
||||
NOT_PRODUCT(print_intervals("After Register Allocation"));
|
||||
NOT_PRODUCT(print_lir(2, "LIR after register allocation:"));
|
||||
DEBUG_ONLY(verify());
|
||||
|
||||
sort_intervals_after_allocation();
|
||||
|
||||
DEBUG_ONLY(verify());
|
||||
|
||||
eliminate_spill_moves();
|
||||
assign_reg_num();
|
||||
CHECK_BAILOUT();
|
||||
@ -3147,6 +3149,16 @@ void LinearScan::verify_intervals() {
|
||||
|
||||
|
||||
void LinearScan::verify_no_oops_in_fixed_intervals() {
|
||||
Interval* fixed_intervals;
|
||||
Interval* other_intervals;
|
||||
create_unhandled_lists(&fixed_intervals, &other_intervals, is_precolored_cpu_interval, NULL);
|
||||
|
||||
// to ensure a walking until the last instruction id, add a dummy interval
|
||||
// with a high operation id
|
||||
other_intervals = new Interval(any_reg);
|
||||
other_intervals->add_range(max_jint - 2, max_jint - 1);
|
||||
IntervalWalker* iw = new IntervalWalker(this, fixed_intervals, other_intervals);
|
||||
|
||||
LIR_OpVisitState visitor;
|
||||
for (int i = 0; i < block_count(); i++) {
|
||||
BlockBegin* block = block_at(i);
|
||||
@ -3159,6 +3171,54 @@ void LinearScan::verify_no_oops_in_fixed_intervals() {
|
||||
|
||||
visitor.visit(op);
|
||||
|
||||
if (visitor.info_count() > 0) {
|
||||
iw->walk_before(op->id());
|
||||
bool check_live = true;
|
||||
if (op->code() == lir_move) {
|
||||
LIR_Op1* move = (LIR_Op1*)op;
|
||||
check_live = (move->patch_code() == lir_patch_none);
|
||||
}
|
||||
LIR_OpBranch* branch = op->as_OpBranch();
|
||||
if (branch != NULL && branch->stub() != NULL && branch->stub()->is_exception_throw_stub()) {
|
||||
// Don't bother checking the stub in this case since the
|
||||
// exception stub will never return to normal control flow.
|
||||
check_live = false;
|
||||
}
|
||||
|
||||
// Make sure none of the fixed registers is live across an
|
||||
// oopmap since we can't handle that correctly.
|
||||
if (check_live) {
|
||||
for (Interval* interval = iw->active_first(fixedKind);
|
||||
interval != Interval::end();
|
||||
interval = interval->next()) {
|
||||
if (interval->current_to() > op->id() + 1) {
|
||||
// This interval is live out of this op so make sure
|
||||
// that this interval represents some value that's
|
||||
// referenced by this op either as an input or output.
|
||||
bool ok = false;
|
||||
for_each_visitor_mode(mode) {
|
||||
int n = visitor.opr_count(mode);
|
||||
for (int k = 0; k < n; k++) {
|
||||
LIR_Opr opr = visitor.opr_at(mode, k);
|
||||
if (opr->is_fixed_cpu()) {
|
||||
if (interval_at(reg_num(opr)) == interval) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
int hi = reg_numHi(opr);
|
||||
if (hi != -1 && interval_at(hi) == interval) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(ok, "fixed intervals should never be live across an oopmap point");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// oop-maps at calls do not contain registers, so check is not needed
|
||||
if (!visitor.has_call()) {
|
||||
|
||||
|
@ -833,6 +833,7 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokestatic:
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_invokeinterface:
|
||||
{ bool will_link;
|
||||
ciMethod* target = s.get_method(will_link);
|
||||
@ -848,9 +849,6 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Bytecodes::_xxxunusedxxx:
|
||||
ShouldNotReachHere();
|
||||
break;
|
||||
case Bytecodes::_new:
|
||||
state.apush(allocated_obj);
|
||||
break;
|
||||
|
@ -301,17 +301,19 @@ int ciBytecodeStream::get_field_signature_index() {
|
||||
// If this is a method invocation bytecode, get the constant pool
|
||||
// index of the invoked method.
|
||||
int ciBytecodeStream::get_method_index() {
|
||||
#ifdef ASSERT
|
||||
switch (cur_bc()) {
|
||||
case Bytecodes::_invokeinterface:
|
||||
return Bytes::get_Java_u2(_pc-4);
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokestatic:
|
||||
return get_index_big();
|
||||
case Bytecodes::_invokedynamic:
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return get_index_int();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@ -337,6 +339,9 @@ ciMethod* ciBytecodeStream::get_method(bool& will_link) {
|
||||
// for checking linkability when retrieving the associated method.
|
||||
ciKlass* ciBytecodeStream::get_declared_method_holder() {
|
||||
bool ignore;
|
||||
// report as Dynamic for invokedynamic, which is syntactically classless
|
||||
if (cur_bc() == Bytecodes::_invokedynamic)
|
||||
return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_Dynamic(), false);
|
||||
return CURRENT_ENV->get_klass_by_index(_holder, get_method_holder_index(), ignore);
|
||||
}
|
||||
|
||||
|
@ -91,9 +91,10 @@ public:
|
||||
_end = _start + max;
|
||||
}
|
||||
|
||||
address cur_bcp() { return _bc_start; } // Returns bcp to current instruction
|
||||
address cur_bcp() const { return _bc_start; } // Returns bcp to current instruction
|
||||
int next_bci() const { return _pc -_start; }
|
||||
int cur_bci() const { return _bc_start - _start; }
|
||||
int instruction_size() const { return _pc - _bc_start; }
|
||||
|
||||
Bytecodes::Code cur_bc() const{ return check_java(_bc); }
|
||||
Bytecodes::Code next_bc() { return Bytecodes::java_code((Bytecodes::Code)* _pc); }
|
||||
@ -121,34 +122,39 @@ public:
|
||||
return check_java(_bc);
|
||||
}
|
||||
|
||||
bool is_wide() { return ( _pc == _was_wide ); }
|
||||
bool is_wide() const { return ( _pc == _was_wide ); }
|
||||
|
||||
// Get a byte index following this bytecode.
|
||||
// If prefixed with a wide bytecode, get a wide index.
|
||||
int get_index() const {
|
||||
assert_index_size(is_wide() ? 2 : 1);
|
||||
return (_pc == _was_wide) // was widened?
|
||||
? Bytes::get_Java_u2(_bc_start+2) // yes, return wide index
|
||||
: _bc_start[1]; // no, return narrow index
|
||||
}
|
||||
|
||||
// Set a byte index following this bytecode.
|
||||
// If prefixed with a wide bytecode, get a wide index.
|
||||
void put_index(int idx) {
|
||||
if (_pc == _was_wide) // was widened?
|
||||
Bytes::put_Java_u2(_bc_start+2,idx); // yes, set wide index
|
||||
else
|
||||
_bc_start[1]=idx; // no, set narrow index
|
||||
// Get 2-byte index (getfield/putstatic/etc)
|
||||
int get_index_big() const {
|
||||
assert_index_size(2);
|
||||
return Bytes::get_Java_u2(_bc_start+1);
|
||||
}
|
||||
|
||||
// Get 2-byte index (getfield/putstatic/etc)
|
||||
int get_index_big() const { return Bytes::get_Java_u2(_bc_start+1); }
|
||||
// Get 2-byte index (or 4-byte, for invokedynamic)
|
||||
int get_index_int() const {
|
||||
return has_giant_index() ? get_index_giant() : get_index_big();
|
||||
}
|
||||
|
||||
// Get 4-byte index, for invokedynamic.
|
||||
int get_index_giant() const {
|
||||
assert_index_size(4);
|
||||
return Bytes::get_native_u4(_bc_start+1);
|
||||
}
|
||||
|
||||
bool has_giant_index() const { return (cur_bc() == Bytecodes::_invokedynamic); }
|
||||
|
||||
// Get dimensions byte (multinewarray)
|
||||
int get_dimensions() const { return *(unsigned char*)(_pc-1); }
|
||||
|
||||
// Get unsigned index fast
|
||||
int get_index_fast() const { return Bytes::get_native_u2(_pc-2); }
|
||||
|
||||
// Sign-extended index byte/short, no widening
|
||||
int get_byte() const { return (int8_t)(_pc[-1]); }
|
||||
int get_short() const { return (int16_t)Bytes::get_Java_u2(_pc-2); }
|
||||
@ -225,6 +231,22 @@ public:
|
||||
ciKlass* get_declared_method_holder();
|
||||
int get_method_holder_index();
|
||||
int get_method_signature_index();
|
||||
|
||||
private:
|
||||
void assert_index_size(int required_size) const {
|
||||
#ifdef ASSERT
|
||||
int isize = instruction_size() - (is_wide() ? 1 : 0) - 1;
|
||||
if (isize == 2 && cur_bc() == Bytecodes::_iinc)
|
||||
isize = 1;
|
||||
else if (isize <= 2)
|
||||
; // no change
|
||||
else if (has_giant_index())
|
||||
isize = 4;
|
||||
else
|
||||
isize = 2;
|
||||
assert(isize = required_size, "wrong index size");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -1217,31 +1217,34 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) {
|
||||
// valid class file. The class loader will check everything else.
|
||||
if (strchr(buffer, '.') == NULL) {
|
||||
_compile_the_world_counter++;
|
||||
if (_compile_the_world_counter >= CompileTheWorldStartAt && _compile_the_world_counter <= CompileTheWorldStopAt) {
|
||||
// Construct name without extension
|
||||
symbolHandle sym = oopFactory::new_symbol_handle(buffer, CHECK);
|
||||
// Use loader to load and initialize class
|
||||
klassOop ik = SystemDictionary::resolve_or_null(sym, loader, Handle(), THREAD);
|
||||
instanceKlassHandle k (THREAD, ik);
|
||||
if (k.not_null() && !HAS_PENDING_EXCEPTION) {
|
||||
k->initialize(THREAD);
|
||||
if (_compile_the_world_counter > CompileTheWorldStopAt) return;
|
||||
|
||||
// Construct name without extension
|
||||
symbolHandle sym = oopFactory::new_symbol_handle(buffer, CHECK);
|
||||
// Use loader to load and initialize class
|
||||
klassOop ik = SystemDictionary::resolve_or_null(sym, loader, Handle(), THREAD);
|
||||
instanceKlassHandle k (THREAD, ik);
|
||||
if (k.not_null() && !HAS_PENDING_EXCEPTION) {
|
||||
k->initialize(THREAD);
|
||||
}
|
||||
bool exception_occurred = HAS_PENDING_EXCEPTION;
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
if (CompileTheWorldPreloadClasses && k.not_null()) {
|
||||
constantPoolKlass::preload_and_initialize_all_classes(k->constants(), THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
// If something went wrong in preloading we just ignore it
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
tty->print_cr("Preloading failed for (%d) %s", _compile_the_world_counter, buffer);
|
||||
}
|
||||
bool exception_occurred = HAS_PENDING_EXCEPTION;
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
}
|
||||
|
||||
if (_compile_the_world_counter >= CompileTheWorldStartAt) {
|
||||
if (k.is_null() || (exception_occurred && !CompileTheWorldIgnoreInitErrors)) {
|
||||
// If something went wrong (e.g. ExceptionInInitializerError) we skip this class
|
||||
tty->print_cr("CompileTheWorld (%d) : Skipping %s", _compile_the_world_counter, buffer);
|
||||
} else {
|
||||
tty->print_cr("CompileTheWorld (%d) : %s", _compile_the_world_counter, buffer);
|
||||
// Preload all classes to get around uncommon traps
|
||||
if (CompileTheWorldPreloadClasses) {
|
||||
constantPoolKlass::preload_and_initialize_all_classes(k->constants(), THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
// If something went wrong in preloading we just ignore it
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
tty->print_cr("Preloading failed for (%d) %s", _compile_the_world_counter, buffer);
|
||||
}
|
||||
}
|
||||
// Iterate over all methods in class
|
||||
for (int n = 0; n < k->methods()->length(); n++) {
|
||||
methodHandle m (THREAD, methodOop(k->methods()->obj_at(n)));
|
||||
@ -1253,16 +1256,28 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_counter, m->name()->as_C_string());
|
||||
}
|
||||
if (TieredCompilation) {
|
||||
// Clobber the first compile and force second tier compilation
|
||||
m->clear_code();
|
||||
CompileBroker::compile_method(m, InvocationEntryBci,
|
||||
methodHandle(), 0, "CTW", THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_counter, m->name()->as_C_string());
|
||||
if (TieredCompilation) {
|
||||
// Clobber the first compile and force second tier compilation
|
||||
nmethod* nm = m->code();
|
||||
if (nm != NULL) {
|
||||
// Throw out the code so that the code cache doesn't fill up
|
||||
nm->make_not_entrant();
|
||||
m->clear_code();
|
||||
}
|
||||
CompileBroker::compile_method(m, InvocationEntryBci,
|
||||
methodHandle(), 0, "CTW", THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_counter, m->name()->as_C_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nmethod* nm = m->code();
|
||||
if (nm != NULL) {
|
||||
// Throw out the code so that the code cache doesn't fill up
|
||||
nm->make_not_entrant();
|
||||
m->clear_code();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2430,6 +2430,41 @@ oop java_dyn_MethodTypeForm::erasedType(oop mtform) {
|
||||
}
|
||||
|
||||
|
||||
// Support for sun_dyn_CallSiteImpl
|
||||
|
||||
int sun_dyn_CallSiteImpl::_type_offset;
|
||||
int sun_dyn_CallSiteImpl::_target_offset;
|
||||
int sun_dyn_CallSiteImpl::_vmmethod_offset;
|
||||
|
||||
void sun_dyn_CallSiteImpl::compute_offsets() {
|
||||
if (!EnableInvokeDynamic) return;
|
||||
klassOop k = SystemDictionary::CallSiteImpl_klass();
|
||||
if (k != NULL) {
|
||||
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_dyn_MethodType_signature(), true);
|
||||
compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_dyn_MethodHandle_signature(), true);
|
||||
compute_offset(_vmmethod_offset, k, vmSymbols::vmmethod_name(), vmSymbols::object_signature(), true);
|
||||
}
|
||||
}
|
||||
|
||||
oop sun_dyn_CallSiteImpl::type(oop site) {
|
||||
return site->obj_field(_type_offset);
|
||||
}
|
||||
|
||||
oop sun_dyn_CallSiteImpl::target(oop site) {
|
||||
return site->obj_field(_target_offset);
|
||||
}
|
||||
|
||||
void sun_dyn_CallSiteImpl::set_target(oop site, oop target) {
|
||||
site->obj_field_put(_target_offset, target);
|
||||
}
|
||||
|
||||
oop sun_dyn_CallSiteImpl::vmmethod(oop site) {
|
||||
return site->obj_field(_vmmethod_offset);
|
||||
}
|
||||
|
||||
void sun_dyn_CallSiteImpl::set_vmmethod(oop site, oop ref) {
|
||||
site->obj_field_put(_vmmethod_offset, ref);
|
||||
}
|
||||
|
||||
|
||||
// Support for java_security_AccessControlContext
|
||||
@ -2775,6 +2810,9 @@ void JavaClasses::compute_offsets() {
|
||||
java_dyn_MethodType::compute_offsets();
|
||||
java_dyn_MethodTypeForm::compute_offsets();
|
||||
}
|
||||
if (EnableInvokeDynamic) {
|
||||
sun_dyn_CallSiteImpl::compute_offsets();
|
||||
}
|
||||
java_security_AccessControlContext::compute_offsets();
|
||||
// Initialize reflection classes. The layouts of these classes
|
||||
// changed with the new reflection implementation in JDK 1.4, and
|
||||
|
@ -1060,6 +1060,33 @@ class java_dyn_MethodTypeForm: AllStatic {
|
||||
};
|
||||
|
||||
|
||||
// Interface to sun.dyn.CallSiteImpl objects
|
||||
|
||||
class sun_dyn_CallSiteImpl: AllStatic {
|
||||
friend class JavaClasses;
|
||||
|
||||
private:
|
||||
static int _type_offset;
|
||||
static int _target_offset;
|
||||
static int _vmmethod_offset;
|
||||
|
||||
static void compute_offsets();
|
||||
|
||||
public:
|
||||
// Accessors
|
||||
static oop type(oop site);
|
||||
|
||||
static oop target(oop site);
|
||||
static void set_target(oop site, oop target);
|
||||
|
||||
static oop vmmethod(oop site);
|
||||
static void set_vmmethod(oop site, oop ref);
|
||||
|
||||
// Accessors for code generation:
|
||||
static int target_offset_in_bytes() { return _target_offset; }
|
||||
static int type_offset_in_bytes() { return _type_offset; }
|
||||
static int vmmethod_offset_in_bytes() { return _vmmethod_offset; }
|
||||
};
|
||||
|
||||
|
||||
// Interface to java.security.AccessControlContext objects
|
||||
|
@ -1951,6 +1951,16 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||
// Skip the rest of the method handle classes, if MethodHandle is not loaded.
|
||||
scan = WKID(meth_group_end+1);
|
||||
}
|
||||
WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass);
|
||||
WKID indy_group_end = WK_KLASS_ENUM_NAME(Dynamic_klass);
|
||||
initialize_wk_klasses_until(indy_group_start, scan, CHECK);
|
||||
if (EnableInvokeDynamic) {
|
||||
initialize_wk_klasses_through(indy_group_start, scan, CHECK);
|
||||
}
|
||||
if (_well_known_klasses[indy_group_start] == NULL) {
|
||||
// Skip the rest of the dynamic typing classes, if Linkage is not loaded.
|
||||
scan = WKID(indy_group_end+1);
|
||||
}
|
||||
|
||||
initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
|
||||
|
||||
@ -2367,6 +2377,76 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
|
||||
}
|
||||
|
||||
|
||||
// Ask Java code to find or construct a java.dyn.CallSite for the given
|
||||
// name and signature, as interpreted relative to the given class loader.
|
||||
Handle SystemDictionary::make_dynamic_call_site(KlassHandle caller,
|
||||
int caller_method_idnum,
|
||||
int caller_bci,
|
||||
symbolHandle name,
|
||||
methodHandle mh_invdyn,
|
||||
TRAPS) {
|
||||
Handle empty;
|
||||
// call sun.dyn.CallSiteImpl::makeSite(caller, name, mtype, cmid, cbci)
|
||||
oop name_str_oop = StringTable::intern(name(), CHECK_(empty)); // not a handle!
|
||||
JavaCallArguments args(Handle(THREAD, caller->java_mirror()));
|
||||
args.push_oop(name_str_oop);
|
||||
args.push_oop(mh_invdyn->method_handle_type());
|
||||
args.push_int(caller_method_idnum);
|
||||
args.push_int(caller_bci);
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
SystemDictionary::CallSiteImpl_klass(),
|
||||
vmSymbols::makeSite_name(), vmSymbols::makeSite_signature(),
|
||||
&args, CHECK_(empty));
|
||||
oop call_site_oop = (oop) result.get_jobject();
|
||||
sun_dyn_CallSiteImpl::set_vmmethod(call_site_oop, mh_invdyn());
|
||||
if (TraceMethodHandles) {
|
||||
tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop);
|
||||
call_site_oop->print();
|
||||
tty->cr();
|
||||
}
|
||||
return call_site_oop;
|
||||
}
|
||||
|
||||
Handle SystemDictionary::find_bootstrap_method(KlassHandle caller,
|
||||
KlassHandle search_bootstrap_klass,
|
||||
TRAPS) {
|
||||
Handle empty;
|
||||
if (!caller->oop_is_instance()) return empty;
|
||||
|
||||
instanceKlassHandle ik(THREAD, caller());
|
||||
|
||||
if (ik->bootstrap_method() != NULL) {
|
||||
return Handle(THREAD, ik->bootstrap_method());
|
||||
}
|
||||
|
||||
// call java.dyn.Linkage::findBootstrapMethod(caller, sbk)
|
||||
JavaCallArguments args(Handle(THREAD, ik->java_mirror()));
|
||||
if (search_bootstrap_klass.is_null())
|
||||
args.push_oop(Handle());
|
||||
else
|
||||
args.push_oop(search_bootstrap_klass->java_mirror());
|
||||
JavaValue result(T_OBJECT);
|
||||
JavaCalls::call_static(&result,
|
||||
SystemDictionary::Linkage_klass(),
|
||||
vmSymbols::findBootstrapMethod_name(),
|
||||
vmSymbols::findBootstrapMethod_signature(),
|
||||
&args, CHECK_(empty));
|
||||
oop boot_method_oop = (oop) result.get_jobject();
|
||||
|
||||
if (boot_method_oop != NULL) {
|
||||
// probably no race conditions, but let's be careful:
|
||||
if (Atomic::cmpxchg_ptr(boot_method_oop, ik->adr_bootstrap_method(), NULL) == NULL)
|
||||
ik->set_bootstrap_method(boot_method_oop);
|
||||
else
|
||||
boot_method_oop = ik->bootstrap_method();
|
||||
} else {
|
||||
boot_method_oop = ik->bootstrap_method();
|
||||
}
|
||||
|
||||
return Handle(THREAD, boot_method_oop);
|
||||
}
|
||||
|
||||
// Since the identity hash code for symbols changes when the symbols are
|
||||
// moved from the regular perm gen (hash in the mark word) to the shared
|
||||
// spaces (hash is the address), the classes loaded into the dictionary
|
||||
|
@ -142,6 +142,12 @@ class SymbolPropertyTable;
|
||||
template(MethodType_klass, java_dyn_MethodType, Opt) \
|
||||
template(MethodTypeForm_klass, java_dyn_MethodTypeForm, Opt) \
|
||||
template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
|
||||
template(Linkage_klass, java_dyn_Linkage, Opt) \
|
||||
template(CallSite_klass, java_dyn_CallSite, Opt) \
|
||||
template(CallSiteImpl_klass, sun_dyn_CallSiteImpl, Opt) \
|
||||
template(Dynamic_klass, java_dyn_Dynamic, Opt) \
|
||||
/* Note: MethodHandle must be first, and Dynamic last in group */ \
|
||||
\
|
||||
template(vector_klass, java_util_Vector, Pre) \
|
||||
template(hashtable_klass, java_util_Hashtable, Pre) \
|
||||
template(stringBuffer_klass, java_lang_StringBuffer, Pre) \
|
||||
@ -466,6 +472,21 @@ public:
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
TRAPS);
|
||||
// ask Java to create a dynamic call site, while linking an invokedynamic op
|
||||
static Handle make_dynamic_call_site(KlassHandle caller,
|
||||
int caller_method_idnum,
|
||||
int caller_bci,
|
||||
symbolHandle name,
|
||||
methodHandle mh_invoke,
|
||||
TRAPS);
|
||||
|
||||
// coordinate with Java about bootstrap methods
|
||||
static Handle find_bootstrap_method(KlassHandle caller,
|
||||
// This argument is non-null only when a
|
||||
// classfile attribute has been found:
|
||||
KlassHandle search_bootstrap_klass,
|
||||
TRAPS);
|
||||
|
||||
// Utility for printing loader "name" as part of tracing constraints
|
||||
static const char* loader_name(oop loader) {
|
||||
return ((loader) == NULL ? "<bootloader>" :
|
||||
|
@ -1174,6 +1174,7 @@ void ClassVerifier::verify_method(methodHandle m, TRAPS) {
|
||||
&this_uninit, return_type, cp, CHECK_VERIFY(this));
|
||||
no_control_flow = false; break;
|
||||
case Bytecodes::_invokeinterface :
|
||||
case Bytecodes::_invokedynamic :
|
||||
verify_invoke_instructions(
|
||||
&bcs, code_length, ¤t_frame,
|
||||
&this_uninit, return_type, cp, CHECK_VERIFY(this));
|
||||
@ -1895,12 +1896,23 @@ void ClassVerifier::verify_invoke_instructions(
|
||||
Bytecodes::Code opcode = bcs->code();
|
||||
unsigned int types = (opcode == Bytecodes::_invokeinterface
|
||||
? 1 << JVM_CONSTANT_InterfaceMethodref
|
||||
: opcode == Bytecodes::_invokedynamic
|
||||
? 1 << JVM_CONSTANT_NameAndType
|
||||
: 1 << JVM_CONSTANT_Methodref);
|
||||
verify_cp_type(index, cp, types, CHECK_VERIFY(this));
|
||||
|
||||
// Get method name and signature
|
||||
symbolHandle method_name(THREAD, cp->name_ref_at(index));
|
||||
symbolHandle method_sig(THREAD, cp->signature_ref_at(index));
|
||||
symbolHandle method_name;
|
||||
symbolHandle method_sig;
|
||||
if (opcode == Bytecodes::_invokedynamic) {
|
||||
int name_index = cp->name_ref_index_at(index);
|
||||
int sig_index = cp->signature_ref_index_at(index);
|
||||
method_name = symbolHandle(THREAD, cp->symbol_at(name_index));
|
||||
method_sig = symbolHandle(THREAD, cp->symbol_at(sig_index));
|
||||
} else {
|
||||
method_name = symbolHandle(THREAD, cp->name_ref_at(index));
|
||||
method_sig = symbolHandle(THREAD, cp->signature_ref_at(index));
|
||||
}
|
||||
|
||||
if (!SignatureVerifier::is_valid_method_signature(method_sig)) {
|
||||
class_format_error(
|
||||
@ -1910,8 +1922,17 @@ void ClassVerifier::verify_invoke_instructions(
|
||||
}
|
||||
|
||||
// Get referenced class type
|
||||
VerificationType ref_class_type = cp_ref_index_to_type(
|
||||
index, cp, CHECK_VERIFY(this));
|
||||
VerificationType ref_class_type;
|
||||
if (opcode == Bytecodes::_invokedynamic) {
|
||||
if (!EnableInvokeDynamic) {
|
||||
class_format_error(
|
||||
"invokedynamic instructions not enabled on this JVM",
|
||||
_klass->external_name());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
ref_class_type = cp_ref_index_to_type(index, cp, CHECK_VERIFY(this));
|
||||
}
|
||||
|
||||
// For a small signature length, we just allocate 128 bytes instead
|
||||
// of parsing the signature once to find its size.
|
||||
@ -1970,6 +1991,14 @@ void ClassVerifier::verify_invoke_instructions(
|
||||
}
|
||||
}
|
||||
|
||||
if (opcode == Bytecodes::_invokedynamic) {
|
||||
address bcp = bcs->bcp();
|
||||
if (*(bcp+3) != 0 || *(bcp+4) != 0) {
|
||||
verify_error(bci, "Third and fourth operand bytes of invokedynamic must be zero");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (method_name->byte_at(0) == '<') {
|
||||
// Make sure <init> can only be invoked by invokespecial
|
||||
if (opcode != Bytecodes::_invokespecial ||
|
||||
@ -1994,7 +2023,8 @@ void ClassVerifier::verify_invoke_instructions(
|
||||
current_frame->pop_stack(sig_types[i], CHECK_VERIFY(this));
|
||||
}
|
||||
// Check objectref on operand stack
|
||||
if (opcode != Bytecodes::_invokestatic) {
|
||||
if (opcode != Bytecodes::_invokestatic &&
|
||||
opcode != Bytecodes::_invokedynamic) {
|
||||
if (method_name() == vmSymbols::object_initializer_name()) { // <init> method
|
||||
verify_invoke_init(bcs, ref_class_type, current_frame,
|
||||
code_length, this_uninit, cp, CHECK_VERIFY(this));
|
||||
|
@ -217,6 +217,9 @@
|
||||
template(base_name, "base") \
|
||||
\
|
||||
/* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
|
||||
template(java_dyn_Dynamic, "java/dyn/Dynamic") \
|
||||
template(java_dyn_Linkage, "java/dyn/Linkage") \
|
||||
template(java_dyn_CallSite, "java/dyn/CallSite") \
|
||||
template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \
|
||||
template(java_dyn_MethodType, "java/dyn/MethodType") \
|
||||
template(java_dyn_WrongMethodTypeException, "java/dyn/WrongMethodTypeException") \
|
||||
@ -230,8 +233,13 @@
|
||||
template(sun_dyn_AdapterMethodHandle, "sun/dyn/AdapterMethodHandle") \
|
||||
template(sun_dyn_BoundMethodHandle, "sun/dyn/BoundMethodHandle") \
|
||||
template(sun_dyn_DirectMethodHandle, "sun/dyn/DirectMethodHandle") \
|
||||
template(sun_dyn_CallSiteImpl, "sun/dyn/CallSiteImpl") \
|
||||
template(makeImpl_name, "makeImpl") /*MethodType::makeImpl*/ \
|
||||
template(makeImpl_signature, "(Ljava/lang/Class;[Ljava/lang/Class;ZZ)Ljava/dyn/MethodType;") \
|
||||
template(makeSite_name, "makeSite") /*CallSiteImpl::makeImpl*/ \
|
||||
template(makeSite_signature, "(Ljava/lang/Class;Ljava/lang/String;Ljava/dyn/MethodType;II)Ljava/dyn/CallSite;") \
|
||||
template(findBootstrapMethod_name, "findBootstrapMethod") \
|
||||
template(findBootstrapMethod_signature, "(Ljava/lang/Class;Ljava/lang/Class;)Ljava/dyn/MethodHandle;") \
|
||||
NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
|
||||
LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \
|
||||
\
|
||||
@ -308,9 +316,11 @@
|
||||
template(bitCount_name, "bitCount") \
|
||||
template(profile_name, "profile") \
|
||||
template(equals_name, "equals") \
|
||||
template(target_name, "target") \
|
||||
template(toString_name, "toString") \
|
||||
template(values_name, "values") \
|
||||
template(receiver_name, "receiver") \
|
||||
template(vmmethod_name, "vmmethod") \
|
||||
template(vmtarget_name, "vmtarget") \
|
||||
template(vmentry_name, "vmentry") \
|
||||
template(vmslots_name, "vmslots") \
|
||||
|
@ -270,6 +270,7 @@ c1_LIRGenerator_<arch>.cpp vmreg_<arch>.inline.hpp
|
||||
|
||||
c1_LinearScan.cpp bitMap.inline.hpp
|
||||
c1_LinearScan.cpp c1_CFGPrinter.hpp
|
||||
c1_LinearScan.cpp c1_CodeStubs.hpp
|
||||
c1_LinearScan.cpp c1_Compilation.hpp
|
||||
c1_LinearScan.cpp c1_FrameMap.hpp
|
||||
c1_LinearScan.cpp c1_IR.hpp
|
||||
|
@ -4102,6 +4102,7 @@ templateTable.hpp interp_masm_<arch_model>.hpp
|
||||
templateTable_<arch_model>.cpp interpreterRuntime.hpp
|
||||
templateTable_<arch_model>.cpp interpreter.hpp
|
||||
templateTable_<arch_model>.cpp methodDataOop.hpp
|
||||
templateTable_<arch_model>.cpp methodHandles.hpp
|
||||
templateTable_<arch_model>.cpp objArrayKlass.hpp
|
||||
templateTable_<arch_model>.cpp oop.inline.hpp
|
||||
templateTable_<arch_model>.cpp sharedRuntime.hpp
|
||||
|
@ -42,6 +42,12 @@ constantPoolKlass.cpp psPromotionManager.inline.hpp
|
||||
constantPoolKlass.cpp psScavenge.inline.hpp
|
||||
constantPoolKlass.cpp parOopClosures.inline.hpp
|
||||
|
||||
cpCacheKlass.cpp cardTableRS.hpp
|
||||
cpCacheKlass.cpp oop.pcgc.inline.hpp
|
||||
cpCacheKlass.cpp psPromotionManager.inline.hpp
|
||||
cpCacheKlass.cpp psScavenge.inline.hpp
|
||||
cpCacheKlass.cpp parOopClosures.inline.hpp
|
||||
|
||||
genCollectedHeap.cpp concurrentMarkSweepThread.hpp
|
||||
genCollectedHeap.cpp vmCMSOperations.hpp
|
||||
|
||||
|
@ -28,6 +28,7 @@ jvmtiClassFileReconstituter.cpp bytecodeStream.hpp
|
||||
jvmtiClassFileReconstituter.cpp bytes_<arch>.hpp
|
||||
jvmtiClassFileReconstituter.cpp jvmtiClassFileReconstituter.hpp
|
||||
jvmtiClassFileReconstituter.cpp symbolTable.hpp
|
||||
jvmtiClassFileReconstituter.cpp signature.hpp
|
||||
|
||||
jvmtiClassFileReconstituter.hpp jvmtiEnv.hpp
|
||||
|
||||
|
@ -217,6 +217,73 @@ class AbstractInterpreter: AllStatic {
|
||||
stackElementSize()) + tag_offset_in_bytes();
|
||||
}
|
||||
|
||||
// access to stacked values according to type:
|
||||
static oop* oop_addr_in_slot(intptr_t* slot_addr) {
|
||||
return (oop*) slot_addr;
|
||||
}
|
||||
static jint* int_addr_in_slot(intptr_t* slot_addr) {
|
||||
if ((int) sizeof(jint) < wordSize && !Bytes::is_Java_byte_ordering_different())
|
||||
// big-endian LP64
|
||||
return (jint*)(slot_addr + 1) - 1;
|
||||
else
|
||||
return (jint*) slot_addr;
|
||||
}
|
||||
static jlong long_in_slot(intptr_t* slot_addr) {
|
||||
if (sizeof(intptr_t) >= sizeof(jlong)) {
|
||||
return *(jlong*) slot_addr;
|
||||
} else if (!TaggedStackInterpreter) {
|
||||
return Bytes::get_native_u8((address)slot_addr);
|
||||
} else {
|
||||
assert(sizeof(intptr_t) * 2 == sizeof(jlong), "ILP32");
|
||||
// assemble the long in memory order (not arithmetic order)
|
||||
union { jlong j; jint i[2]; } u;
|
||||
u.i[0] = (jint) slot_addr[0*stackElementSize()];
|
||||
u.i[1] = (jint) slot_addr[1*stackElementSize()];
|
||||
return u.j;
|
||||
}
|
||||
}
|
||||
static void set_long_in_slot(intptr_t* slot_addr, jlong value) {
|
||||
if (sizeof(intptr_t) >= sizeof(jlong)) {
|
||||
*(jlong*) slot_addr = value;
|
||||
} else if (!TaggedStackInterpreter) {
|
||||
Bytes::put_native_u8((address)slot_addr, value);
|
||||
} else {
|
||||
assert(sizeof(intptr_t) * 2 == sizeof(jlong), "ILP32");
|
||||
// assemble the long in memory order (not arithmetic order)
|
||||
union { jlong j; jint i[2]; } u;
|
||||
u.j = value;
|
||||
slot_addr[0*stackElementSize()] = (intptr_t) u.i[0];
|
||||
slot_addr[1*stackElementSize()] = (intptr_t) u.i[1];
|
||||
}
|
||||
}
|
||||
static void get_jvalue_in_slot(intptr_t* slot_addr, BasicType type, jvalue* value) {
|
||||
switch (type) {
|
||||
case T_BOOLEAN: value->z = *int_addr_in_slot(slot_addr); break;
|
||||
case T_CHAR: value->c = *int_addr_in_slot(slot_addr); break;
|
||||
case T_BYTE: value->b = *int_addr_in_slot(slot_addr); break;
|
||||
case T_SHORT: value->s = *int_addr_in_slot(slot_addr); break;
|
||||
case T_INT: value->i = *int_addr_in_slot(slot_addr); break;
|
||||
case T_LONG: value->j = long_in_slot(slot_addr); break;
|
||||
case T_FLOAT: value->f = *(jfloat*)int_addr_in_slot(slot_addr); break;
|
||||
case T_DOUBLE: value->d = jdouble_cast(long_in_slot(slot_addr)); break;
|
||||
case T_OBJECT: value->l = (jobject)*oop_addr_in_slot(slot_addr); break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
static void set_jvalue_in_slot(intptr_t* slot_addr, BasicType type, jvalue* value) {
|
||||
switch (type) {
|
||||
case T_BOOLEAN: *int_addr_in_slot(slot_addr) = (value->z != 0); break;
|
||||
case T_CHAR: *int_addr_in_slot(slot_addr) = value->c; break;
|
||||
case T_BYTE: *int_addr_in_slot(slot_addr) = value->b; break;
|
||||
case T_SHORT: *int_addr_in_slot(slot_addr) = value->s; break;
|
||||
case T_INT: *int_addr_in_slot(slot_addr) = value->i; break;
|
||||
case T_LONG: set_long_in_slot(slot_addr, value->j); break;
|
||||
case T_FLOAT: *(jfloat*)int_addr_in_slot(slot_addr) = value->f; break;
|
||||
case T_DOUBLE: set_long_in_slot(slot_addr, jlong_cast(value->d)); break;
|
||||
case T_OBJECT: *oop_addr_in_slot(slot_addr) = (oop) value->l; break;
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -34,12 +34,6 @@ void Bytecode::set_code(Bytecodes::Code code) {
|
||||
}
|
||||
|
||||
|
||||
void Bytecode::set_fast_index(int i) {
|
||||
assert(0 <= i && i < 0x10000, "illegal index value");
|
||||
Bytes::put_native_u2(addr_at(1), (jushort)i);
|
||||
}
|
||||
|
||||
|
||||
bool Bytecode::check_must_rewrite() const {
|
||||
assert(Bytecodes::can_rewrite(code()), "post-check only");
|
||||
|
||||
@ -118,7 +112,12 @@ methodHandle Bytecode_invoke::static_target(TRAPS) {
|
||||
|
||||
|
||||
int Bytecode_invoke::index() const {
|
||||
return Bytes::get_Java_u2(bcp() + 1);
|
||||
// Note: Rewriter::rewrite changes the Java_u2 of an invokedynamic to a native_u4,
|
||||
// at the same time it allocates per-call-site CP cache entries.
|
||||
if (has_giant_index())
|
||||
return Bytes::get_native_u4(bcp() + 1);
|
||||
else
|
||||
return Bytes::get_Java_u2(bcp() + 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,14 +65,6 @@ class ThisRelativeObj VALUE_OBJ_CLASS_SPEC {
|
||||
// The base class for different kinds of bytecode abstractions.
|
||||
// Provides the primitive operations to manipulate code relative
|
||||
// to an objects 'this' pointer.
|
||||
//
|
||||
// Note: Even though it seems that the fast_index & set_fast_index
|
||||
// functions are machine specific, they're not. They only use
|
||||
// the natural way to store a 16bit index on a given machine,
|
||||
// independent of the particular byte ordering. Since all other
|
||||
// places in the system that refer to these indices use the
|
||||
// same method (the natural byte ordering on the platform)
|
||||
// this will always work and be machine-independent).
|
||||
|
||||
class Bytecode: public ThisRelativeObj {
|
||||
protected:
|
||||
@ -83,24 +75,40 @@ class Bytecode: public ThisRelativeObj {
|
||||
// Attributes
|
||||
address bcp() const { return addr_at(0); }
|
||||
address next_bcp() const { return addr_at(0) + Bytecodes::length_at(bcp()); }
|
||||
int instruction_size() const { return Bytecodes::length_at(bcp()); }
|
||||
|
||||
Bytecodes::Code code() const { return Bytecodes::code_at(addr_at(0)); }
|
||||
Bytecodes::Code java_code() const { return Bytecodes::java_code(code()); }
|
||||
bool must_rewrite() const { return Bytecodes::can_rewrite(code()) && check_must_rewrite(); }
|
||||
bool is_active_breakpoint() const { return Bytecodes::is_active_breakpoint_at(bcp()); }
|
||||
|
||||
int one_byte_index() const { return byte_at(1); }
|
||||
int two_byte_index() const { return (byte_at(1) << 8) + byte_at(2); }
|
||||
int one_byte_index() const { assert_index_size(1); return byte_at(1); }
|
||||
int two_byte_index() const { assert_index_size(2); return (byte_at(1) << 8) + byte_at(2); }
|
||||
|
||||
int offset() const { return (two_byte_index() << 16) >> 16; }
|
||||
address destination() const { return bcp() + offset(); }
|
||||
int fast_index() const { return Bytes::get_native_u2(addr_at(1)); }
|
||||
|
||||
// Attribute modification
|
||||
void set_code(Bytecodes::Code code);
|
||||
void set_fast_index(int i);
|
||||
|
||||
// Creation
|
||||
inline friend Bytecode* Bytecode_at(address bcp);
|
||||
|
||||
private:
|
||||
void assert_index_size(int required_size) const {
|
||||
#ifdef ASSERT
|
||||
int isize = instruction_size() - 1;
|
||||
if (isize == 2 && code() == Bytecodes::_iinc)
|
||||
isize = 1;
|
||||
else if (isize <= 2)
|
||||
; // no change
|
||||
else if (code() == Bytecodes::_invokedynamic)
|
||||
isize = 4;
|
||||
else
|
||||
isize = 2;
|
||||
assert(isize = required_size, "wrong index size");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
inline Bytecode* Bytecode_at(address bcp) {
|
||||
@ -195,6 +203,9 @@ class Bytecode_invoke: public ResourceObj {
|
||||
bool is_invokevirtual() const { return adjusted_invoke_code() == Bytecodes::_invokevirtual; }
|
||||
bool is_invokestatic() const { return adjusted_invoke_code() == Bytecodes::_invokestatic; }
|
||||
bool is_invokespecial() const { return adjusted_invoke_code() == Bytecodes::_invokespecial; }
|
||||
bool is_invokedynamic() const { return adjusted_invoke_code() == Bytecodes::_invokedynamic; }
|
||||
|
||||
bool has_giant_index() const { return is_invokedynamic(); }
|
||||
|
||||
bool is_valid() const { return is_invokeinterface() ||
|
||||
is_invokevirtual() ||
|
||||
|
@ -109,6 +109,7 @@ class RawBytecodeStream: StackObj {
|
||||
|
||||
Bytecodes::Code code() const { return _code; }
|
||||
bool is_wide() const { return _is_wide; }
|
||||
int instruction_size() const { return (_next_bci - _bci); }
|
||||
bool is_last_bytecode() const { return _next_bci >= _end_bci; }
|
||||
|
||||
address bcp() const { return method()->code_base() + _bci; }
|
||||
@ -122,8 +123,29 @@ class RawBytecodeStream: StackObj {
|
||||
int dest_w() const { return bci() + (int )Bytes::get_Java_u4(bcp() + 1); }
|
||||
|
||||
// Unsigned indices, widening
|
||||
int get_index() const { return (is_wide()) ? Bytes::get_Java_u2(bcp() + 2) : bcp()[1]; }
|
||||
int get_index_big() const { return (int)Bytes::get_Java_u2(bcp() + 1); }
|
||||
int get_index() const { assert_index_size(is_wide() ? 2 : 1);
|
||||
return (is_wide()) ? Bytes::get_Java_u2(bcp() + 2) : bcp()[1]; }
|
||||
int get_index_big() const { assert_index_size(2);
|
||||
return (int)Bytes::get_Java_u2(bcp() + 1); }
|
||||
int get_index_int() const { return has_giant_index() ? get_index_giant() : get_index_big(); }
|
||||
int get_index_giant() const { assert_index_size(4); return Bytes::get_native_u4(bcp() + 1); }
|
||||
int has_giant_index() const { return (code() == Bytecodes::_invokedynamic); }
|
||||
|
||||
private:
|
||||
void assert_index_size(int required_size) const {
|
||||
#ifdef ASSERT
|
||||
int isize = instruction_size() - (int)_is_wide - 1;
|
||||
if (isize == 2 && code() == Bytecodes::_iinc)
|
||||
isize = 1;
|
||||
else if (isize <= 2)
|
||||
; // no change
|
||||
else if (has_giant_index())
|
||||
isize = 4;
|
||||
else
|
||||
isize = 2;
|
||||
assert(isize = required_size, "wrong index size");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// In BytecodeStream, non-java bytecodes will be translated into the
|
||||
|
@ -48,12 +48,15 @@ class BytecodePrinter: public BytecodeClosure {
|
||||
|
||||
int get_index() { return *(address)_next_pc++; }
|
||||
int get_big_index() { int i=Bytes::get_Java_u2(_next_pc); _next_pc+=2; return i; }
|
||||
int get_giant_index() { int i=Bytes::get_native_u4(_next_pc); _next_pc+=4; return i; }
|
||||
int get_index_special() { return (is_wide()) ? get_big_index() : get_index(); }
|
||||
methodOop method() { return _current_method; }
|
||||
bool is_wide() { return _is_wide; }
|
||||
|
||||
|
||||
bool check_index(int i, bool in_cp_cache, int& cp_index, outputStream* st = tty);
|
||||
void print_constant(int i, outputStream* st = tty);
|
||||
void print_field_or_method(int i, outputStream* st = tty);
|
||||
void print_attributes(Bytecodes::Code code, int bci, outputStream* st = tty);
|
||||
void bytecode_epilog(int bci, outputStream* st = tty);
|
||||
|
||||
@ -182,7 +185,71 @@ void print_oop(oop value, outputStream* st) {
|
||||
}
|
||||
}
|
||||
|
||||
bool BytecodePrinter::check_index(int i, bool in_cp_cache, int& cp_index, outputStream* st) {
|
||||
constantPoolOop constants = method()->constants();
|
||||
int ilimit = constants->length(), climit = 0;
|
||||
|
||||
constantPoolCacheOop cache = NULL;
|
||||
if (in_cp_cache) {
|
||||
cache = constants->cache();
|
||||
if (cache != NULL) {
|
||||
//climit = cache->length(); // %%% private!
|
||||
size_t size = cache->size() * HeapWordSize;
|
||||
size -= sizeof(constantPoolCacheOopDesc);
|
||||
size /= sizeof(ConstantPoolCacheEntry);
|
||||
climit = (int) size;
|
||||
}
|
||||
}
|
||||
|
||||
if (in_cp_cache && constantPoolCacheOopDesc::is_secondary_index(i)) {
|
||||
i = constantPoolCacheOopDesc::decode_secondary_index(i);
|
||||
st->print(" secondary cache[%d] of", i);
|
||||
if (i >= 0 && i < climit) {
|
||||
if (!cache->entry_at(i)->is_secondary_entry()) {
|
||||
st->print_cr(" not secondary entry?", i);
|
||||
return false;
|
||||
}
|
||||
i = cache->entry_at(i)->main_entry_index();
|
||||
goto check_cache_index;
|
||||
} else {
|
||||
st->print_cr(" not in cache[*]?", i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cache != NULL) {
|
||||
i = Bytes::swap_u2(i);
|
||||
if (WizardMode) st->print(" (swap=%d)", i);
|
||||
goto check_cache_index;
|
||||
}
|
||||
|
||||
check_cp_index:
|
||||
if (i >= 0 && i < ilimit) {
|
||||
if (WizardMode) st->print(" cp[%d]", i);
|
||||
cp_index = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
st->print_cr(" CP[%d] not in CP", i);
|
||||
return false;
|
||||
|
||||
check_cache_index:
|
||||
if (i >= 0 && i < climit) {
|
||||
if (cache->entry_at(i)->is_secondary_entry()) {
|
||||
st->print_cr(" secondary entry?");
|
||||
return false;
|
||||
}
|
||||
i = cache->entry_at(i)->constant_pool_index();
|
||||
goto check_cp_index;
|
||||
}
|
||||
st->print_cr(" not in CP[*]?", i);
|
||||
return false;
|
||||
}
|
||||
|
||||
void BytecodePrinter::print_constant(int i, outputStream* st) {
|
||||
int orig_i = i;
|
||||
if (!check_index(orig_i, false, i, st)) return;
|
||||
|
||||
constantPoolOop constants = method()->constants();
|
||||
constantTag tag = constants->tag_at(i);
|
||||
|
||||
@ -203,7 +270,31 @@ void BytecodePrinter::print_constant(int i, outputStream* st) {
|
||||
st->print_cr(" %s", constants->resolved_klass_at(i)->klass_part()->external_name());
|
||||
} else if (tag.is_unresolved_klass()) {
|
||||
st->print_cr(" <unresolved klass at %d>", i);
|
||||
} else ShouldNotReachHere();
|
||||
} else {
|
||||
st->print_cr(" bad tag=%d at %d", tag.value(), i);
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodePrinter::print_field_or_method(int i, outputStream* st) {
|
||||
int orig_i = i;
|
||||
if (!check_index(orig_i, true, i, st)) return;
|
||||
|
||||
constantPoolOop constants = method()->constants();
|
||||
constantTag tag = constants->tag_at(i);
|
||||
|
||||
switch (tag.value()) {
|
||||
case JVM_CONSTANT_InterfaceMethodref:
|
||||
case JVM_CONSTANT_Methodref:
|
||||
case JVM_CONSTANT_Fieldref:
|
||||
break;
|
||||
default:
|
||||
st->print_cr(" bad tag=%d at %d", tag.value(), i);
|
||||
return;
|
||||
}
|
||||
|
||||
symbolOop name = constants->name_ref_at(orig_i);
|
||||
symbolOop signature = constants->signature_ref_at(orig_i);
|
||||
st->print_cr(" %d <%s> <%s> ", i, name->as_C_string(), signature->as_C_string());
|
||||
}
|
||||
|
||||
|
||||
@ -354,36 +445,28 @@ void BytecodePrinter::print_attributes(Bytecodes::Code code, int bci, outputStre
|
||||
case Bytecodes::_putstatic:
|
||||
case Bytecodes::_getstatic:
|
||||
case Bytecodes::_putfield:
|
||||
case Bytecodes::_getfield: {
|
||||
int i = get_big_index();
|
||||
constantPoolOop constants = method()->constants();
|
||||
symbolOop field = constants->name_ref_at(i);
|
||||
st->print_cr(" %d <%s>", i, field->as_C_string());
|
||||
}
|
||||
case Bytecodes::_getfield:
|
||||
print_field_or_method(get_big_index(), st);
|
||||
break;
|
||||
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokestatic:
|
||||
{ int i = get_big_index();
|
||||
constantPoolOop constants = method()->constants();
|
||||
symbolOop name = constants->name_ref_at(i);
|
||||
symbolOop signature = constants->signature_ref_at(i);
|
||||
st->print_cr(" %d <%s> <%s> ", i, name->as_C_string(), signature->as_C_string());
|
||||
}
|
||||
print_field_or_method(get_big_index(), st);
|
||||
break;
|
||||
|
||||
case Bytecodes::_invokeinterface:
|
||||
{ int i = get_big_index();
|
||||
int n = get_index();
|
||||
get_index();
|
||||
constantPoolOop constants = method()->constants();
|
||||
symbolOop name = constants->name_ref_at(i);
|
||||
symbolOop signature = constants->signature_ref_at(i);
|
||||
st->print_cr(" %d <%s> <%s> %d", i, name->as_C_string(), signature->as_C_string(), n);
|
||||
get_index(); // ignore zero byte
|
||||
print_field_or_method(i, st);
|
||||
}
|
||||
break;
|
||||
|
||||
case Bytecodes::_invokedynamic:
|
||||
print_field_or_method(get_giant_index(), st);
|
||||
break;
|
||||
|
||||
case Bytecodes::_new:
|
||||
case Bytecodes::_checkcast:
|
||||
case Bytecodes::_instanceof:
|
||||
|
@ -357,7 +357,7 @@ void Bytecodes::initialize() {
|
||||
def(_invokespecial , "invokespecial" , "bjj" , NULL , T_ILLEGAL, -1, true);
|
||||
def(_invokestatic , "invokestatic" , "bjj" , NULL , T_ILLEGAL, 0, true);
|
||||
def(_invokeinterface , "invokeinterface" , "bjj__", NULL , T_ILLEGAL, -1, true);
|
||||
def(_xxxunusedxxx , "xxxunusedxxx" , NULL , NULL , T_VOID , 0, false);
|
||||
def(_invokedynamic , "invokedynamic" , "bjjjj", NULL , T_ILLEGAL, -1, true );
|
||||
def(_new , "new" , "bii" , NULL , T_OBJECT , 1, true );
|
||||
def(_newarray , "newarray" , "bc" , NULL , T_OBJECT , 0, true );
|
||||
def(_anewarray , "anewarray" , "bii" , NULL , T_OBJECT , 0, true );
|
||||
|
@ -218,7 +218,7 @@ class Bytecodes: AllStatic {
|
||||
_invokespecial = 183, // 0xb7
|
||||
_invokestatic = 184, // 0xb8
|
||||
_invokeinterface = 185, // 0xb9
|
||||
_xxxunusedxxx = 186, // 0xba
|
||||
_invokedynamic = 186, // 0xba // if EnableInvokeDynamic
|
||||
_new = 187, // 0xbb
|
||||
_newarray = 188, // 0xbc
|
||||
_anewarray = 189, // 0xbd
|
||||
|
@ -681,6 +681,133 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes
|
||||
IRT_END
|
||||
|
||||
|
||||
// First time execution: Resolve symbols, create a permanent CallSiteImpl object.
|
||||
IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
|
||||
ResourceMark rm(thread);
|
||||
|
||||
assert(EnableInvokeDynamic, "");
|
||||
|
||||
const Bytecodes::Code bytecode = Bytecodes::_invokedynamic;
|
||||
|
||||
methodHandle caller_method(thread, method(thread));
|
||||
|
||||
// first determine if there is a bootstrap method
|
||||
{
|
||||
KlassHandle caller_klass(thread, caller_method->method_holder());
|
||||
Handle bootm = SystemDictionary::find_bootstrap_method(caller_klass, KlassHandle(), CHECK);
|
||||
if (bootm.is_null()) {
|
||||
// If there is no bootstrap method, throw IncompatibleClassChangeError.
|
||||
// This is a valid generic error type for resolution (JLS 12.3.3).
|
||||
char buf[200];
|
||||
jio_snprintf(buf, sizeof(buf), "Class %s has not declared a bootstrap method for invokedynamic",
|
||||
(Klass::cast(caller_klass()))->external_name());
|
||||
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
|
||||
}
|
||||
}
|
||||
|
||||
constantPoolHandle pool(thread, caller_method->constants());
|
||||
pool->set_invokedynamic(); // mark header to flag active call sites
|
||||
|
||||
int raw_index = four_byte_index(thread);
|
||||
assert(constantPoolCacheOopDesc::is_secondary_index(raw_index), "invokedynamic indexes marked specially");
|
||||
|
||||
// there are two CPC entries that are of interest:
|
||||
int site_index = constantPoolCacheOopDesc::decode_secondary_index(raw_index);
|
||||
int main_index = pool->cache()->entry_at(site_index)->main_entry_index();
|
||||
// and there is one CP entry, a NameAndType:
|
||||
int nt_index = pool->map_instruction_operand_to_index(raw_index);
|
||||
|
||||
// first resolve the signature to a MH.invoke methodOop
|
||||
if (!pool->cache()->entry_at(main_index)->is_resolved(bytecode)) {
|
||||
JvmtiHideSingleStepping jhss(thread);
|
||||
CallInfo info;
|
||||
LinkResolver::resolve_invoke(info, Handle(), pool,
|
||||
raw_index, bytecode, CHECK);
|
||||
// The main entry corresponds to a JVM_CONSTANT_NameAndType, and serves
|
||||
// as a common reference point for all invokedynamic call sites with
|
||||
// that exact call descriptor. We will link it in the CP cache exactly
|
||||
// as if it were an invokevirtual of MethodHandle.invoke.
|
||||
pool->cache()->entry_at(main_index)->set_method(
|
||||
bytecode,
|
||||
info.resolved_method(),
|
||||
info.vtable_index());
|
||||
assert(pool->cache()->entry_at(main_index)->is_vfinal(), "f2 must be a methodOop");
|
||||
}
|
||||
|
||||
// The method (f2 entry) of the main entry is the MH.invoke for the
|
||||
// invokedynamic target call signature.
|
||||
intptr_t f2_value = pool->cache()->entry_at(main_index)->f2();
|
||||
methodHandle mh_invdyn(THREAD, (methodOop) f2_value);
|
||||
assert(mh_invdyn.not_null() && mh_invdyn->is_method() && mh_invdyn->is_method_handle_invoke(),
|
||||
"correct result from LinkResolver::resolve_invokedynamic");
|
||||
|
||||
symbolHandle call_site_name(THREAD, pool->nt_name_ref_at(nt_index));
|
||||
Handle call_site
|
||||
= SystemDictionary::make_dynamic_call_site(caller_method->method_holder(),
|
||||
caller_method->method_idnum(),
|
||||
caller_method->bci_from(bcp(thread)),
|
||||
call_site_name,
|
||||
mh_invdyn,
|
||||
CHECK);
|
||||
|
||||
// In the secondary entry, the f1 field is the call site, and the f2 (index)
|
||||
// field is some data about the invoke site.
|
||||
int extra_data = 0;
|
||||
pool->cache()->entry_at(site_index)->set_dynamic_call(call_site(), extra_data);
|
||||
}
|
||||
IRT_END
|
||||
|
||||
|
||||
// Called on first time execution, and also whenever the CallSite.target is null.
|
||||
// FIXME: Do more of this in Java code.
|
||||
IRT_ENTRY(void, InterpreterRuntime::bootstrap_invokedynamic(JavaThread* thread, oopDesc* call_site)) {
|
||||
methodHandle mh_invdyn(thread, (methodOop) sun_dyn_CallSiteImpl::vmmethod(call_site));
|
||||
Handle mh_type(thread, mh_invdyn->method_handle_type());
|
||||
objArrayHandle mh_ptypes(thread, java_dyn_MethodType::ptypes(mh_type()));
|
||||
|
||||
// squish the arguments down to a single array
|
||||
int nargs = mh_ptypes->length();
|
||||
objArrayHandle arg_array;
|
||||
{
|
||||
objArrayOop aaoop = oopFactory::new_objArray(SystemDictionary::object_klass(), nargs, CHECK);
|
||||
arg_array = objArrayHandle(thread, aaoop);
|
||||
}
|
||||
frame fr = thread->last_frame();
|
||||
assert(fr.interpreter_frame_bcp() != NULL, "sanity");
|
||||
int tos_offset = 0;
|
||||
for (int i = nargs; --i >= 0; ) {
|
||||
intptr_t* slot_addr = fr.interpreter_frame_tos_at(tos_offset++);
|
||||
oop ptype = mh_ptypes->obj_at(i);
|
||||
oop arg = NULL;
|
||||
if (!java_lang_Class::is_primitive(ptype)) {
|
||||
arg = *(oop*) slot_addr;
|
||||
} else {
|
||||
BasicType bt = java_lang_Class::primitive_type(ptype);
|
||||
assert(frame::interpreter_frame_expression_stack_direction() < 0, "else reconsider this code");
|
||||
jvalue value;
|
||||
Interpreter::get_jvalue_in_slot(slot_addr, bt, &value);
|
||||
tos_offset += type2size[bt]-1;
|
||||
arg = java_lang_boxing_object::create(bt, &value, CHECK);
|
||||
// FIXME: These boxing objects are not canonicalized under
|
||||
// the Java autoboxing rules. They should be...
|
||||
// The best approach would be to push the arglist creation into Java.
|
||||
// The JVM should use a lower-level interface to communicate argument lists.
|
||||
}
|
||||
arg_array->obj_at_put(i, arg);
|
||||
}
|
||||
|
||||
// now find the bootstrap method
|
||||
oop bootstrap_mh_oop = instanceKlass::cast(fr.interpreter_frame_method()->method_holder())->bootstrap_method();
|
||||
assert(bootstrap_mh_oop != NULL, "resolve_invokedynamic ensures a BSM");
|
||||
|
||||
// return the bootstrap method and argument array via vm_result/_2
|
||||
thread->set_vm_result(bootstrap_mh_oop);
|
||||
thread->set_vm_result_2(arg_array());
|
||||
}
|
||||
IRT_END
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
// Miscellaneous
|
||||
|
||||
|
@ -42,8 +42,11 @@ class InterpreterRuntime: AllStatic {
|
||||
static bool already_resolved(JavaThread *thread) { return cache_entry(thread)->is_resolved(code(thread)); }
|
||||
static int one_byte_index(JavaThread *thread) { return bcp(thread)[1]; }
|
||||
static int two_byte_index(JavaThread *thread) { return Bytes::get_Java_u2(bcp(thread) + 1); }
|
||||
static int four_byte_index(JavaThread *thread) { return Bytes::get_native_u4(bcp(thread) + 1); }
|
||||
static int number_of_dimensions(JavaThread *thread) { return bcp(thread)[3]; }
|
||||
static ConstantPoolCacheEntry* cache_entry(JavaThread *thread) { return method(thread)->constants()->cache()->entry_at(Bytes::get_native_u2(bcp(thread) + 1)); }
|
||||
|
||||
static ConstantPoolCacheEntry* cache_entry_at(JavaThread *thread, int i) { return method(thread)->constants()->cache()->entry_at(i); }
|
||||
static ConstantPoolCacheEntry* cache_entry(JavaThread *thread) { return cache_entry_at(thread, Bytes::get_native_u2(bcp(thread) + 1)); }
|
||||
static void note_trap(JavaThread *thread, int reason, TRAPS);
|
||||
|
||||
public:
|
||||
@ -83,7 +86,9 @@ class InterpreterRuntime: AllStatic {
|
||||
static void new_illegal_monitor_state_exception(JavaThread* thread);
|
||||
|
||||
// Calls
|
||||
static void resolve_invoke (JavaThread* thread, Bytecodes::Code bytecode);
|
||||
static void resolve_invoke (JavaThread* thread, Bytecodes::Code bytecode);
|
||||
static void resolve_invokedynamic(JavaThread* thread);
|
||||
static void bootstrap_invokedynamic(JavaThread* thread, oopDesc* call_site);
|
||||
|
||||
// Breakpoints
|
||||
static void _breakpoint(JavaThread* thread, methodOopDesc* method, address bcp);
|
||||
|
@ -947,6 +947,7 @@ void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, constantPoolHan
|
||||
case Bytecodes::_invokestatic : resolve_invokestatic (result, pool, index, CHECK); break;
|
||||
case Bytecodes::_invokespecial : resolve_invokespecial (result, pool, index, CHECK); break;
|
||||
case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, CHECK); break;
|
||||
case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break;
|
||||
case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break;
|
||||
}
|
||||
return;
|
||||
@ -1008,6 +1009,30 @@ void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, consta
|
||||
resolve_interface_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK);
|
||||
}
|
||||
|
||||
|
||||
void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int raw_index, TRAPS) {
|
||||
assert(EnableInvokeDynamic, "");
|
||||
|
||||
// This guy is reached from InterpreterRuntime::resolve_invokedynamic.
|
||||
|
||||
assert(constantPoolCacheOopDesc::is_secondary_index(raw_index), "must be secondary index");
|
||||
int nt_index = pool->map_instruction_operand_to_index(raw_index);
|
||||
|
||||
// At this point, we only need the signature, and can ignore the name.
|
||||
symbolHandle method_signature(THREAD, pool->nt_signature_ref_at(nt_index));
|
||||
symbolHandle method_name = vmSymbolHandles::invoke_name();
|
||||
KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
|
||||
|
||||
// JSR 292: this must be an implicitly generated method MethodHandle.invoke(*...)
|
||||
// The extra MH receiver will be inserted into the stack on every call.
|
||||
methodHandle resolved_method;
|
||||
lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, CHECK);
|
||||
if (resolved_method.is_null()) {
|
||||
THROW(vmSymbols::java_lang_InternalError());
|
||||
}
|
||||
result.set_virtual(resolved_klass, KlassHandle(), resolved_method, resolved_method, resolved_method->vtable_index(), CHECK);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------------
|
||||
#ifndef PRODUCT
|
||||
|
||||
|
@ -167,6 +167,7 @@ class LinkResolver: AllStatic {
|
||||
static void resolve_invokespecial (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokevirtual (CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokeinterface(CallInfo& result, Handle recv, constantPoolHandle pool, int index, TRAPS);
|
||||
static void resolve_invokedynamic (CallInfo& result, constantPoolHandle pool, int index, TRAPS);
|
||||
|
||||
static void resolve_invoke (CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS);
|
||||
};
|
||||
|
@ -25,39 +25,50 @@
|
||||
# include "incls/_precompiled.incl"
|
||||
# include "incls/_rewriter.cpp.incl"
|
||||
|
||||
|
||||
// Computes an index_map (new_index -> original_index) for contant pool entries
|
||||
// Computes a CPC map (new_index -> original_index) for constant pool entries
|
||||
// that are referred to by the interpreter at runtime via the constant pool cache.
|
||||
void Rewriter::compute_index_maps(constantPoolHandle pool, intArray*& index_map, intStack*& inverse_index_map) {
|
||||
const int length = pool->length();
|
||||
index_map = new intArray(length, -1);
|
||||
// Choose an initial value large enough that we don't get frequent
|
||||
// calls to grow().
|
||||
inverse_index_map = new intStack(length / 2);
|
||||
// Also computes a CP map (original_index -> new_index).
|
||||
// Marks entries in CP which require additional processing.
|
||||
void Rewriter::compute_index_maps() {
|
||||
const int length = _pool->length();
|
||||
init_cp_map(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
switch (pool->tag_at(i).value()) {
|
||||
int tag = _pool->tag_at(i).value();
|
||||
switch (tag) {
|
||||
case JVM_CONSTANT_InterfaceMethodref:
|
||||
case JVM_CONSTANT_Fieldref : // fall through
|
||||
case JVM_CONSTANT_Methodref : // fall through
|
||||
case JVM_CONSTANT_InterfaceMethodref: {
|
||||
index_map->at_put(i, inverse_index_map->length());
|
||||
inverse_index_map->append(i);
|
||||
}
|
||||
add_cp_cache_entry(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
guarantee((int)_cp_cache_map.length()-1 <= (int)((u2)-1),
|
||||
"all cp cache indexes fit in a u2");
|
||||
}
|
||||
|
||||
|
||||
// Creates a constant pool cache given an inverse_index_map
|
||||
int Rewriter::add_extra_cp_cache_entry(int main_entry) {
|
||||
// Hack: We put it on the map as an encoded value.
|
||||
// The only place that consumes this is ConstantPoolCacheEntry::set_initial_state
|
||||
int encoded = constantPoolCacheOopDesc::encode_secondary_index(main_entry);
|
||||
int plain_secondary_index = _cp_cache_map.append(encoded);
|
||||
return constantPoolCacheOopDesc::encode_secondary_index(plain_secondary_index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Creates a constant pool cache given a CPC map
|
||||
// This creates the constant pool cache initially in a state
|
||||
// that is unsafe for concurrent GC processing but sets it to
|
||||
// a safe mode before the constant pool cache is returned.
|
||||
constantPoolCacheHandle Rewriter::new_constant_pool_cache(intArray& inverse_index_map, TRAPS) {
|
||||
const int length = inverse_index_map.length();
|
||||
constantPoolCacheOop cache = oopFactory::new_constantPoolCache(length,
|
||||
methodOopDesc::IsUnsafeConc,
|
||||
CHECK_(constantPoolCacheHandle()));
|
||||
cache->initialize(inverse_index_map);
|
||||
return constantPoolCacheHandle(THREAD, cache);
|
||||
void Rewriter::make_constant_pool_cache(TRAPS) {
|
||||
const int length = _cp_cache_map.length();
|
||||
constantPoolCacheOop cache =
|
||||
oopFactory::new_constantPoolCache(length, methodOopDesc::IsUnsafeConc, CHECK);
|
||||
cache->initialize(_cp_cache_map);
|
||||
_pool->set_cache(cache);
|
||||
cache->set_constant_pool(_pool());
|
||||
}
|
||||
|
||||
|
||||
@ -101,8 +112,38 @@ void Rewriter::rewrite_Object_init(methodHandle method, TRAPS) {
|
||||
}
|
||||
|
||||
|
||||
// Rewrite a classfile-order CP index into a native-order CPC index.
|
||||
int Rewriter::rewrite_member_reference(address bcp, int offset) {
|
||||
address p = bcp + offset;
|
||||
int cp_index = Bytes::get_Java_u2(p);
|
||||
int cache_index = cp_entry_to_cp_cache(cp_index);
|
||||
Bytes::put_native_u2(p, cache_index);
|
||||
return cp_index;
|
||||
}
|
||||
|
||||
|
||||
void Rewriter::rewrite_invokedynamic(address bcp, int offset, int delete_me) {
|
||||
address p = bcp + offset;
|
||||
assert(p[-1] == Bytecodes::_invokedynamic, "");
|
||||
int cp_index = Bytes::get_Java_u2(p);
|
||||
int cpc = maybe_add_cp_cache_entry(cp_index); // add lazily
|
||||
int cpc2 = add_extra_cp_cache_entry(cpc);
|
||||
|
||||
// Replace the trailing four bytes with a CPC index for the dynamic
|
||||
// call site. Unlike other CPC entries, there is one per bytecode,
|
||||
// not just one per distinct CP entry. In other words, the
|
||||
// CPC-to-CP relation is many-to-one for invokedynamic entries.
|
||||
// This means we must use a larger index size than u2 to address
|
||||
// all these entries. That is the main reason invokedynamic
|
||||
// must have a five-byte instruction format. (Of course, other JVM
|
||||
// implementations can use the bytes for other purposes.)
|
||||
Bytes::put_native_u4(p, cpc2);
|
||||
// Note: We use native_u4 format exclusively for 4-byte indexes.
|
||||
}
|
||||
|
||||
|
||||
// Rewrites a method given the index_map information
|
||||
methodHandle Rewriter::rewrite_method(methodHandle method, intArray& index_map, TRAPS) {
|
||||
void Rewriter::scan_method(methodOop method) {
|
||||
|
||||
int nof_jsrs = 0;
|
||||
bool has_monitor_bytecodes = false;
|
||||
@ -121,6 +162,7 @@ methodHandle Rewriter::rewrite_method(methodHandle method, intArray& index_map,
|
||||
int bc_length;
|
||||
for (int bci = 0; bci < code_length; bci += bc_length) {
|
||||
address bcp = code_base + bci;
|
||||
int prefix_length = 0;
|
||||
c = (Bytecodes::Code)(*bcp);
|
||||
|
||||
// Since we have the code, see if we can get the length
|
||||
@ -135,6 +177,7 @@ methodHandle Rewriter::rewrite_method(methodHandle method, intArray& index_map,
|
||||
// by 'wide'. We don't currently examine any of the bytecodes
|
||||
// modified by wide, but in case we do in the future...
|
||||
if (c == Bytecodes::_wide) {
|
||||
prefix_length = 1;
|
||||
c = (Bytecodes::Code)bcp[1];
|
||||
}
|
||||
}
|
||||
@ -159,12 +202,13 @@ methodHandle Rewriter::rewrite_method(methodHandle method, intArray& index_map,
|
||||
case Bytecodes::_putfield : // fall through
|
||||
case Bytecodes::_invokevirtual : // fall through
|
||||
case Bytecodes::_invokespecial : // fall through
|
||||
case Bytecodes::_invokestatic : // fall through
|
||||
case Bytecodes::_invokeinterface: {
|
||||
address p = bcp + 1;
|
||||
Bytes::put_native_u2(p, index_map[Bytes::get_Java_u2(p)]);
|
||||
case Bytecodes::_invokestatic :
|
||||
case Bytecodes::_invokeinterface:
|
||||
rewrite_member_reference(bcp, prefix_length+1);
|
||||
break;
|
||||
case Bytecodes::_invokedynamic:
|
||||
rewrite_invokedynamic(bcp, prefix_length+1, int(sizeof"@@@@DELETE ME"));
|
||||
break;
|
||||
}
|
||||
case Bytecodes::_jsr : // fall through
|
||||
case Bytecodes::_jsr_w : nof_jsrs++; break;
|
||||
case Bytecodes::_monitorenter : // fall through
|
||||
@ -182,53 +226,56 @@ methodHandle Rewriter::rewrite_method(methodHandle method, intArray& index_map,
|
||||
// have to be rewritten, so we run the oopMapGenerator on the method
|
||||
if (nof_jsrs > 0) {
|
||||
method->set_has_jsrs();
|
||||
ResolveOopMapConflicts romc(method);
|
||||
methodHandle original_method = method;
|
||||
method = romc.do_potential_rewrite(CHECK_(methodHandle()));
|
||||
if (method() != original_method()) {
|
||||
// Insert invalid bytecode into original methodOop and set
|
||||
// interpreter entrypoint, so that a executing this method
|
||||
// will manifest itself in an easy recognizable form.
|
||||
address bcp = original_method->bcp_from(0);
|
||||
*bcp = (u1)Bytecodes::_shouldnotreachhere;
|
||||
int kind = Interpreter::method_kind(original_method);
|
||||
original_method->set_interpreter_kind(kind);
|
||||
}
|
||||
// Second pass will revisit this method.
|
||||
assert(method->has_jsrs(), "");
|
||||
}
|
||||
}
|
||||
|
||||
// Update monitor matching info.
|
||||
if (romc.monitor_safe()) {
|
||||
method->set_guaranteed_monitor_matching();
|
||||
}
|
||||
// After constant pool is created, revisit methods containing jsrs.
|
||||
methodHandle Rewriter::rewrite_jsrs(methodHandle method, TRAPS) {
|
||||
ResolveOopMapConflicts romc(method);
|
||||
methodHandle original_method = method;
|
||||
method = romc.do_potential_rewrite(CHECK_(methodHandle()));
|
||||
if (method() != original_method()) {
|
||||
// Insert invalid bytecode into original methodOop and set
|
||||
// interpreter entrypoint, so that a executing this method
|
||||
// will manifest itself in an easy recognizable form.
|
||||
address bcp = original_method->bcp_from(0);
|
||||
*bcp = (u1)Bytecodes::_shouldnotreachhere;
|
||||
int kind = Interpreter::method_kind(original_method);
|
||||
original_method->set_interpreter_kind(kind);
|
||||
}
|
||||
|
||||
// Setup method entrypoints for compiler and interpreter
|
||||
method->link_method(method, CHECK_(methodHandle()));
|
||||
// Update monitor matching info.
|
||||
if (romc.monitor_safe()) {
|
||||
method->set_guaranteed_monitor_matching();
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
|
||||
void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) {
|
||||
// gather starting points
|
||||
ResourceMark rm(THREAD);
|
||||
constantPoolHandle pool (THREAD, klass->constants());
|
||||
objArrayHandle methods (THREAD, klass->methods());
|
||||
assert(pool->cache() == NULL, "constant pool cache must not be set yet");
|
||||
Rewriter rw(klass, CHECK);
|
||||
// (That's all, folks.)
|
||||
}
|
||||
|
||||
Rewriter::Rewriter(instanceKlassHandle klass, TRAPS)
|
||||
: _klass(klass),
|
||||
// gather starting points
|
||||
_pool( THREAD, klass->constants()),
|
||||
_methods(THREAD, klass->methods())
|
||||
{
|
||||
assert(_pool->cache() == NULL, "constant pool cache must not be set yet");
|
||||
|
||||
// determine index maps for methodOop rewriting
|
||||
intArray* index_map = NULL;
|
||||
intStack* inverse_index_map = NULL;
|
||||
compute_index_maps(pool, index_map, inverse_index_map);
|
||||
compute_index_maps();
|
||||
|
||||
// allocate constant pool cache
|
||||
constantPoolCacheHandle cache = new_constant_pool_cache(*inverse_index_map, CHECK);
|
||||
pool->set_cache(cache());
|
||||
cache->set_constant_pool(pool());
|
||||
|
||||
if (RegisterFinalizersAtInit && klass->name() == vmSymbols::java_lang_Object()) {
|
||||
int i = methods->length();
|
||||
if (RegisterFinalizersAtInit && _klass->name() == vmSymbols::java_lang_Object()) {
|
||||
int i = _methods->length();
|
||||
while (i-- > 0) {
|
||||
methodOop method = (methodOop)methods->obj_at(i);
|
||||
methodOop method = (methodOop)_methods->obj_at(i);
|
||||
if (method->intrinsic_id() == vmIntrinsics::_Object_init) {
|
||||
// rewrite the return bytecodes of Object.<init> to register the
|
||||
// object for finalization if needed.
|
||||
@ -239,13 +286,27 @@ void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) {
|
||||
}
|
||||
}
|
||||
|
||||
// rewrite methods
|
||||
{ int i = methods->length();
|
||||
while (i-- > 0) {
|
||||
methodHandle m(THREAD, (methodOop)methods->obj_at(i));
|
||||
m = rewrite_method(m, *index_map, CHECK);
|
||||
// rewrite methods, in two passes
|
||||
int i, len = _methods->length();
|
||||
|
||||
for (i = len; --i >= 0; ) {
|
||||
methodOop method = (methodOop)_methods->obj_at(i);
|
||||
scan_method(method);
|
||||
}
|
||||
|
||||
// allocate constant pool cache, now that we've seen all the bytecodes
|
||||
make_constant_pool_cache(CHECK);
|
||||
|
||||
for (i = len; --i >= 0; ) {
|
||||
methodHandle m(THREAD, (methodOop)_methods->obj_at(i));
|
||||
|
||||
if (m->has_jsrs()) {
|
||||
m = rewrite_jsrs(m, CHECK);
|
||||
// Method might have gotten rewritten.
|
||||
methods->obj_at_put(i, m());
|
||||
_methods->obj_at_put(i, m());
|
||||
}
|
||||
|
||||
// Set up method entry points for compiler and interpreter.
|
||||
m->link_method(m, CHECK);
|
||||
}
|
||||
}
|
||||
|
@ -25,13 +25,44 @@
|
||||
// The Rewriter adds caches to the constant pool and rewrites bytecode indices
|
||||
// pointing into the constant pool for better interpreter performance.
|
||||
|
||||
class Rewriter: public AllStatic {
|
||||
class Rewriter: public StackObj {
|
||||
private:
|
||||
static void compute_index_maps(constantPoolHandle pool, intArray*& index_map, intStack*& inverse_index_map);
|
||||
static constantPoolCacheHandle new_constant_pool_cache(intArray& inverse_index_map, TRAPS);
|
||||
static methodHandle rewrite_method(methodHandle method, intArray& index_map, TRAPS);
|
||||
static void rewrite_Object_init(methodHandle method, TRAPS);
|
||||
instanceKlassHandle _klass;
|
||||
constantPoolHandle _pool;
|
||||
objArrayHandle _methods;
|
||||
intArray _cp_map;
|
||||
intStack _cp_cache_map;
|
||||
|
||||
void init_cp_map(int length) {
|
||||
_cp_map.initialize(length, -1);
|
||||
// Choose an initial value large enough that we don't get frequent
|
||||
// calls to grow().
|
||||
_cp_cache_map.initialize(length / 2);
|
||||
}
|
||||
int cp_entry_to_cp_cache(int i) { assert(has_cp_cache(i), "oob"); return _cp_map[i]; }
|
||||
bool has_cp_cache(int i) { return (uint)i < (uint)_cp_map.length() && _cp_map[i] >= 0; }
|
||||
int maybe_add_cp_cache_entry(int i) { return has_cp_cache(i) ? _cp_map[i] : add_cp_cache_entry(i); }
|
||||
int add_cp_cache_entry(int cp_index) {
|
||||
assert(_cp_map[cp_index] == -1, "not twice on same cp_index");
|
||||
int cache_index = _cp_cache_map.append(cp_index);
|
||||
_cp_map.at_put(cp_index, cache_index);
|
||||
assert(cp_entry_to_cp_cache(cp_index) == cache_index, "");
|
||||
return cache_index;
|
||||
}
|
||||
int add_extra_cp_cache_entry(int main_entry);
|
||||
|
||||
// All the work goes in here:
|
||||
Rewriter(instanceKlassHandle klass, TRAPS);
|
||||
|
||||
void compute_index_maps();
|
||||
void make_constant_pool_cache(TRAPS);
|
||||
void scan_method(methodOop m);
|
||||
methodHandle rewrite_jsrs(methodHandle m, TRAPS);
|
||||
void rewrite_Object_init(methodHandle m, TRAPS);
|
||||
int rewrite_member_reference(address bcp, int offset);
|
||||
void rewrite_invokedynamic(address bcp, int offset, int cp_index);
|
||||
|
||||
public:
|
||||
// Driver routine:
|
||||
static void rewrite(instanceKlassHandle klass, TRAPS);
|
||||
};
|
||||
|
@ -178,12 +178,14 @@ EntryPoint TemplateInterpreter::_trace_code;
|
||||
#endif // !PRODUCT
|
||||
EntryPoint TemplateInterpreter::_return_entry[TemplateInterpreter::number_of_return_entries];
|
||||
EntryPoint TemplateInterpreter::_earlyret_entry;
|
||||
EntryPoint TemplateInterpreter::_return_unbox_entry;
|
||||
EntryPoint TemplateInterpreter::_deopt_entry [TemplateInterpreter::number_of_deopt_entries ];
|
||||
EntryPoint TemplateInterpreter::_continuation_entry;
|
||||
EntryPoint TemplateInterpreter::_safept_entry;
|
||||
|
||||
address TemplateInterpreter::_return_3_addrs_by_index[TemplateInterpreter::number_of_return_addrs];
|
||||
address TemplateInterpreter::_return_5_addrs_by_index[TemplateInterpreter::number_of_return_addrs];
|
||||
address TemplateInterpreter::_return_5_unbox_addrs_by_index[TemplateInterpreter::number_of_return_addrs];
|
||||
|
||||
DispatchTable TemplateInterpreter::_active_table;
|
||||
DispatchTable TemplateInterpreter::_normal_table;
|
||||
@ -251,6 +253,22 @@ void TemplateInterpreterGenerator::generate_all() {
|
||||
}
|
||||
}
|
||||
|
||||
if (EnableInvokeDynamic) {
|
||||
CodeletMark cm(_masm, "unboxing return entry points");
|
||||
Interpreter::_return_unbox_entry =
|
||||
EntryPoint(
|
||||
generate_return_unbox_entry_for(btos, 5),
|
||||
generate_return_unbox_entry_for(ctos, 5),
|
||||
generate_return_unbox_entry_for(stos, 5),
|
||||
generate_return_unbox_entry_for(atos, 5), // cast conversion
|
||||
generate_return_unbox_entry_for(itos, 5),
|
||||
generate_return_unbox_entry_for(ltos, 5),
|
||||
generate_return_unbox_entry_for(ftos, 5),
|
||||
generate_return_unbox_entry_for(dtos, 5),
|
||||
Interpreter::_return_entry[5].entry(vtos) // no unboxing for void
|
||||
);
|
||||
}
|
||||
|
||||
{ CodeletMark cm(_masm, "earlyret entry points");
|
||||
Interpreter::_earlyret_entry =
|
||||
EntryPoint(
|
||||
@ -298,8 +316,11 @@ void TemplateInterpreterGenerator::generate_all() {
|
||||
|
||||
for (int j = 0; j < number_of_states; j++) {
|
||||
const TosState states[] = {btos, ctos, stos, itos, ltos, ftos, dtos, atos, vtos};
|
||||
Interpreter::_return_3_addrs_by_index[Interpreter::TosState_as_index(states[j])] = Interpreter::return_entry(states[j], 3);
|
||||
Interpreter::_return_5_addrs_by_index[Interpreter::TosState_as_index(states[j])] = Interpreter::return_entry(states[j], 5);
|
||||
int index = Interpreter::TosState_as_index(states[j]);
|
||||
Interpreter::_return_3_addrs_by_index[index] = Interpreter::return_entry(states[j], 3);
|
||||
Interpreter::_return_5_addrs_by_index[index] = Interpreter::return_entry(states[j], 5);
|
||||
if (EnableInvokeDynamic)
|
||||
Interpreter::_return_5_unbox_addrs_by_index[index] = Interpreter::return_unbox_entry(states[j], 5);
|
||||
}
|
||||
|
||||
{ CodeletMark cm(_masm, "continuation entry points");
|
||||
@ -526,6 +547,18 @@ address TemplateInterpreter::return_entry(TosState state, int length) {
|
||||
}
|
||||
|
||||
|
||||
address TemplateInterpreter::return_unbox_entry(TosState state, int length) {
|
||||
assert(EnableInvokeDynamic, "");
|
||||
if (state == vtos) {
|
||||
// no unboxing to do, actually
|
||||
return return_entry(state, length);
|
||||
} else {
|
||||
assert(length == 5, "unboxing entries generated for invokedynamic only");
|
||||
return _return_unbox_entry.entry(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
address TemplateInterpreter::deopt_entry(TosState state, int length) {
|
||||
guarantee(0 <= length && length < Interpreter::number_of_deopt_entries, "illegal length");
|
||||
return _deopt_entry[length].entry(state);
|
||||
|
@ -83,9 +83,9 @@ class TemplateInterpreter: public AbstractInterpreter {
|
||||
public:
|
||||
|
||||
enum MoreConstants {
|
||||
number_of_return_entries = 9, // number of return entry points
|
||||
number_of_deopt_entries = 9, // number of deoptimization entry points
|
||||
number_of_return_addrs = 9 // number of return addresses
|
||||
number_of_return_entries = number_of_states, // number of return entry points
|
||||
number_of_deopt_entries = number_of_states, // number of deoptimization entry points
|
||||
number_of_return_addrs = number_of_states // number of return addresses
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -110,12 +110,14 @@ class TemplateInterpreter: public AbstractInterpreter {
|
||||
#endif // !PRODUCT
|
||||
static EntryPoint _return_entry[number_of_return_entries]; // entry points to return to from a call
|
||||
static EntryPoint _earlyret_entry; // entry point to return early from a call
|
||||
static EntryPoint _return_unbox_entry; // entry point to unbox a return value from a call
|
||||
static EntryPoint _deopt_entry[number_of_deopt_entries]; // entry points to return to from a deoptimization
|
||||
static EntryPoint _continuation_entry;
|
||||
static EntryPoint _safept_entry;
|
||||
|
||||
static address _return_3_addrs_by_index[number_of_return_addrs]; // for invokevirtual return entries
|
||||
static address _return_5_addrs_by_index[number_of_return_addrs]; // for invokeinterface return entries
|
||||
static address _return_5_unbox_addrs_by_index[number_of_return_addrs]; // for invokedynamic bootstrap methods
|
||||
|
||||
static DispatchTable _active_table; // the active dispatch table (used by the interpreter for dispatch)
|
||||
static DispatchTable _normal_table; // the normal dispatch table (used to set the active table in normal mode)
|
||||
@ -157,10 +159,12 @@ class TemplateInterpreter: public AbstractInterpreter {
|
||||
// Support for invokes
|
||||
static address* return_3_addrs_by_index_table() { return _return_3_addrs_by_index; }
|
||||
static address* return_5_addrs_by_index_table() { return _return_5_addrs_by_index; }
|
||||
static address* return_5_unbox_addrs_by_index_table() { return _return_5_unbox_addrs_by_index; }
|
||||
static int TosState_as_index(TosState state); // computes index into return_3_entry_by_index table
|
||||
|
||||
static address return_entry (TosState state, int length);
|
||||
static address deopt_entry (TosState state, int length);
|
||||
static address return_unbox_entry(TosState state, int length);
|
||||
|
||||
// Safepoint support
|
||||
static void notice_safepoints(); // stops the thread when reaching a safepoint
|
||||
|
@ -51,7 +51,10 @@ class TemplateInterpreterGenerator: public AbstractInterpreterGenerator {
|
||||
address generate_WrongMethodType_handler();
|
||||
address generate_ArrayIndexOutOfBounds_handler(const char* name);
|
||||
address generate_continuation_for(TosState state);
|
||||
address generate_return_entry_for(TosState state, int step);
|
||||
address generate_return_entry_for(TosState state, int step, bool unbox = false);
|
||||
address generate_return_unbox_entry_for(TosState state, int step) {
|
||||
return generate_return_entry_for(state, step, true);
|
||||
}
|
||||
address generate_earlyret_entry_for(TosState state);
|
||||
address generate_deopt_entry_for(TosState state, int step);
|
||||
address generate_safept_entry_for(TosState state, address runtime_entry);
|
||||
|
@ -442,6 +442,7 @@ void TemplateTable::initialize() {
|
||||
def(Bytecodes::_invokespecial , ubcp|disp|clvm|____, vtos, vtos, invokespecial , 1 );
|
||||
def(Bytecodes::_invokestatic , ubcp|disp|clvm|____, vtos, vtos, invokestatic , 1 );
|
||||
def(Bytecodes::_invokeinterface , ubcp|disp|clvm|____, vtos, vtos, invokeinterface , 1 );
|
||||
def(Bytecodes::_invokedynamic , ubcp|disp|clvm|____, vtos, vtos, invokedynamic , 1 );
|
||||
def(Bytecodes::_new , ubcp|____|clvm|____, vtos, atos, _new , _ );
|
||||
def(Bytecodes::_newarray , ubcp|____|clvm|____, itos, atos, newarray , _ );
|
||||
def(Bytecodes::_anewarray , ubcp|____|clvm|____, itos, atos, anewarray , _ );
|
||||
@ -503,7 +504,6 @@ void TemplateTable::initialize() {
|
||||
|
||||
def(Bytecodes::_fast_invokevfinal , ubcp|disp|clvm|____, vtos, vtos, fast_invokevfinal , 2 );
|
||||
|
||||
|
||||
def(Bytecodes::_fast_linearswitch , ubcp|disp|____|____, itos, vtos, fast_linearswitch , _ );
|
||||
def(Bytecodes::_fast_binaryswitch , ubcp|disp|____|____, itos, vtos, fast_binaryswitch , _ );
|
||||
|
||||
|
@ -261,6 +261,7 @@ class TemplateTable: AllStatic {
|
||||
static void invokespecial(int byte_no);
|
||||
static void invokestatic(int byte_no);
|
||||
static void invokeinterface(int byte_no);
|
||||
static void invokedynamic(int byte_no);
|
||||
static void fast_invokevfinal(int byte_no);
|
||||
|
||||
static void getfield_or_static(int byte_no, bool is_static);
|
||||
|
@ -312,6 +312,7 @@ void constantPoolKlass::oop_print_on(oop obj, outputStream* st) {
|
||||
if (cp->flags() != 0) {
|
||||
st->print(" - flags : 0x%x", cp->flags());
|
||||
if (cp->has_pseudo_string()) st->print(" has_pseudo_string");
|
||||
if (cp->has_invokedynamic()) st->print(" has_invokedynamic");
|
||||
st->cr();
|
||||
}
|
||||
|
||||
|
@ -249,32 +249,41 @@ klassOop constantPoolOopDesc::klass_ref_at_if_loaded_check(constantPoolHandle th
|
||||
}
|
||||
|
||||
|
||||
symbolOop constantPoolOopDesc::uncached_name_ref_at(int which) {
|
||||
jint ref_index = name_and_type_at(uncached_name_and_type_ref_index_at(which));
|
||||
int name_index = extract_low_short_from_int(ref_index);
|
||||
symbolOop constantPoolOopDesc::impl_name_ref_at(int which, bool uncached) {
|
||||
int name_index = name_ref_index_at(impl_name_and_type_ref_index_at(which, uncached));
|
||||
return symbol_at(name_index);
|
||||
}
|
||||
|
||||
|
||||
symbolOop constantPoolOopDesc::uncached_signature_ref_at(int which) {
|
||||
jint ref_index = name_and_type_at(uncached_name_and_type_ref_index_at(which));
|
||||
int signature_index = extract_high_short_from_int(ref_index);
|
||||
symbolOop constantPoolOopDesc::impl_signature_ref_at(int which, bool uncached) {
|
||||
int signature_index = signature_ref_index_at(impl_name_and_type_ref_index_at(which, uncached));
|
||||
return symbol_at(signature_index);
|
||||
}
|
||||
|
||||
|
||||
int constantPoolOopDesc::uncached_name_and_type_ref_index_at(int which) {
|
||||
jint ref_index = field_or_method_at(which, true);
|
||||
int constantPoolOopDesc::impl_name_and_type_ref_index_at(int which, bool uncached) {
|
||||
jint ref_index = field_or_method_at(which, uncached);
|
||||
return extract_high_short_from_int(ref_index);
|
||||
}
|
||||
|
||||
|
||||
int constantPoolOopDesc::uncached_klass_ref_index_at(int which) {
|
||||
jint ref_index = field_or_method_at(which, true);
|
||||
int constantPoolOopDesc::impl_klass_ref_index_at(int which, bool uncached) {
|
||||
jint ref_index = field_or_method_at(which, uncached);
|
||||
return extract_low_short_from_int(ref_index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int constantPoolOopDesc::map_instruction_operand_to_index(int operand) {
|
||||
if (constantPoolCacheOopDesc::is_secondary_index(operand)) {
|
||||
return cache()->main_entry_at(operand)->constant_pool_index();
|
||||
}
|
||||
assert((int)(u2)operand == operand, "clean u2");
|
||||
int index = Bytes::swap_u2(operand);
|
||||
return cache()->entry_at(index)->constant_pool_index();
|
||||
}
|
||||
|
||||
|
||||
void constantPoolOopDesc::verify_constant_pool_resolve(constantPoolHandle this_oop, KlassHandle k, TRAPS) {
|
||||
if (k->oop_is_instance() || k->oop_is_objArray()) {
|
||||
instanceKlassHandle holder (THREAD, this_oop->pool_holder());
|
||||
@ -290,26 +299,14 @@ void constantPoolOopDesc::verify_constant_pool_resolve(constantPoolHandle this_o
|
||||
}
|
||||
|
||||
|
||||
int constantPoolOopDesc::klass_ref_index_at(int which) {
|
||||
jint ref_index = field_or_method_at(which, false);
|
||||
int constantPoolOopDesc::name_ref_index_at(int which_nt) {
|
||||
jint ref_index = name_and_type_at(which_nt);
|
||||
return extract_low_short_from_int(ref_index);
|
||||
}
|
||||
|
||||
|
||||
int constantPoolOopDesc::name_and_type_ref_index_at(int which) {
|
||||
jint ref_index = field_or_method_at(which, false);
|
||||
return extract_high_short_from_int(ref_index);
|
||||
}
|
||||
|
||||
|
||||
int constantPoolOopDesc::name_ref_index_at(int which) {
|
||||
jint ref_index = name_and_type_at(which);
|
||||
return extract_low_short_from_int(ref_index);
|
||||
}
|
||||
|
||||
|
||||
int constantPoolOopDesc::signature_ref_index_at(int which) {
|
||||
jint ref_index = name_and_type_at(which);
|
||||
int constantPoolOopDesc::signature_ref_index_at(int which_nt) {
|
||||
jint ref_index = name_and_type_at(which_nt);
|
||||
return extract_high_short_from_int(ref_index);
|
||||
}
|
||||
|
||||
@ -353,20 +350,6 @@ char* constantPoolOopDesc::string_at_noresolve(int which) {
|
||||
}
|
||||
|
||||
|
||||
symbolOop constantPoolOopDesc::name_ref_at(int which) {
|
||||
jint ref_index = name_and_type_at(name_and_type_ref_index_at(which));
|
||||
int name_index = extract_low_short_from_int(ref_index);
|
||||
return symbol_at(name_index);
|
||||
}
|
||||
|
||||
|
||||
symbolOop constantPoolOopDesc::signature_ref_at(int which) {
|
||||
jint ref_index = name_and_type_at(name_and_type_ref_index_at(which));
|
||||
int signature_index = extract_high_short_from_int(ref_index);
|
||||
return symbol_at(signature_index);
|
||||
}
|
||||
|
||||
|
||||
BasicType constantPoolOopDesc::basic_type_for_signature_at(int which) {
|
||||
return FieldType::basic_type(symbol_at(which));
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ class constantPoolOopDesc : public oopDesc {
|
||||
void release_tag_at_put(int which, jbyte t) { tags()->release_byte_at_put(which, t); }
|
||||
|
||||
enum FlagBit {
|
||||
FB_has_invokedynamic = 1,
|
||||
FB_has_pseudo_string = 2
|
||||
};
|
||||
|
||||
@ -96,7 +97,9 @@ class constantPoolOopDesc : public oopDesc {
|
||||
typeArrayOop tags() const { return _tags; }
|
||||
|
||||
bool has_pseudo_string() const { return flag_at(FB_has_pseudo_string); }
|
||||
bool has_invokedynamic() const { return flag_at(FB_has_invokedynamic); }
|
||||
void set_pseudo_string() { set_flag_at(FB_has_pseudo_string); }
|
||||
void set_invokedynamic() { set_flag_at(FB_has_invokedynamic); }
|
||||
|
||||
// Klass holding pool
|
||||
klassOop pool_holder() const { return _pool_holder; }
|
||||
@ -338,24 +341,28 @@ class constantPoolOopDesc : public oopDesc {
|
||||
return *int_at_addr(which);
|
||||
}
|
||||
|
||||
// The following methods (klass_ref_at, klass_ref_at_noresolve, name_ref_at,
|
||||
// signature_ref_at, klass_ref_index_at, name_and_type_ref_index_at,
|
||||
// name_ref_index_at, signature_ref_index_at) all expect constant pool indices
|
||||
// The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve,
|
||||
// name_and_type_ref_index_at) all expect constant pool indices
|
||||
// from the bytecodes to be passed in, which are actually potentially byte-swapped
|
||||
// contstant pool cache indices. See field_or_method_at.
|
||||
// or rewritten constant pool cache indices. They all call map_instruction_operand_to_index.
|
||||
int map_instruction_operand_to_index(int operand);
|
||||
|
||||
// There are also "uncached" versions which do not map the operand index; see below.
|
||||
|
||||
// Lookup for entries consisting of (klass_index, name_and_type index)
|
||||
klassOop klass_ref_at(int which, TRAPS);
|
||||
symbolOop klass_ref_at_noresolve(int which);
|
||||
symbolOop name_ref_at(int which);
|
||||
symbolOop signature_ref_at(int which); // the type descriptor
|
||||
symbolOop name_ref_at(int which) { return impl_name_ref_at(which, false); }
|
||||
symbolOop signature_ref_at(int which) { return impl_signature_ref_at(which, false); }
|
||||
|
||||
int klass_ref_index_at(int which);
|
||||
int name_and_type_ref_index_at(int which);
|
||||
int klass_ref_index_at(int which) { return impl_klass_ref_index_at(which, false); }
|
||||
int name_and_type_ref_index_at(int which) { return impl_name_and_type_ref_index_at(which, false); }
|
||||
|
||||
// Lookup for entries consisting of (name_index, signature_index)
|
||||
int name_ref_index_at(int which);
|
||||
int signature_ref_index_at(int which);
|
||||
int name_ref_index_at(int which_nt); // == low-order jshort of name_and_type_at(which_nt)
|
||||
int signature_ref_index_at(int which_nt); // == high-order jshort of name_and_type_at(which_nt)
|
||||
symbolOop nt_name_ref_at(int which_nt) { return symbol_at(name_ref_index_at(which_nt)); }
|
||||
symbolOop nt_signature_ref_at(int which_nt) { return symbol_at(signature_ref_index_at(which_nt)); }
|
||||
|
||||
BasicType basic_type_for_signature_at(int which);
|
||||
|
||||
@ -397,10 +404,10 @@ class constantPoolOopDesc : public oopDesc {
|
||||
// Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
|
||||
// future by other Java code. These take constant pool indices rather than possibly-byte-swapped
|
||||
// constant pool cache indices as do the peer methods above.
|
||||
symbolOop uncached_name_ref_at(int which);
|
||||
symbolOop uncached_signature_ref_at(int which);
|
||||
int uncached_klass_ref_index_at(int which);
|
||||
int uncached_name_and_type_ref_index_at(int which);
|
||||
symbolOop uncached_name_ref_at(int which) { return impl_name_ref_at(which, true); }
|
||||
symbolOop uncached_signature_ref_at(int which) { return impl_signature_ref_at(which, true); }
|
||||
int uncached_klass_ref_index_at(int which) { return impl_klass_ref_index_at(which, true); }
|
||||
int uncached_name_and_type_ref_index_at(int which) { return impl_name_and_type_ref_index_at(which, true); }
|
||||
|
||||
// Sharing
|
||||
int pre_resolve_shared_klasses(TRAPS);
|
||||
@ -413,16 +420,19 @@ class constantPoolOopDesc : public oopDesc {
|
||||
|
||||
private:
|
||||
|
||||
symbolOop impl_name_ref_at(int which, bool uncached);
|
||||
symbolOop impl_signature_ref_at(int which, bool uncached);
|
||||
int impl_klass_ref_index_at(int which, bool uncached);
|
||||
int impl_name_and_type_ref_index_at(int which, bool uncached);
|
||||
|
||||
// Takes either a constant pool cache index in possibly byte-swapped
|
||||
// byte order (which comes from the bytecodes after rewriting) or,
|
||||
// if "uncached" is true, a vanilla constant pool index
|
||||
jint field_or_method_at(int which, bool uncached) {
|
||||
int i = -1;
|
||||
if (uncached || cache() == NULL) {
|
||||
i = which;
|
||||
} else {
|
||||
int i = which;
|
||||
if (!uncached && cache() != NULL) {
|
||||
// change byte-ordering and go via cache
|
||||
i = cache()->entry_at(Bytes::swap_u2(which))->constant_pool_index();
|
||||
i = map_instruction_operand_to_index(which);
|
||||
}
|
||||
assert(tag_at(i).is_field_or_method(), "Corrupted constant pool");
|
||||
return *int_at_addr(i);
|
||||
|
@ -169,11 +169,47 @@ bool constantPoolCacheKlass::oop_is_conc_safe(oop obj) const {
|
||||
void constantPoolCacheKlass::oop_copy_contents(PSPromotionManager* pm,
|
||||
oop obj) {
|
||||
assert(obj->is_constantPoolCache(), "should be constant pool");
|
||||
if (EnableInvokeDynamic) {
|
||||
constantPoolCacheOop cache = (constantPoolCacheOop)obj;
|
||||
// during a scavenge, it is safe to inspect my pool, since it is perm
|
||||
constantPoolOop pool = cache->constant_pool();
|
||||
assert(pool->is_constantPool(), "should be constant pool");
|
||||
if (pool->has_invokedynamic()) {
|
||||
for (int i = 0; i < cache->length(); i++) {
|
||||
ConstantPoolCacheEntry* e = cache->entry_at(i);
|
||||
oop* p = (oop*)&e->_f1;
|
||||
if (e->is_secondary_entry()) {
|
||||
if (PSScavenge::should_scavenge(p))
|
||||
pm->claim_or_forward_breadth(p);
|
||||
assert(!(e->is_vfinal() && PSScavenge::should_scavenge((oop*)&e->_f2)),
|
||||
"no live oops here");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void constantPoolCacheKlass::oop_push_contents(PSPromotionManager* pm,
|
||||
oop obj) {
|
||||
assert(obj->is_constantPoolCache(), "should be constant pool");
|
||||
if (EnableInvokeDynamic) {
|
||||
constantPoolCacheOop cache = (constantPoolCacheOop)obj;
|
||||
// during a scavenge, it is safe to inspect my pool, since it is perm
|
||||
constantPoolOop pool = cache->constant_pool();
|
||||
assert(pool->is_constantPool(), "should be constant pool");
|
||||
if (pool->has_invokedynamic()) {
|
||||
for (int i = 0; i < cache->length(); i++) {
|
||||
ConstantPoolCacheEntry* e = cache->entry_at(i);
|
||||
oop* p = (oop*)&e->_f1;
|
||||
if (e->is_secondary_entry()) {
|
||||
if (PSScavenge::should_scavenge(p))
|
||||
pm->claim_or_forward_depth(p);
|
||||
assert(!(e->is_vfinal() && PSScavenge::should_scavenge((oop*)&e->_f2)),
|
||||
"no live oops here");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -29,8 +29,18 @@
|
||||
// Implememtation of ConstantPoolCacheEntry
|
||||
|
||||
void ConstantPoolCacheEntry::set_initial_state(int index) {
|
||||
assert(0 <= index && index < 0x10000, "sanity check");
|
||||
if (constantPoolCacheOopDesc::is_secondary_index(index)) {
|
||||
// Hack: The rewriter is trying to say that this entry itself
|
||||
// will be a secondary entry.
|
||||
int main_index = constantPoolCacheOopDesc::decode_secondary_index(index);
|
||||
assert(0 <= main_index && main_index < 0x10000, "sanity check");
|
||||
_indices = (main_index << 16);
|
||||
assert(main_entry_index() == main_index, "");
|
||||
return;
|
||||
}
|
||||
assert(0 < index && index < 0x10000, "sanity check");
|
||||
_indices = index;
|
||||
assert(constant_pool_index() == index, "");
|
||||
}
|
||||
|
||||
|
||||
@ -136,6 +146,7 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code,
|
||||
int byte_no = -1;
|
||||
bool needs_vfinal_flag = false;
|
||||
switch (invoke_code) {
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokeinterface: {
|
||||
if (method->can_be_statically_bound()) {
|
||||
@ -211,6 +222,23 @@ void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index)
|
||||
}
|
||||
|
||||
|
||||
void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, int extra_data) {
|
||||
methodOop method = (methodOop) sun_dyn_CallSiteImpl::vmmethod(call_site());
|
||||
assert(method->is_method(), "must be initialized properly");
|
||||
int param_size = method->size_of_parameters();
|
||||
assert(param_size > 1, "method argument size must include MH.this & initial dynamic receiver");
|
||||
param_size -= 1; // do not count MH.this; it is not stacked for invokedynamic
|
||||
if (Atomic::cmpxchg_ptr(call_site(), &_f1, NULL) == NULL) {
|
||||
// racing threads might be trying to install their own favorites
|
||||
set_f1(call_site());
|
||||
}
|
||||
set_f2(extra_data);
|
||||
set_flags(as_flags(as_TosState(method->result_type()), method->is_final_method(), false, false, false, true) | param_size);
|
||||
// do not do set_bytecode on a secondary CP cache entry
|
||||
//set_bytecode_1(Bytecodes::_invokedynamic);
|
||||
}
|
||||
|
||||
|
||||
class LocalOopClosure: public OopClosure {
|
||||
private:
|
||||
void (*_f)(oop*);
|
||||
@ -392,7 +420,11 @@ void ConstantPoolCacheEntry::print(outputStream* st, int index) const {
|
||||
// print separator
|
||||
if (index == 0) tty->print_cr(" -------------");
|
||||
// print entry
|
||||
tty->print_cr("%3d (%08x) [%02x|%02x|%5d]", index, this, bytecode_2(), bytecode_1(), constant_pool_index());
|
||||
tty->print_cr("%3d (%08x) ", index, this);
|
||||
if (is_secondary_entry())
|
||||
tty->print_cr("[%5d|secondary]", main_entry_index());
|
||||
else
|
||||
tty->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index());
|
||||
tty->print_cr(" [ %08x]", (address)(oop)_f1);
|
||||
tty->print_cr(" [ %08x]", _f2);
|
||||
tty->print_cr(" [ %08x]", _flags);
|
||||
|
@ -89,6 +89,7 @@
|
||||
// _f1 = method for all but virtual calls, unused by virtual calls
|
||||
// (note: for interface calls, which are essentially virtual,
|
||||
// contains klassOop for the corresponding interface.
|
||||
// for invokedynamic, f1 contains the CallSite object for the invocation
|
||||
// _f2 = method/vtable index for virtual calls only, unused by all other
|
||||
// calls. The vf flag indicates this is a method pointer not an
|
||||
// index.
|
||||
@ -108,6 +109,8 @@
|
||||
|
||||
class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
||||
friend class VMStructs;
|
||||
friend class constantPoolCacheKlass;
|
||||
|
||||
private:
|
||||
volatile intx _indices; // constant pool index & rewrite bytecodes
|
||||
volatile oop _f1; // entry specific oop field
|
||||
@ -175,6 +178,11 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
||||
int index // Method index into interface
|
||||
);
|
||||
|
||||
void set_dynamic_call(
|
||||
Handle call_site, // Resolved java.dyn.CallSite (f1)
|
||||
int extra_data // (f2)
|
||||
);
|
||||
|
||||
void set_parameter_size(int value) {
|
||||
assert(parameter_size() == 0 || parameter_size() == value,
|
||||
"size must not change");
|
||||
@ -216,7 +224,11 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
|
||||
}
|
||||
|
||||
// Accessors
|
||||
int constant_pool_index() const { return _indices & 0xFFFF; }
|
||||
bool is_secondary_entry() const { return (_indices & 0xFFFF) == 0; }
|
||||
int constant_pool_index() const { assert((_indices & 0xFFFF) != 0, "must be main entry");
|
||||
return (_indices & 0xFFFF); }
|
||||
int main_entry_index() const { assert((_indices & 0xFFFF) == 0, "must be secondary entry");
|
||||
return ((uintx)_indices >> 16); }
|
||||
Bytecodes::Code bytecode_1() const { return Bytecodes::cast((_indices >> 16) & 0xFF); }
|
||||
Bytecodes::Code bytecode_2() const { return Bytecodes::cast((_indices >> 24) & 0xFF); }
|
||||
volatile oop f1() const { return _f1; }
|
||||
@ -314,10 +326,30 @@ class constantPoolCacheOopDesc: public oopDesc {
|
||||
// Initialization
|
||||
void initialize(intArray& inverse_index_map);
|
||||
|
||||
// Secondary indexes.
|
||||
// They must look completely different from normal indexes.
|
||||
// The main reason is that byte swapping is sometimes done on normal indexes.
|
||||
// Also, it is helpful for debugging to tell the two apart.
|
||||
static bool is_secondary_index(int i) { return (i < 0); }
|
||||
static int decode_secondary_index(int i) { assert(is_secondary_index(i), ""); return ~i; }
|
||||
static int encode_secondary_index(int i) { assert(!is_secondary_index(i), ""); return ~i; }
|
||||
|
||||
// Accessors
|
||||
void set_constant_pool(constantPoolOop pool) { oop_store_without_check((oop*)&_constant_pool, (oop)pool); }
|
||||
constantPoolOop constant_pool() const { return _constant_pool; }
|
||||
ConstantPoolCacheEntry* entry_at(int i) const { assert(0 <= i && i < length(), "index out of bounds"); return base() + i; }
|
||||
ConstantPoolCacheEntry* main_entry_at(int i) const {
|
||||
ConstantPoolCacheEntry* e;
|
||||
if (is_secondary_index(i)) {
|
||||
// run through an extra level of indirection:
|
||||
i = decode_secondary_index(i);
|
||||
e = entry_at(i);
|
||||
i = e->main_entry_index();
|
||||
}
|
||||
e = entry_at(i);
|
||||
assert(!e->is_secondary_entry(), "only one level of indirection");
|
||||
return e;
|
||||
}
|
||||
|
||||
// GC support
|
||||
// If the _length field has not been set, the size of the
|
||||
|
@ -1252,8 +1252,9 @@ void GenerateOopMap::print_current_state(outputStream *os,
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokestatic:
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_invokeinterface:
|
||||
int idx = currentBC->get_index_big();
|
||||
int idx = currentBC->get_index_int();
|
||||
constantPoolOop cp = method()->constants();
|
||||
int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx);
|
||||
int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx);
|
||||
@ -1283,8 +1284,9 @@ void GenerateOopMap::print_current_state(outputStream *os,
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokestatic:
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_invokeinterface:
|
||||
int idx = currentBC->get_index_big();
|
||||
int idx = currentBC->get_index_int();
|
||||
constantPoolOop cp = method()->constants();
|
||||
int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx);
|
||||
int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx);
|
||||
@ -1310,6 +1312,7 @@ void GenerateOopMap::interp1(BytecodeStream *itr) {
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokestatic:
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_invokeinterface:
|
||||
_itr_send = itr;
|
||||
_report_result_for_send = true;
|
||||
@ -1556,6 +1559,7 @@ void GenerateOopMap::interp1(BytecodeStream *itr) {
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokespecial: do_method(false, false, itr->get_index_big(), itr->bci()); break;
|
||||
case Bytecodes::_invokestatic: do_method(true, false, itr->get_index_big(), itr->bci()); break;
|
||||
case Bytecodes::_invokedynamic: do_method(false, true, itr->get_index_int(), itr->bci()); break;
|
||||
case Bytecodes::_invokeinterface: do_method(false, true, itr->get_index_big(), itr->bci()); break;
|
||||
case Bytecodes::_newarray:
|
||||
case Bytecodes::_anewarray: pp_new_ref(vCTS, itr->bci()); break;
|
||||
@ -1899,7 +1903,7 @@ void GenerateOopMap::do_method(int is_static, int is_interface, int idx, int bci
|
||||
// Dig up signature for field in constant pool
|
||||
constantPoolOop cp = _method->constants();
|
||||
int nameAndTypeIdx = cp->name_and_type_ref_index_at(idx);
|
||||
int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx);
|
||||
int signatureIdx = cp->signature_ref_index_at(nameAndTypeIdx); // @@@@@
|
||||
symbolOop signature = cp->symbol_at(signatureIdx);
|
||||
|
||||
// Parse method signature
|
||||
|
@ -163,6 +163,8 @@ class instanceKlass: public Klass {
|
||||
klassOop _implementors[implementors_limit];
|
||||
// Generic signature, or null if none.
|
||||
symbolOop _generic_signature;
|
||||
// invokedynamic bootstrap method (a java.dyn.MethodHandle)
|
||||
oop _bootstrap_method;
|
||||
// Annotations for this class, or null if none.
|
||||
typeArrayOop _class_annotations;
|
||||
// Annotation objects (byte arrays) for fields, or null if no annotations.
|
||||
@ -464,6 +466,10 @@ class instanceKlass: public Klass {
|
||||
u2 method_index) { _enclosing_method_class_index = class_index;
|
||||
_enclosing_method_method_index = method_index; }
|
||||
|
||||
// JSR 292 support
|
||||
oop bootstrap_method() const { return _bootstrap_method; }
|
||||
void set_bootstrap_method(oop mh) { oop_store(&_bootstrap_method, mh); }
|
||||
|
||||
// jmethodID support
|
||||
static jmethodID get_jmethod_id(instanceKlassHandle ik_h, size_t idnum,
|
||||
jmethodID new_id, jmethodID* new_jmeths);
|
||||
@ -744,6 +750,7 @@ private:
|
||||
oop* adr_inner_classes() const { return (oop*)&this->_inner_classes;}
|
||||
oop* adr_implementors() const { return (oop*)&this->_implementors[0];}
|
||||
oop* adr_generic_signature() const { return (oop*)&this->_generic_signature;}
|
||||
oop* adr_bootstrap_method() const { return (oop*)&this->_bootstrap_method;}
|
||||
oop* adr_methods_jmethod_ids() const { return (oop*)&this->_methods_jmethod_ids;}
|
||||
oop* adr_methods_cached_itable_indices() const { return (oop*)&this->_methods_cached_itable_indices;}
|
||||
oop* adr_class_annotations() const { return (oop*)&this->_class_annotations;}
|
||||
|
@ -84,6 +84,7 @@ void instanceKlassKlass::oop_follow_contents(oop obj) {
|
||||
MarkSweep::mark_and_push(ik->adr_host_klass());
|
||||
MarkSweep::mark_and_push(ik->adr_signers());
|
||||
MarkSweep::mark_and_push(ik->adr_generic_signature());
|
||||
MarkSweep::mark_and_push(ik->adr_bootstrap_method());
|
||||
MarkSweep::mark_and_push(ik->adr_class_annotations());
|
||||
MarkSweep::mark_and_push(ik->adr_fields_annotations());
|
||||
MarkSweep::mark_and_push(ik->adr_methods_annotations());
|
||||
@ -124,6 +125,7 @@ void instanceKlassKlass::oop_follow_contents(ParCompactionManager* cm,
|
||||
PSParallelCompact::mark_and_push(cm, ik->adr_host_klass());
|
||||
PSParallelCompact::mark_and_push(cm, ik->adr_signers());
|
||||
PSParallelCompact::mark_and_push(cm, ik->adr_generic_signature());
|
||||
PSParallelCompact::mark_and_push(cm, ik->adr_bootstrap_method());
|
||||
PSParallelCompact::mark_and_push(cm, ik->adr_class_annotations());
|
||||
PSParallelCompact::mark_and_push(cm, ik->adr_fields_annotations());
|
||||
PSParallelCompact::mark_and_push(cm, ik->adr_methods_annotations());
|
||||
@ -170,6 +172,7 @@ int instanceKlassKlass::oop_oop_iterate(oop obj, OopClosure* blk) {
|
||||
blk->do_oop(&ik->adr_implementors()[i]);
|
||||
}
|
||||
blk->do_oop(ik->adr_generic_signature());
|
||||
blk->do_oop(ik->adr_bootstrap_method());
|
||||
blk->do_oop(ik->adr_class_annotations());
|
||||
blk->do_oop(ik->adr_fields_annotations());
|
||||
blk->do_oop(ik->adr_methods_annotations());
|
||||
@ -230,6 +233,8 @@ int instanceKlassKlass::oop_oop_iterate_m(oop obj, OopClosure* blk,
|
||||
}
|
||||
adr = ik->adr_generic_signature();
|
||||
if (mr.contains(adr)) blk->do_oop(adr);
|
||||
adr = ik->adr_bootstrap_method();
|
||||
if (mr.contains(adr)) blk->do_oop(adr);
|
||||
adr = ik->adr_class_annotations();
|
||||
if (mr.contains(adr)) blk->do_oop(adr);
|
||||
adr = ik->adr_fields_annotations();
|
||||
@ -274,6 +279,7 @@ int instanceKlassKlass::oop_adjust_pointers(oop obj) {
|
||||
MarkSweep::adjust_pointer(&ik->adr_implementors()[i]);
|
||||
}
|
||||
MarkSweep::adjust_pointer(ik->adr_generic_signature());
|
||||
MarkSweep::adjust_pointer(ik->adr_bootstrap_method());
|
||||
MarkSweep::adjust_pointer(ik->adr_class_annotations());
|
||||
MarkSweep::adjust_pointer(ik->adr_fields_annotations());
|
||||
MarkSweep::adjust_pointer(ik->adr_methods_annotations());
|
||||
@ -454,6 +460,7 @@ klassOop instanceKlassKlass::allocate_instance_klass(int vtable_len, int itable_
|
||||
ik->set_breakpoints(NULL);
|
||||
ik->init_previous_versions();
|
||||
ik->set_generic_signature(NULL);
|
||||
ik->set_bootstrap_method(NULL);
|
||||
ik->release_set_methods_jmethod_ids(NULL);
|
||||
ik->release_set_methods_cached_itable_indices(NULL);
|
||||
ik->set_class_annotations(NULL);
|
||||
@ -578,6 +585,11 @@ void instanceKlassKlass::oop_print_on(oop obj, outputStream* st) {
|
||||
} // pvw is cleaned up
|
||||
} // rm is cleaned up
|
||||
|
||||
if (ik->bootstrap_method() != NULL) {
|
||||
st->print(BULLET"bootstrap method: ");
|
||||
ik->bootstrap_method()->print_value_on(st);
|
||||
st->cr();
|
||||
}
|
||||
if (ik->generic_signature() != NULL) {
|
||||
st->print(BULLET"generic signature: ");
|
||||
ik->generic_signature()->print_value_on(st);
|
||||
|
@ -442,6 +442,8 @@ int methodDataOopDesc::bytecode_cell_count(Bytecodes::Code code) {
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokeinterface:
|
||||
return VirtualCallData::static_cell_count();
|
||||
case Bytecodes::_invokedynamic:
|
||||
return CounterData::static_cell_count();
|
||||
case Bytecodes::_ret:
|
||||
return RetData::static_cell_count();
|
||||
case Bytecodes::_ifeq:
|
||||
@ -570,6 +572,11 @@ int methodDataOopDesc::initialize_data(BytecodeStream* stream,
|
||||
cell_count = VirtualCallData::static_cell_count();
|
||||
tag = DataLayout::virtual_call_data_tag;
|
||||
break;
|
||||
case Bytecodes::_invokedynamic:
|
||||
// %%% should make a type profile for any invokedynamic that takes a ref argument
|
||||
cell_count = CounterData::static_cell_count();
|
||||
tag = DataLayout::counter_data_tag;
|
||||
break;
|
||||
case Bytecodes::_ret:
|
||||
cell_count = RetData::static_cell_count();
|
||||
tag = DataLayout::ret_data_tag;
|
||||
|
@ -161,7 +161,7 @@ void methodOopDesc::mask_for(int bci, InterpreterOopMap* mask) {
|
||||
|
||||
|
||||
int methodOopDesc::bci_from(address bcp) const {
|
||||
assert(is_native() && bcp == code_base() || contains(bcp), "bcp doesn't belong to this method");
|
||||
assert(is_native() && bcp == code_base() || contains(bcp) || is_error_reported(), "bcp doesn't belong to this method");
|
||||
return bcp - code_base();
|
||||
}
|
||||
|
||||
|
@ -534,7 +534,10 @@ class methodOopDesc : public oopDesc {
|
||||
oop method_handle_type() const;
|
||||
static jint* method_type_offsets_chain(); // series of pointer-offsets, terminated by -1
|
||||
// presize interpreter frames for extra interpreter stack entries, if needed
|
||||
static int extra_stack_entries() { return EnableMethodHandles ? (int)MethodHandlePushLimit : 0; }
|
||||
// method handles want to be able to push a few extra values (e.g., a bound receiver), and
|
||||
// invokedynamic sometimes needs to push a bootstrap method, call site, and arglist,
|
||||
// all without checking for a stack overflow
|
||||
static int extra_stack_entries() { return (EnableMethodHandles ? (int)MethodHandlePushLimit : 0) + (EnableInvokeDynamic ? 3 : 0); }
|
||||
static int extra_stack_words(); // = extra_stack_entries() * Interpreter::stackElementSize()
|
||||
// RedefineClasses() support:
|
||||
bool is_old() const { return access_flags().is_old(); }
|
||||
|
@ -363,6 +363,20 @@ OopMap *OopFlow::build_oop_map( Node *n, int max_reg, PhaseRegAlloc *regalloc, i
|
||||
*/
|
||||
#endif
|
||||
|
||||
#ifdef ASSERT
|
||||
for( OopMapStream oms1(omap, OopMapValue::derived_oop_value); !oms1.is_done(); oms1.next()) {
|
||||
OopMapValue omv1 = oms1.current();
|
||||
bool found = false;
|
||||
for( OopMapStream oms2(omap,OopMapValue::oop_value); !oms2.is_done(); oms2.next()) {
|
||||
if( omv1.content_reg() == oms2.current().reg() ) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert( found, "derived with no base in oopmap" );
|
||||
}
|
||||
#endif
|
||||
|
||||
return omap;
|
||||
}
|
||||
|
||||
|
@ -321,7 +321,7 @@ bool pass_initial_checks(ciMethod* caller_method, int caller_bci, ciMethod* call
|
||||
// stricter than callee_holder->is_initialized()
|
||||
ciBytecodeStream iter(caller_method);
|
||||
iter.force_bci(caller_bci);
|
||||
int index = iter.get_index_big();
|
||||
int index = iter.get_index_int();
|
||||
if( !caller_method->is_klass_loaded(index, true) ) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1423,17 +1423,33 @@ Node *PhaseChaitin::find_base_for_derived( Node **derived_base_map, Node *derive
|
||||
// pointers derived from NULL! These are always along paths that
|
||||
// can't happen at run-time but the optimizer cannot deduce it so
|
||||
// we have to handle it gracefully.
|
||||
assert(!derived->bottom_type()->isa_narrowoop() ||
|
||||
derived->bottom_type()->make_ptr()->is_ptr()->_offset == 0, "sanity");
|
||||
const TypePtr *tj = derived->bottom_type()->isa_ptr();
|
||||
// If its an OOP with a non-zero offset, then it is derived.
|
||||
if( tj->_offset == 0 ) {
|
||||
if( tj == NULL || tj->_offset == 0 ) {
|
||||
derived_base_map[derived->_idx] = derived;
|
||||
return derived;
|
||||
}
|
||||
// Derived is NULL+offset? Base is NULL!
|
||||
if( derived->is_Con() ) {
|
||||
Node *base = new (C, 1) ConPNode( TypePtr::NULL_PTR );
|
||||
uint no_lidx = 0; // an unmatched constant in debug info has no LRG
|
||||
_names.extend(base->_idx, no_lidx);
|
||||
Node *base = _matcher.mach_null();
|
||||
assert(base != NULL, "sanity");
|
||||
if (base->in(0) == NULL) {
|
||||
// Initialize it once and make it shared:
|
||||
// set control to _root and place it into Start block
|
||||
// (where top() node is placed).
|
||||
base->init_req(0, _cfg._root);
|
||||
Block *startb = _cfg._bbs[C->top()->_idx];
|
||||
startb->_nodes.insert(startb->find_node(C->top()), base );
|
||||
_cfg._bbs.map( base->_idx, startb );
|
||||
assert (n2lidx(base) == 0, "should not have LRG yet");
|
||||
}
|
||||
if (n2lidx(base) == 0) {
|
||||
new_lrg(base, maxlrg++);
|
||||
}
|
||||
assert(base->in(0) == _cfg._root &&
|
||||
_cfg._bbs[base->_idx] == _cfg._bbs[C->top()->_idx], "base NULL should be shared");
|
||||
derived_base_map[derived->_idx] = base;
|
||||
return base;
|
||||
}
|
||||
@ -1460,9 +1476,13 @@ Node *PhaseChaitin::find_base_for_derived( Node **derived_base_map, Node *derive
|
||||
}
|
||||
|
||||
// Now we see we need a base-Phi here to merge the bases
|
||||
base = new (C, derived->req()) PhiNode( derived->in(0), base->bottom_type() );
|
||||
for( i = 1; i < derived->req(); i++ )
|
||||
const Type *t = base->bottom_type();
|
||||
base = new (C, derived->req()) PhiNode( derived->in(0), t );
|
||||
for( i = 1; i < derived->req(); i++ ) {
|
||||
base->init_req(i, find_base_for_derived(derived_base_map, derived->in(i), maxlrg));
|
||||
t = t->meet(base->in(i)->bottom_type());
|
||||
}
|
||||
base->as_Phi()->set_type(t);
|
||||
|
||||
// Search the current block for an existing base-Phi
|
||||
Block *b = _cfg._bbs[derived->_idx];
|
||||
@ -1560,6 +1580,8 @@ bool PhaseChaitin::stretch_base_pointer_live_ranges( ResourceArea *a ) {
|
||||
// This works because we are still in SSA during this call.
|
||||
Node *derived = lrgs(neighbor)._def;
|
||||
const TypePtr *tj = derived->bottom_type()->isa_ptr();
|
||||
assert(!derived->bottom_type()->isa_narrowoop() ||
|
||||
derived->bottom_type()->make_ptr()->is_ptr()->_offset == 0, "sanity");
|
||||
// If its an OOP with a non-zero offset, then it is derived.
|
||||
if( tj && tj->_offset != 0 && tj->isa_oop_ptr() ) {
|
||||
Node *base = find_base_for_derived( derived_base_map, derived, maxlrg );
|
||||
|
@ -248,6 +248,14 @@ bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* kl
|
||||
holder_klass);
|
||||
return true;
|
||||
}
|
||||
if (dest_method->is_method_handle_invoke()
|
||||
&& holder_klass->name() == ciSymbol::java_dyn_Dynamic()) {
|
||||
// FIXME: NYI
|
||||
uncommon_trap(Deoptimization::Reason_unhandled,
|
||||
Deoptimization::Action_none,
|
||||
holder_klass);
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(dest_method->will_link(method()->holder(), klass, bc()), "dest_method: typeflow responsibility");
|
||||
return false;
|
||||
@ -748,6 +756,7 @@ void Parse::count_compiled_calls(bool at_method_entry, bool is_inline) {
|
||||
case Bytecodes::_invokevirtual: increment_counter(SharedRuntime::nof_inlined_calls_addr()); break;
|
||||
case Bytecodes::_invokeinterface: increment_counter(SharedRuntime::nof_inlined_interface_calls_addr()); break;
|
||||
case Bytecodes::_invokestatic:
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_invokespecial: increment_counter(SharedRuntime::nof_inlined_static_calls_addr()); break;
|
||||
default: fatal("unexpected call bytecode");
|
||||
}
|
||||
@ -756,6 +765,7 @@ void Parse::count_compiled_calls(bool at_method_entry, bool is_inline) {
|
||||
case Bytecodes::_invokevirtual: increment_counter(SharedRuntime::nof_normal_calls_addr()); break;
|
||||
case Bytecodes::_invokeinterface: increment_counter(SharedRuntime::nof_interface_calls_addr()); break;
|
||||
case Bytecodes::_invokestatic:
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_invokespecial: increment_counter(SharedRuntime::nof_static_calls_addr()); break;
|
||||
default: fatal("unexpected call bytecode");
|
||||
}
|
||||
|
@ -947,6 +947,7 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth) {
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokestatic:
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_invokeinterface:
|
||||
{
|
||||
bool is_static = (depth == 0);
|
||||
@ -2979,6 +2980,7 @@ Node* GraphKit::new_instance(Node* klass_node,
|
||||
// See comments on new_instance for the meaning of the other arguments.
|
||||
Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
|
||||
Node* length, // number of array elements
|
||||
int nargs, // number of arguments to push back for uncommon trap
|
||||
bool raw_mem_only, // affect only raw memory
|
||||
Node* *return_size_val) {
|
||||
jint layout_con = Klass::_lh_neutral_value;
|
||||
@ -2994,6 +2996,7 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable)
|
||||
Node* cmp_lh = _gvn.transform( new(C, 3) CmpINode(layout_val, intcon(layout_con)) );
|
||||
Node* bol_lh = _gvn.transform( new(C, 2) BoolNode(cmp_lh, BoolTest::eq) );
|
||||
{ BuildCutout unless(this, bol_lh, PROB_MAX);
|
||||
_sp += nargs;
|
||||
uncommon_trap(Deoptimization::Reason_class_check,
|
||||
Deoptimization::Action_maybe_recompile);
|
||||
}
|
||||
|
@ -699,7 +699,7 @@ class GraphKit : public Phase {
|
||||
Node* slow_test = NULL,
|
||||
bool raw_mem_only = false,
|
||||
Node* *return_size_val = NULL);
|
||||
Node* new_array(Node* klass_node, Node* count_val,
|
||||
Node* new_array(Node* klass_node, Node* count_val, int nargs,
|
||||
bool raw_mem_only = false, Node* *return_size_val = NULL);
|
||||
|
||||
// Handy for making control flow
|
||||
|
@ -3055,9 +3055,7 @@ bool LibraryCallKit::inline_native_newArray() {
|
||||
// Normal case: The array type has been cached in the java.lang.Class.
|
||||
// The following call works fine even if the array type is polymorphic.
|
||||
// It could be a dynamic mix of int[], boolean[], Object[], etc.
|
||||
_sp += nargs; // set original stack for use by uncommon_trap
|
||||
Node* obj = new_array(klass_node, count_val);
|
||||
_sp -= nargs;
|
||||
Node* obj = new_array(klass_node, count_val, nargs);
|
||||
result_reg->init_req(_normal_path, control());
|
||||
result_val->init_req(_normal_path, obj);
|
||||
result_io ->init_req(_normal_path, i_o());
|
||||
@ -3179,9 +3177,7 @@ bool LibraryCallKit::inline_array_copyOf(bool is_copyOfRange) {
|
||||
Node* orig_tail = _gvn.transform( new(C, 3) SubINode(orig_length, start) );
|
||||
Node* moved = generate_min_max(vmIntrinsics::_min, orig_tail, length);
|
||||
|
||||
_sp += nargs; // set original stack for use by uncommon_trap
|
||||
Node* newcopy = new_array(klass_node, length);
|
||||
_sp -= nargs;
|
||||
Node* newcopy = new_array(klass_node, length, nargs);
|
||||
|
||||
// Generate a direct call to the right arraycopy function(s).
|
||||
// We know the copy is disjoint but we might not know if the
|
||||
@ -3903,10 +3899,8 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
|
||||
set_control(array_ctl);
|
||||
Node* obj_length = load_array_length(obj);
|
||||
Node* obj_size = NULL;
|
||||
_sp += nargs; // set original stack for use by uncommon_trap
|
||||
Node* alloc_obj = new_array(obj_klass, obj_length,
|
||||
Node* alloc_obj = new_array(obj_klass, obj_length, nargs,
|
||||
raw_mem_only, &obj_size);
|
||||
_sp -= nargs;
|
||||
assert(obj_size != NULL, "");
|
||||
Node* raw_obj = alloc_obj->in(1);
|
||||
assert(raw_obj->is_Proj() && raw_obj->in(0)->is_Allocate(), "");
|
||||
|
@ -275,6 +275,12 @@ void Matcher::match( ) {
|
||||
|
||||
C->print_method("Before Matching");
|
||||
|
||||
// Create new ideal node ConP #NULL even if it does exist in old space
|
||||
// to avoid false sharing if the corresponding mach node is not used.
|
||||
// The corresponding mach node is only used in rare cases for derived
|
||||
// pointers.
|
||||
Node* new_ideal_null = ConNode::make(C, TypePtr::NULL_PTR);
|
||||
|
||||
// Swap out to old-space; emptying new-space
|
||||
Arena *old = C->node_arena()->move_contents(C->old_arena());
|
||||
|
||||
@ -316,7 +322,16 @@ void Matcher::match( ) {
|
||||
}
|
||||
}
|
||||
|
||||
// Generate new mach node for ConP #NULL
|
||||
assert(new_ideal_null != NULL, "sanity");
|
||||
_mach_null = match_tree(new_ideal_null);
|
||||
// Don't set control, it will confuse GCM since there are no uses.
|
||||
// The control will be set when this node is used first time
|
||||
// in find_base_for_derived().
|
||||
assert(_mach_null != NULL, "");
|
||||
|
||||
C->set_root(xroot->is_Root() ? xroot->as_Root() : NULL);
|
||||
|
||||
#ifdef ASSERT
|
||||
verify_new_nodes_only(xroot);
|
||||
#endif
|
||||
|
@ -109,6 +109,9 @@ class Matcher : public PhaseTransform {
|
||||
Node* _mem_node; // Ideal memory node consumed by mach node
|
||||
#endif
|
||||
|
||||
// Mach node for ConP #NULL
|
||||
MachNode* _mach_null;
|
||||
|
||||
public:
|
||||
int LabelRootDepth;
|
||||
static const int base2reg[]; // Map Types to machine register types
|
||||
@ -122,6 +125,8 @@ public:
|
||||
static RegMask mreg2regmask[];
|
||||
static RegMask STACK_ONLY_mask;
|
||||
|
||||
MachNode* mach_null() const { return _mach_null; }
|
||||
|
||||
bool is_shared( Node *n ) { return _shared.test(n->_idx) != 0; }
|
||||
void set_shared( Node *n ) { _shared.set(n->_idx); }
|
||||
bool is_visited( Node *n ) { return _visited.test(n->_idx) != 0; }
|
||||
|
@ -476,7 +476,7 @@ class Parse : public GraphKit {
|
||||
void do_newarray(BasicType elemtype);
|
||||
void do_anewarray();
|
||||
void do_multianewarray();
|
||||
Node* expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, int ndimensions);
|
||||
Node* expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, int ndimensions, int nargs);
|
||||
|
||||
// implementation of jsr/ret
|
||||
void do_jsr();
|
||||
|
@ -828,6 +828,7 @@ bool Parse::can_rerun_bytecode() {
|
||||
break;
|
||||
|
||||
case Bytecodes::_invokestatic:
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokeinterface:
|
||||
|
@ -2156,6 +2156,7 @@ void Parse::do_one_bytecode() {
|
||||
break;
|
||||
|
||||
case Bytecodes::_invokestatic:
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_invokespecial:
|
||||
case Bytecodes::_invokevirtual:
|
||||
case Bytecodes::_invokeinterface:
|
||||
|
@ -335,7 +335,7 @@ void Parse::do_anewarray() {
|
||||
|
||||
const TypeKlassPtr* array_klass_type = TypeKlassPtr::make(array_klass);
|
||||
Node* count_val = pop();
|
||||
Node* obj = new_array(makecon(array_klass_type), count_val);
|
||||
Node* obj = new_array(makecon(array_klass_type), count_val, 1);
|
||||
push(obj);
|
||||
}
|
||||
|
||||
@ -345,17 +345,17 @@ void Parse::do_newarray(BasicType elem_type) {
|
||||
|
||||
Node* count_val = pop();
|
||||
const TypeKlassPtr* array_klass = TypeKlassPtr::make(ciTypeArrayKlass::make(elem_type));
|
||||
Node* obj = new_array(makecon(array_klass), count_val);
|
||||
Node* obj = new_array(makecon(array_klass), count_val, 1);
|
||||
// Push resultant oop onto stack
|
||||
push(obj);
|
||||
}
|
||||
|
||||
// Expand simple expressions like new int[3][5] and new Object[2][nonConLen].
|
||||
// Also handle the degenerate 1-dimensional case of anewarray.
|
||||
Node* Parse::expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, int ndimensions) {
|
||||
Node* Parse::expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, int ndimensions, int nargs) {
|
||||
Node* length = lengths[0];
|
||||
assert(length != NULL, "");
|
||||
Node* array = new_array(makecon(TypeKlassPtr::make(array_klass)), length);
|
||||
Node* array = new_array(makecon(TypeKlassPtr::make(array_klass)), length, nargs);
|
||||
if (ndimensions > 1) {
|
||||
jint length_con = find_int_con(length, -1);
|
||||
guarantee(length_con >= 0, "non-constant multianewarray");
|
||||
@ -364,7 +364,7 @@ Node* Parse::expand_multianewarray(ciArrayKlass* array_klass, Node* *lengths, in
|
||||
const Type* elemtype = _gvn.type(array)->is_aryptr()->elem();
|
||||
const intptr_t header = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
|
||||
for (jint i = 0; i < length_con; i++) {
|
||||
Node* elem = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1);
|
||||
Node* elem = expand_multianewarray(array_klass_1, &lengths[1], ndimensions-1, nargs);
|
||||
intptr_t offset = header + ((intptr_t)i << LogBytesPerHeapOop);
|
||||
Node* eaddr = basic_plus_adr(array, offset);
|
||||
store_oop_to_array(control(), array, eaddr, adr_type, elem, elemtype, T_OBJECT);
|
||||
@ -419,7 +419,7 @@ void Parse::do_multianewarray() {
|
||||
// Can use multianewarray instead of [a]newarray if only one dimension,
|
||||
// or if all non-final dimensions are small constants.
|
||||
if (expand_count == 1 || (1 <= expand_count && expand_count <= expand_limit)) {
|
||||
Node* obj = expand_multianewarray(array_klass, &length[0], ndimensions);
|
||||
Node* obj = expand_multianewarray(array_klass, &length[0], ndimensions, ndimensions);
|
||||
push(obj);
|
||||
return;
|
||||
}
|
||||
|
@ -414,6 +414,7 @@ void Parse::profile_call(Node* receiver) {
|
||||
profile_receiver_type(receiver);
|
||||
break;
|
||||
case Bytecodes::_invokestatic:
|
||||
case Bytecodes::_invokedynamic:
|
||||
case Bytecodes::_invokespecial:
|
||||
break;
|
||||
default: fatal("unexpected call bytecode");
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user