--- a/hotspot/.hgignore Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/.hgignore Wed Apr 29 13:22:09 2009 -0700
@@ -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/
--- a/hotspot/make/jprt.properties Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/make/jprt.properties Wed Apr 29 13:22:09 2009 -0700
@@ -46,24 +46,28 @@
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
--- a/hotspot/make/solaris/makefiles/sparcWorks.make Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/make/solaris/makefiles/sparcWorks.make Wed Apr 29 13:22:09 2009 -0700
@@ -46,7 +46,7 @@
$(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 @@
# 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
--- a/hotspot/make/windows/makefiles/vm.make Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/make/windows/makefiles/vm.make Wed Apr 29 13:22:09 2009 -0700
@@ -55,10 +55,16 @@
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)\""
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
}
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
// %%% 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 @@
#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 @@
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::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_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 @@
// 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 @@
#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);
+ assert(tmp != obj, "need separate temp reg");
+ set((address) byte_map_base, tmp);
+ stb(G0, tmp, 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 );
-}
-
-
-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 @@
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);
+}
+
+void MacroAssembler::set(intptr_t value, Register d) {
+ AddressLiteral al(value);
+ internal_set(al, d, false);
}
-// %%% End of moved six set instructions.
+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 @@
}
-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 @@
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 @@
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 @@
{ // 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
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 @@
// 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 @@
// 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_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 @@
// 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 @@
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 @@
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 @@
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 @@
#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 @@
#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 @@
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::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::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);
}
}
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -274,21 +274,90 @@
class Address VALUE_OBJ_CLASS_SPEC {
private:
- Register _base;
-#ifdef _LP64
- int _hi32; // bits 63::32
- int _low32; // bits 31::0
+ Register _base; // Base register.
+ RegisterOrConstant _index_or_disp; // Index register or constant displacement.
+ RelocationHolder _rspec;
+
+ 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
- int _hi;
- int _disp;
- RelocationHolder _rspec;
-
- RelocationHolder rspec_from_rtype(relocInfo::relocType rt, address a = NULL) {
- switch (rt) {
+
+ // 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 @@
}
}
+ 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;
-#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 in low word
- _disp = (intptr_t)a & 0x3ff; // bottom 10 bits
- }
-
- Address(Register b, address a, RelocationHolder const& rspec)
- : _rspec(rspec)
- {
- _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
-#endif
- _hi = (intptr_t)a & ~0x3ff; // top 22 bits
- _disp = (intptr_t)a & 0x3ff; // bottom 10 bits
- }
-
- 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;
+ // 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
- }
-
- Address()
- : _rspec(RelocationHolder())
- {
- _base = G0;
-#ifdef _LP64
- _hi32 = 0;
- _low32 = 0;
-#endif
- _hi = 0;
- _disp = 0;
- }
-
- // fancier constructors
-
- enum addr_type {
- extra_in_argument, // in the In registers
- extra_out_argument // in the Outs
- };
-
- 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 {
+
+ AddressLiteral(oop addr, relocInfo::relocType rtype = relocInfo::none)
+ : _address((address) addr),
+ _rspec(rspec_from_rtype(rtype, (address) addr)) {}
+
+ AddressLiteral(float* addr, relocInfo::relocType rtype = relocInfo::none)
+ : _address((address) addr),
+ _rspec(rspec_from_rtype(rtype, (address) addr)) {}
+
+ AddressLiteral(double* addr, relocInfo::relocType rtype = relocInfo::none)
+ : _address((address) addr),
+ _rspec(rspec_from_rtype(rtype, (address) addr)) {}
+
+ intptr_t value() const { return (intptr_t) _address; }
+ int low10() const;
+
+ const relocInfo::relocType rtype() const { return _rspec.type(); }
+ const RelocationHolder& rspec() const { 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 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 @@
// 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 @@
friend class AbstractAssembler;
+ friend class AddressLiteral;
// code patchers need various routines like inv_wdisp()
friend class NativeInstruction;
@@ -1093,11 +1118,11 @@
// 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 @@
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, const Address& a, FloatRegister d, int offset = 0);
+ 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 ldfsr( Register s1, Register s2 );
@@ -1303,15 +1326,20 @@
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 @@
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 @@
#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 @@
#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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
// 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
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -38,6 +38,11 @@
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::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::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,49 +137,68 @@
#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
+
+#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::ldub( 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::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::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::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::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::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::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::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::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::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::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( 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::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) {
@@ -187,17 +207,6 @@
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::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); }
+
+#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, Register s1, RegisterOrConstant s2) {
- if (s2.is_register()) stb(d, s1, s2.as_register());
- else stb(d, s1, s2.as_constant());
+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::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::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::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::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::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 @@
// 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, 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 @@
#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 @@
#ifdef _LP64
Assembler::sllx(s1, s2, d);
#else
- Assembler::sll(s1, s2, d);
+ Assembler::sll( s1, s2, d);
#endif
}
@@ -435,7 +466,7 @@
#ifdef _LP64
Assembler::sllx(s1, imm6a, d);
#else
- Assembler::sll(s1, imm6a, d);
+ Assembler::sll( s1, imm6a, d);
#endif
}
@@ -443,7 +474,7 @@
#ifdef _LP64
Assembler::srlx(s1, s2, d);
#else
- Assembler::srl(s1, s2, d);
+ Assembler::srl( s1, s2, d);
#endif
}
@@ -451,7 +482,7 @@
#ifdef _LP64
Assembler::srlx(s1, imm6a, d);
#else
- Assembler::srl(s1, imm6a, d);
+ Assembler::srl( s1, imm6a, d);
#endif
}
@@ -541,9 +572,8 @@
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 @@
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
-}
-
-
-inline void MacroAssembler::split_disp( Address& a, Register temp ) {
- assert_not_delayed();
- a = a.split_disp();
- Assembler::sethi(a.hi(), temp, a.rspec());
- add(a.base(), temp, a.base());
+ sethi(addrlit, d);
+ ld(d, addrlit.low10() + offset, d);
}
-inline void MacroAssembler::load_contents( Address& a, Register d, int offset ) {
+inline void MacroAssembler::load_ptr_contents(AddressLiteral& addrlit, Register d, int offset) {
assert_not_delayed();
- sethi(a);
- ld(a, d, offset);
+ sethi(addrlit, d);
+ ld_ptr(d, addrlit.low10() + offset, d);
}
-inline void MacroAssembler::load_ptr_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_ptr(a, d, offset);
+ sethi(addrlit, temp);
+ st(s, temp, addrlit.low10() + offset);
}
-inline void MacroAssembler::store_contents( Register s, Address& a, int offset ) {
+inline void MacroAssembler::store_ptr_contents(Register s, AddressLiteral& addrlit, Register temp, 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);
}
--- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
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++) {
--- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
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));
}
--- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -196,7 +196,7 @@
// 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 @@
}
#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 @@
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 @@
#endif // ASSERT
compilation()->offsets()->set_value(CodeOffsets::Deopt, code_offset());
- Address deopt_blob(G3_scratch, SharedRuntime::deopt_blob()->unpack());
-
- __ JUMP(deopt_blob, 0); // sethi;jmp
+ AddressLiteral deopt_blob(SharedRuntime::deopt_blob()->unpack());
+
+ __ JUMP(deopt_blob, G3_scratch, 0); // sethi;jmp
__ delayed()->nop();
assert(code_offset() - offset <= deopt_handler_size, "overflow");
@@ -441,13 +441,12 @@
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::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 @@
// 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 @@
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 @@
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 @@
__ 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 @@
__ 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 @@
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 @@
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 @@
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 @@
} 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
__ 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 @@
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 @@
}
- 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 @@
__ 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 @@
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 @@
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 @@
}
}
} 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 @@
// 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 @@
__ 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();
--- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
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 @@
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 @@
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::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) {
--- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
// 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 @@
} 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 @@
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 @@
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 @@
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 @@
__ 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 @@
__ 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();
--- a/hotspot/src/cpu/sparc/vm/dump_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/dump_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
__ 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();
--- a/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
// (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();
}
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
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 @@
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::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 @@
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 @@
// 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 @@
} 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
// 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 @@
// %%% 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 @@
#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 @@
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 @@
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 @@
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::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_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 @@
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 @@
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 @@
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);
--- a/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
// 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 @@
}
#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 @@
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();
}
--- a/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
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 @@
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 @@
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 @@
__ 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 @@
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 @@
default: ShouldNotReachHere();
}
- __ ld (ca, O5);
+ __ ld (cnt_addr, O5);
__ cmp (O5, G4);
__ br (Assembler::notEqual, false, Assembler::pn, label2);
__ delayed()->mov (O7, G1);
--- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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() );
--- a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
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);
--- a/hotspot/src/cpu/sparc/vm/runtime_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/runtime_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
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 @@
// 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
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -625,9 +625,9 @@
__ 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 @@
#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 @@
// 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 @@
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 @@
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 @@
__ 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 @@
// 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 @@
{
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 @@
// 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 @@
// 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 @@
// 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 @@
__ 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 @@
__ 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 @@
{
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 @@
// 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 @@
// 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 @@
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 @@
// 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 @@
{
// 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 @@
// 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();
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Wed Apr 29 13:22:09 2009 -0700
@@ -980,8 +980,8 @@
// 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_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 @@
// 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 @@
__ 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 @@
// 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 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 @@
// 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 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 @@
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 @@
// 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 @@
__ 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 @@
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;
-
- 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();
+ 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);
%}
// Compiler ensures base is doubleword aligned and cnt is count of doublewords
@@ -2901,19 +2836,19 @@
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 @@
// 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 @@
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 @@
__ 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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
#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);
-
- 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);
+ match(Set dst (LoadN mem));
+ ins_cost(MEMORY_REF_COST);
+ size(4);
+
+ 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 @@
#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 @@
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 @@
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 @@
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 @@
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);
%}
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
#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 @@
__ 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 @@
// 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 @@
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 @@
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 @@
#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 @@
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 @@
__ 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();
-
}
}
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -87,8 +87,8 @@
}
// 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_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 @@
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 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 @@
// 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 @@
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 @@
__ 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 @@
// 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 @@
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 @@
__ 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 @@
// 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 @@
// (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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
__ 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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);
+ __ 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 @@
__ 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 @@
__ 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 @@
// 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 @@
__ 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 @@
__ 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 @@
// 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 @@
// 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 @@
// 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 @@
__ 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 @@
//
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 @@
__ 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 @@
__ 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 @@
__ 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 @@
// 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::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);
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
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 @@
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 @@
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 @@
// 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 @@
__ 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 @@
__ 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 @@
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 @@
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 @@
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 @@
// 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 @@
__ 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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
}
}
- __ 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 @@
// 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 @@
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 @@
__ 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
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::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 @@
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
--- a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
#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 @@
#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 @@
__ 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();
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -189,20 +189,33 @@
}
-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_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 @@
// 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,
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -76,8 +76,9 @@
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 @@
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);
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -156,13 +156,22 @@
}
-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 @@
__ 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 @@
// 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 @@
__ 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;
}
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -166,7 +166,8 @@
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
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -206,12 +206,12 @@
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), scratch, rsi, bc);
#ifndef ASSERT
__ jmpb(patch_done);
+#else
+ __ jmp(patch_done);
+#endif
__ bind(fast_patch);
}
-#else
- __ jmp(patch_done);
- __ 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::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 @@
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 @@
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::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 @@
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 @@
__ 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 @@
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(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::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::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::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 @@
__ 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
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 );
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -3058,6 +3058,23 @@
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
--- a/hotspot/src/os/windows/vm/os_windows.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -2632,6 +2632,8 @@
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 @@
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 @@
} 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;
}
}
--- a/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -39,7 +39,7 @@
// 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
--- a/hotspot/src/share/tools/MakeDeps/BuildConfig.java Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/tools/MakeDeps/BuildConfig.java Wed Apr 29 13:22:09 2009 -0700
@@ -247,7 +247,7 @@
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);
--- a/hotspot/src/share/tools/hsdis/Makefile Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/tools/hsdis/Makefile Wed Apr 29 13:22:09 2009 -0700
@@ -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
+ARCH=i386
+endif
+CC = $(MINGW)-gcc
+CONFIGURE_ARGS= --host=$(MINGW) --target=$(MINGW)
else
-ifeq ($(CPU),x86_64)
-CCFLAGS += -fPIC
-endif # x86_64
-endif # ia64
+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
+LIB_EXT = .so
CC = gcc
-CCFLAGS += -O
+endif
+CFLAGS += -O
DLDFLAGS += -shared
+LDFLAGS += -ldl
OUTFLAGS += -o $@
-LIB_EXT = .so
-CPPFLAGS += -Iinclude -Iinclude/$(OS)_$(ARCH)/
## 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 @@
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 @@
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 $@
--- a/hotspot/src/share/tools/hsdis/README Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/tools/hsdis/README Wed Apr 29 13:22:09 2009 -0700
@@ -32,61 +32,55 @@
* Building
-To build this project you need a build of Gnu binutils to link against.
-It is known to work with binutils 2.17.
-
-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.
-
-To build Gnu binutils, first download a copy of the software:
- http://directory.fsf.org/project/binutils/
+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.
-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
+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.
-From inside that directory, run configure and make:
- ( export CFLAGS='-fPIC'
- ./configure i386-pc-elf )
- gnumake
-
-(Leave out or change the argument to configure if not on an i386 system.)
+Windows
-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
+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:
-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.
+make MINGW=i586-mingw32msvc BINTUILS=build/binutils-2.19.1
-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
--- a/hotspot/src/share/tools/hsdis/hsdis-demo.c Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/tools/hsdis/hsdis-demo.c Wed Apr 29 13:22:09 2009 -0700
@@ -53,7 +53,7 @@
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 @@
#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 @@
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);
}
}
--- a/hotspot/src/share/tools/hsdis/hsdis.c Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/tools/hsdis/hsdis.c Wed Apr 29 13:22:09 2009 -0700
@@ -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 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;
}
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -1524,6 +1524,11 @@
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 @@
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 @@
, Bytecodes::_invokevirtual
, Bytecodes::_invokespecial
, Bytecodes::_invokestatic
+ , Bytecodes::_invokedynamic
, Bytecodes::_invokeinterface
, Bytecodes::_new
, Bytecodes::_newarray
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -2956,9 +2956,11 @@
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_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 @@
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()) {
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -833,6 +833,7 @@
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 @@
}
}
break;
- case Bytecodes::_xxxunusedxxx:
- ShouldNotReachHere();
- break;
case Bytecodes::_new:
state.apush(allocated_obj);
break;
--- a/hotspot/src/share/vm/ci/ciStreams.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/ci/ciStreams.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -301,17 +301,19 @@
// 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 @@
// 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);
}
--- a/hotspot/src/share/vm/ci/ciStreams.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/ci/ciStreams.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -91,9 +91,10 @@
_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 @@
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 @@
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
+ }
};
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -1217,31 +1217,34 @@
// 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 @@
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();
}
}
}
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -2430,6 +2430,41 @@
}
+// 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 @@
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
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -1060,6 +1060,33 @@
};
+// 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
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -1951,6 +1951,16 @@
// 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 @@
}
+// 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
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -142,6 +142,12 @@
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 @@
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>" :
--- a/hotspot/src/share/vm/classfile/verifier.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -1174,6 +1174,7 @@
&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 @@
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 @@
}
// 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 @@
}
}
+ 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 @@
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));
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -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") \
--- a/hotspot/src/share/vm/includeDB_compiler1 Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/includeDB_compiler1 Wed Apr 29 13:22:09 2009 -0700
@@ -270,6 +270,7 @@
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
--- a/hotspot/src/share/vm/includeDB_core Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/includeDB_core Wed Apr 29 13:22:09 2009 -0700
@@ -4102,6 +4102,7 @@
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
--- a/hotspot/src/share/vm/includeDB_gc_parallel Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/includeDB_gc_parallel Wed Apr 29 13:22:09 2009 -0700
@@ -42,6 +42,12 @@
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
--- a/hotspot/src/share/vm/includeDB_jvmti Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/includeDB_jvmti Wed Apr 29 13:22:09 2009 -0700
@@ -28,6 +28,7 @@
jvmtiClassFileReconstituter.cpp bytes_<arch>.hpp
jvmtiClassFileReconstituter.cpp jvmtiClassFileReconstituter.hpp
jvmtiClassFileReconstituter.cpp symbolTable.hpp
+jvmtiClassFileReconstituter.cpp signature.hpp
jvmtiClassFileReconstituter.hpp jvmtiEnv.hpp
--- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -217,6 +217,73 @@
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();
+ }
+ }
};
//------------------------------------------------------------------------------------------------------------------------
--- a/hotspot/src/share/vm/interpreter/bytecode.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecode.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -34,12 +34,6 @@
}
-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 @@
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);
}
--- a/hotspot/src/share/vm/interpreter/bytecode.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecode.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -65,14 +65,6 @@
// 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 @@
// 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 @@
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() ||
--- a/hotspot/src/share/vm/interpreter/bytecodeStream.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodeStream.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -109,6 +109,7 @@
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 @@
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
--- a/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodeTracer.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -48,12 +48,15 @@
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 @@
}
}
+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 @@
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 @@
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:
--- a/hotspot/src/share/vm/interpreter/bytecodes.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -357,7 +357,7 @@
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 );
--- a/hotspot/src/share/vm/interpreter/bytecodes.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -218,7 +218,7 @@
_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
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -681,6 +681,133 @@
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
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -42,8 +42,11 @@
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 @@
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);
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -947,6 +947,7 @@
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 @@
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
--- a/hotspot/src/share/vm/interpreter/linkResolver.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -167,6 +167,7 @@
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);
};
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
}
+// 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
}
}
- // 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);
}
}
--- a/hotspot/src/share/vm/interpreter/rewriter.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/rewriter.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -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);
};
--- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -178,12 +178,14 @@
#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 @@
}
}
+ 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 @@
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_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);
--- a/hotspot/src/share/vm/interpreter/templateInterpreter.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -83,9 +83,9 @@
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 @@
#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 @@
// 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
--- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -51,7 +51,10 @@
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);
--- a/hotspot/src/share/vm/interpreter/templateTable.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/templateTable.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -442,6 +442,7 @@
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 @@
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 , _ );
--- a/hotspot/src/share/vm/interpreter/templateTable.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/interpreter/templateTable.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -261,6 +261,7 @@
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);
--- a/hotspot/src/share/vm/oops/constantPoolKlass.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolKlass.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -312,6 +312,7 @@
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();
}
--- a/hotspot/src/share/vm/oops/constantPoolOop.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolOop.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -249,32 +249,41 @@
}
-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 @@
}
-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 @@
}
-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));
}
--- a/hotspot/src/share/vm/oops/constantPoolOop.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -53,6 +53,7 @@
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 @@
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 @@
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 @@
// 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 @@
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);
--- a/hotspot/src/share/vm/oops/cpCacheKlass.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/cpCacheKlass.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -169,11 +169,47 @@
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
--- a/hotspot/src/share/vm/oops/cpCacheOop.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/cpCacheOop.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
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_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 @@
// 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);
--- a/hotspot/src/share/vm/oops/cpCacheOop.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/cpCacheOop.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -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 @@
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 @@
}
// 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 @@
// 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
--- a/hotspot/src/share/vm/oops/generateOopMap.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/generateOopMap.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -1252,8 +1252,9 @@
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 @@
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 @@
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 @@
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 @@
// 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
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -163,6 +163,8 @@
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 @@
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 @@
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;}
--- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -84,6 +84,7 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
} // 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);
--- a/hotspot/src/share/vm/oops/methodDataOop.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/methodDataOop.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -442,6 +442,8 @@
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 @@
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;
--- a/hotspot/src/share/vm/oops/methodOop.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/methodOop.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -161,7 +161,7 @@
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();
}
--- a/hotspot/src/share/vm/oops/methodOop.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/oops/methodOop.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -534,7 +534,10 @@
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(); }
--- a/hotspot/src/share/vm/opto/buildOopMap.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/buildOopMap.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -363,6 +363,20 @@
*/
#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;
}
--- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -321,7 +321,7 @@
// 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;
}
--- a/hotspot/src/share/vm/opto/chaitin.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/chaitin.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -1423,17 +1423,33 @@
// 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 @@
}
// 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 @@
// 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 );
--- a/hotspot/src/share/vm/opto/doCall.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/doCall.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -248,6 +248,14 @@
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 @@
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 @@
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");
}
--- a/hotspot/src/share/vm/opto/graphKit.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -947,6 +947,7 @@
case Bytecodes::_invokevirtual:
case Bytecodes::_invokespecial:
case Bytecodes::_invokestatic:
+ case Bytecodes::_invokedynamic:
case Bytecodes::_invokeinterface:
{
bool is_static = (depth == 0);
@@ -2979,6 +2980,7 @@
// 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* 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);
}
--- a/hotspot/src/share/vm/opto/graphKit.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -699,7 +699,7 @@
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
--- a/hotspot/src/share/vm/opto/library_call.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -3055,9 +3055,7 @@
// 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 @@
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 @@
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(), "");
--- a/hotspot/src/share/vm/opto/matcher.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/matcher.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -275,6 +275,12 @@
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 @@
}
}
+ // 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
--- a/hotspot/src/share/vm/opto/matcher.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/matcher.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -109,6 +109,9 @@
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 @@
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; }
--- a/hotspot/src/share/vm/opto/parse.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/parse.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -476,7 +476,7 @@
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();
--- a/hotspot/src/share/vm/opto/parse1.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/parse1.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -828,6 +828,7 @@
break;
case Bytecodes::_invokestatic:
+ case Bytecodes::_invokedynamic:
case Bytecodes::_invokespecial:
case Bytecodes::_invokevirtual:
case Bytecodes::_invokeinterface:
--- a/hotspot/src/share/vm/opto/parse2.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/parse2.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -2156,6 +2156,7 @@
break;
case Bytecodes::_invokestatic:
+ case Bytecodes::_invokedynamic:
case Bytecodes::_invokespecial:
case Bytecodes::_invokevirtual:
case Bytecodes::_invokeinterface:
--- a/hotspot/src/share/vm/opto/parse3.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/parse3.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -335,7 +335,7 @@
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 @@
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 @@
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 @@
// 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;
}
--- a/hotspot/src/share/vm/opto/parseHelper.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/parseHelper.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -414,6 +414,7 @@
profile_receiver_type(receiver);
break;
case Bytecodes::_invokestatic:
+ case Bytecodes::_invokedynamic:
case Bytecodes::_invokespecial:
break;
default: fatal("unexpected call bytecode");
--- a/hotspot/src/share/vm/prims/jvm.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -2222,6 +2222,9 @@
case JVM_CONSTANT_InterfaceMethodref:
case JVM_CONSTANT_Methodref:
return cp->uncached_name_ref_at(cp_index)->as_utf8();
+ case JVM_CONSTANT_NameAndType:
+ // for invokedynamic
+ return cp->nt_name_ref_at(cp_index)->as_utf8();
default:
fatal("JVM_GetCPMethodNameUTF: illegal constant");
}
@@ -2239,6 +2242,9 @@
case JVM_CONSTANT_InterfaceMethodref:
case JVM_CONSTANT_Methodref:
return cp->uncached_signature_ref_at(cp_index)->as_utf8();
+ case JVM_CONSTANT_NameAndType:
+ // for invokedynamic
+ return cp->nt_signature_ref_at(cp_index)->as_utf8();
default:
fatal("JVM_GetCPMethodSignatureUTF: illegal constant");
}
--- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -659,15 +659,21 @@
case Bytecodes::_invokevirtual : // fall through
case Bytecodes::_invokespecial : // fall through
case Bytecodes::_invokestatic : // fall through
+ case Bytecodes::_invokedynamic : // fall through
case Bytecodes::_invokeinterface :
assert(len == 3 || (code == Bytecodes::_invokeinterface && len ==5),
"sanity check");
+ int cpci = Bytes::get_native_u2(bcp+1);
+ bool is_invokedynamic = (EnableInvokeDynamic && code == Bytecodes::_invokedynamic);
+ if (is_invokedynamic)
+ cpci = Bytes::get_native_u4(bcp+1);
// cache cannot be pre-fetched since some classes won't have it yet
ConstantPoolCacheEntry* entry =
- mh->constants()->cache()->entry_at(Bytes::get_native_u2(bcp+1));
+ mh->constants()->cache()->main_entry_at(cpci);
int i = entry->constant_pool_index();
assert(i < mh->constants()->length(), "sanity check");
Bytes::put_Java_u2((address)(p+1), (u2)i); // java byte ordering
+ if (is_invokedynamic) *(p+3) = *(p+4) = 0;
break;
}
}
--- a/hotspot/src/share/vm/prims/methodComparator.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/prims/methodComparator.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -148,8 +148,8 @@
case Bytecodes::_invokespecial : // fall through
case Bytecodes::_invokestatic : // fall through
case Bytecodes::_invokeinterface : {
- u2 cpci_old = _s_old->get_index_big();
- u2 cpci_new = _s_new->get_index_big();
+ u2 cpci_old = _s_old->get_index_int();
+ u2 cpci_new = _s_new->get_index_int();
// Check if the names of classes, field/method names and signatures at these indexes
// are the same. Indices which are really into constantpool cache (rather than constant
// pool itself) are accepted by the constantpool query routines below.
--- a/hotspot/src/share/vm/prims/methodHandles.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -2279,6 +2279,16 @@
JVM_END
+JVM_ENTRY(void, MH_linkCallSite(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) {
+ // No special action required, yet.
+ oop site_oop = JNIHandles::resolve(site_jh);
+ if (site_oop == NULL || site_oop->klass() != SystemDictionary::CallSiteImpl_klass())
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "call site");
+ sun_dyn_CallSiteImpl::set_target(site_oop, JNIHandles::resolve(target_jh));
+}
+JVM_END
+
+
/// JVM_RegisterMethodHandleMethods
#define ADR "J"
@@ -2297,6 +2307,7 @@
#define AMH IDYN"AdapterMethodHandle;"
#define BMH IDYN"BoundMethodHandle;"
#define DMH IDYN"DirectMethodHandle;"
+#define CSTI IDYN"CallSiteImpl;"
#define CC (char*) /*cast a literal from (const char*)*/
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
@@ -2320,12 +2331,19 @@
{CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHI_getMembers)}
};
+// More entry points specifically for EnableInvokeDynamic.
+static JNINativeMethod methods2[] = {
+ {CC"linkCallSite", CC"("CSTI MH")V", FN_PTR(MH_linkCallSite)}
+};
+
// This one function is exported, used by NativeLookup.
JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) {
assert(MethodHandles::spot_check_entry_names(), "entry enum is OK");
+ // note: this explicit warning-producing stuff will be replaced by auto-detection of the JSR 292 classes
+
if (!EnableMethodHandles) {
warning("JSR 292 method handles are disabled in this JVM. Use -XX:+EnableMethodHandles to enable.");
return; // bind nothing
@@ -2343,5 +2361,23 @@
MethodHandles::set_enabled(true);
}
}
+
+ if (!EnableInvokeDynamic) {
+ warning("JSR 292 invokedynamic is disabled in this JVM. Use -XX:+EnableInvokeDynamic to enable.");
+ return; // bind nothing
+ }
+
+ {
+ ThreadToNativeFromVM ttnfv(thread);
+
+ int status = env->RegisterNatives(MHN_class, methods2, sizeof(methods2)/sizeof(JNINativeMethod));
+ if (env->ExceptionOccurred()) {
+ MethodHandles::set_enabled(false);
+ warning("JSR 292 method handle code is mismatched to this JVM. Disabling support.");
+ env->ExceptionClear();
+ } else {
+ MethodHandles::set_enabled(true);
+ }
+ }
}
JVM_END
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Apr 29 13:22:09 2009 -0700
@@ -2627,6 +2627,12 @@
}
#endif // PRODUCT
+ if (EnableInvokeDynamic && !EnableMethodHandles) {
+ if (!FLAG_IS_DEFAULT(EnableMethodHandles)) {
+ warning("forcing EnableMethodHandles true to allow EnableInvokeDynamic");
+ }
+ EnableMethodHandles = true;
+ }
if (EnableMethodHandles && !AnonymousClasses) {
if (!FLAG_IS_DEFAULT(AnonymousClasses)) {
warning("forcing AnonymousClasses true to enable EnableMethodHandles");
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -3316,6 +3316,12 @@
diagnostic(bool, OptimizeMethodHandles, true, \
"when constructing method handles, try to improve them") \
\
+ product(bool, EnableInvokeDynamic, false, \
+ "recognize the invokedynamic instruction") \
+ \
+ develop(bool, TraceInvokeDynamic, false, \
+ "trace internal invoke dynamic operations") \
+ \
product(bool, TaggedStackInterpreter, false, \
"Insert tags in interpreter execution stack for oopmap generaion")\
\
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Thu Apr 23 15:54:48 2009 -0700
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Wed Apr 29 13:22:09 2009 -0700
@@ -572,8 +572,8 @@
enum TosState { // describes the tos cache contents
btos = 0, // byte, bool tos cached
- ctos = 1, // short, char tos cached
- stos = 2, // short, char tos cached
+ ctos = 1, // char tos cached
+ stos = 2, // short tos cached
itos = 3, // int tos cached
ltos = 4, // long tos cached
ftos = 5, // float tos cached
@@ -588,7 +588,7 @@
inline TosState as_TosState(BasicType type) {
switch (type) {
case T_BYTE : return btos;
- case T_BOOLEAN: return btos;
+ case T_BOOLEAN: return btos; // FIXME: Add ztos
case T_CHAR : return ctos;
case T_SHORT : return stos;
case T_INT : return itos;
@@ -602,6 +602,22 @@
return ilgl;
}
+inline BasicType as_BasicType(TosState state) {
+ switch (state) {
+ //case ztos: return T_BOOLEAN;//FIXME
+ case btos : return T_BYTE;
+ case ctos : return T_CHAR;
+ case stos : return T_SHORT;
+ case itos : return T_INT;
+ case ltos : return T_LONG;
+ case ftos : return T_FLOAT;
+ case dtos : return T_DOUBLE;
+ case atos : return T_OBJECT;
+ case vtos : return T_VOID;
+ }
+ return T_ILLEGAL;
+}
+
// Helper function to convert BasicType info into TosState
// Note: Cannot define here as it uses global constant at the time being.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6589834/Test_ia32.java Wed Apr 29 13:22:09 2009 -0700
@@ -0,0 +1,126 @@
+/*
+ * Copyright 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6589834
+ * @summary deoptimization problem with -XX:+DeoptimizeALot
+ *
+ * @run main/othervm -server Test_ia32
+ */
+
+/***************************************************************************************
+NOTE: The bug shows up (with several "Bug!" message) even without the
+ flag -XX:+DeoptimizeALot. In a debug build, you may want to try
+ the flags -XX:+VerifyStack and -XX:+DeoptimizeALot to get more information.
+****************************************************************************************/
+import java.lang.reflect.Constructor;
+
+public class Test_ia32 {
+
+ public static int NUM_THREADS = 100;
+
+ public static int CLONE_LENGTH = 1000;
+
+ public static void main(String[] args) throws InterruptedException, ClassNotFoundException {
+
+ Reflector[] threads = new Reflector[NUM_THREADS];
+ for (int i = 0; i < threads.length; i++) {
+ threads[i] = new Reflector();
+ threads[i].start();
+ }
+
+ System.out.println("Give Reflector.run() some time to compile...");
+ Thread.sleep(5000);
+
+ System.out.println("Load RMISecurityException causing run() deoptimization");
+ ClassLoader.getSystemClassLoader().loadClass("java.rmi.RMISecurityException");
+
+ for (Reflector thread : threads)
+ thread.requestStop();
+
+ for (Reflector thread : threads)
+ try {
+ thread.join();
+ } catch (InterruptedException e) {
+ System.out.println(e);
+ }
+
+ }
+
+}
+
+class Reflector extends Thread {
+
+ volatile boolean _doSpin = true;
+
+ Test_ia32[] _tests;
+
+ Reflector() {
+ _tests = new Test_ia32[Test_ia32.CLONE_LENGTH];
+ for (int i = 0; i < _tests.length; i++) {
+ _tests[i] = new Test_ia32();
+ }
+ }
+
+ static int g(int i1, int i2, Test_ia32[] arr, int i3, int i4) {
+
+ if (!(i1==1 && i2==2 && i3==3 && i4==4)) {
+ System.out.println("Bug!");
+ }
+
+ return arr.length;
+ }
+
+ static int f(Test_ia32[] arr) {
+ return g(1, 2, arr.clone(), 3, 4);
+ }
+
+ @Override
+ public void run() {
+ Constructor[] ctrs = null;
+ Class<Test_ia32> klass = Test_ia32.class;
+ try {
+ ctrs = klass.getConstructors();
+ } catch (SecurityException e) {
+ System.out.println(e);
+ }
+
+ try {
+ while (_doSpin) {
+ if (f(_tests) < 0)
+ System.out.println("return value usage");
+ }
+ } catch (NullPointerException e) {
+ e.printStackTrace();
+ }
+
+ System.out.println(this + " - stopped.");
+ }
+
+ public void requestStop() {
+ System.out.println(this + " - stop requested.");
+ _doSpin = false;
+ }
+
+}