6420645: Create a vm that uses compressed oops for up to 32gb heapsizes

Compressed oops in instances, arrays, and headers. Code contributors are coleenp, phh, never, swamyv

Reviewed-by: jmasa, kamg, acorn, tbell, kvn, rasbold
This commit is contained in:
Coleen Phillimore 2008-04-13 17:43:42 -04:00
parent 680ecf1611
commit 4a831d45f0
273 changed files with 6585 additions and 2993 deletions
hotspot
agent/src/share/classes/sun/jvm/hotspot
make
Makefile
solaris/makefiles
src/cpu

@ -885,7 +885,12 @@ public class CommandProcessor {
out.println("found at " + addr);
}
}
public void visitCompOopAddress(Address addr) {
Address val = addr.getCompOopAddressAt(0);
if (AddressOps.equal(val, value)) {
out.println("found at " + addr);
}
}
public void epilogue() {
}
};

@ -1011,8 +1011,21 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
Assert.that(addr.andWithMask(VM.getVM().getAddressSize() - 1) == null,
"Address " + addr + "should have been aligned");
}
// Check contents
OopHandle handle = addr.getOopHandleAt(0);
addAnnotation(addr, handle);
}
public void visitCompOopAddress(Address addr) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(addr.andWithMask(VM.getVM().getAddressSize() - 1) == null,
"Address " + addr + "should have been aligned");
}
OopHandle handle = addr.getCompOopHandleAt(0);
addAnnotation(addr, handle);
}
public void addAnnotation(Address addr, OopHandle handle) {
// Check contents
String anno = "null oop";
if (handle != null) {
// Find location

@ -306,6 +306,8 @@ public class HotSpotTypeDataBase extends BasicTypeDataBase {
entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride);
} while (nameAddr != null);
String symbol = "heapOopSize"; // global int constant and value is initialized at runtime.
addIntConstant(symbol, (int)lookupInProcess(symbol).getCIntegerAt(0, 4, false));
}
private void readVMLongConstants() {

@ -68,7 +68,8 @@ public class OopMapSet extends VMObject {
public void visitValueLocation(Address valueAddr) {
}
public void visitDeadLocation(Address deadAddr) {
public void visitNarrowOopLocation(Address narrowOopAddr) {
addressVisitor.visitCompOopAddress(narrowOopAddr);
}
}
@ -197,9 +198,9 @@ public class OopMapSet extends VMObject {
}
}
// We want dead, value and oop oop_types
// We want narow oop, value and oop oop_types
OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[] {
OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.DEAD_VALUE
OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE
};
{
@ -214,8 +215,8 @@ public class OopMapSet extends VMObject {
visitor.visitOopLocation(loc);
} else if (omv.getType() == OopMapValue.OopTypes.VALUE_VALUE) {
visitor.visitValueLocation(loc);
} else if (omv.getType() == OopMapValue.OopTypes.DEAD_VALUE) {
visitor.visitDeadLocation(loc);
} else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) {
visitor.visitNarrowOopLocation(loc);
}
}
}

@ -50,7 +50,7 @@ public class OopMapValue {
static int UNUSED_VALUE;
static int OOP_VALUE;
static int VALUE_VALUE;
static int DEAD_VALUE;
static int NARROWOOP_VALUE;
static int CALLEE_SAVED_VALUE;
static int DERIVED_OOP_VALUE;
@ -74,7 +74,7 @@ public class OopMapValue {
UNUSED_VALUE = db.lookupIntConstant("OopMapValue::unused_value").intValue();
OOP_VALUE = db.lookupIntConstant("OopMapValue::oop_value").intValue();
VALUE_VALUE = db.lookupIntConstant("OopMapValue::value_value").intValue();
DEAD_VALUE = db.lookupIntConstant("OopMapValue::dead_value").intValue();
NARROWOOP_VALUE = db.lookupIntConstant("OopMapValue::narrowoop_value").intValue();
CALLEE_SAVED_VALUE = db.lookupIntConstant("OopMapValue::callee_saved_value").intValue();
DERIVED_OOP_VALUE = db.lookupIntConstant("OopMapValue::derived_oop_value").intValue();
}
@ -83,7 +83,7 @@ public class OopMapValue {
public static final OopTypes UNUSED_VALUE = new OopTypes() { int getValue() { return OopMapValue.UNUSED_VALUE; }};
public static final OopTypes OOP_VALUE = new OopTypes() { int getValue() { return OopMapValue.OOP_VALUE; }};
public static final OopTypes VALUE_VALUE = new OopTypes() { int getValue() { return OopMapValue.VALUE_VALUE; }};
public static final OopTypes DEAD_VALUE = new OopTypes() { int getValue() { return OopMapValue.DEAD_VALUE; }};
public static final OopTypes NARROWOOP_VALUE = new OopTypes() { int getValue() { return OopMapValue.NARROWOOP_VALUE; }};
public static final OopTypes CALLEE_SAVED_VALUE = new OopTypes() { int getValue() { return OopMapValue.CALLEE_SAVED_VALUE; }};
public static final OopTypes DERIVED_OOP_VALUE = new OopTypes() { int getValue() { return OopMapValue.DERIVED_OOP_VALUE; }};
@ -106,7 +106,7 @@ public class OopMapValue {
// Querying
public boolean isOop() { return (getValue() & TYPE_MASK_IN_PLACE) == OOP_VALUE; }
public boolean isValue() { return (getValue() & TYPE_MASK_IN_PLACE) == VALUE_VALUE; }
public boolean isDead() { return (getValue() & TYPE_MASK_IN_PLACE) == DEAD_VALUE; }
public boolean isNarrowOop() { return (getValue() & TYPE_MASK_IN_PLACE) == NARROWOOP_VALUE; }
public boolean isCalleeSaved() { return (getValue() & TYPE_MASK_IN_PLACE) == CALLEE_SAVED_VALUE; }
public boolean isDerivedOop() { return (getValue() & TYPE_MASK_IN_PLACE) == DERIVED_OOP_VALUE; }
@ -118,7 +118,7 @@ public class OopMapValue {
if (which == UNUSED_VALUE) return OopTypes.UNUSED_VALUE;
else if (which == OOP_VALUE) return OopTypes.OOP_VALUE;
else if (which == VALUE_VALUE) return OopTypes.VALUE_VALUE;
else if (which == DEAD_VALUE) return OopTypes.DEAD_VALUE;
else if (which == NARROWOOP_VALUE) return OopTypes.NARROWOOP_VALUE;
else if (which == CALLEE_SAVED_VALUE) return OopTypes.CALLEE_SAVED_VALUE;
else if (which == DERIVED_OOP_VALUE) return OopTypes.DERIVED_OOP_VALUE;
else throw new InternalError("unknown which " + which + " (TYPE_MASK_IN_PLACE = " + TYPE_MASK_IN_PLACE + ")");

@ -32,5 +32,5 @@ public interface OopMapVisitor {
public void visitOopLocation(Address oopAddr);
public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr);
public void visitValueLocation(Address valueAddr);
public void visitDeadLocation(Address deadAddr);
public void visitNarrowOopLocation(Address narrowOopAddr);
}

@ -87,6 +87,8 @@ public interface Address {
throws UnmappedAddressException, UnalignedAddressException;
/** This returns null if the address at the given offset is NULL. */
public Address getAddressAt (long offset) throws UnmappedAddressException, UnalignedAddressException;
/** Returns the decoded address at the given offset */
public Address getCompOopAddressAt (long offset) throws UnmappedAddressException, UnalignedAddressException;
//
// Java-related routines
@ -103,6 +105,8 @@ public interface Address {
/** This returns null if the address at the given offset is NULL. */
public OopHandle getOopHandleAt (long offset)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException;
public OopHandle getCompOopHandleAt (long offset)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException;
//
// C/C++-related mutators. These throw UnmappedAddressException if

@ -118,6 +118,9 @@ public interface Debugger extends SymbolLookup, ThreadAccess {
public long getJIntSize();
public long getJLongSize();
public long getJShortSize();
public long getHeapBase();
public long getHeapOopSize();
public long getLogMinObjAlignmentInBytes();
public ReadResult readBytesFromProcess(long address, long numBytes)
throws DebuggerException;

@ -37,6 +37,7 @@ package sun.jvm.hotspot.debugger;
DbxDebugger interfaces. </P> */
public abstract class DebuggerBase implements Debugger {
// May be set lazily, but must be set before calling any of the read
// routines below
protected MachineDescription machDesc;
@ -52,6 +53,11 @@ public abstract class DebuggerBase implements Debugger {
protected long jlongSize;
protected long jshortSize;
protected boolean javaPrimitiveTypesConfigured;
// heap data.
protected long oopSize;
protected long heapOopSize;
protected long heapBase; // heap base for compressed oops.
protected long logMinObjAlignmentInBytes; // Used to decode compressed oops.
// Should be initialized if desired by calling initCache()
private PageCache cache;
@ -153,6 +159,12 @@ public abstract class DebuggerBase implements Debugger {
javaPrimitiveTypesConfigured = true;
}
public void putHeapConst(long heapBase, long heapOopSize, long logMinObjAlignmentInBytes) {
this.heapBase = heapBase;
this.heapOopSize = heapOopSize;
this.logMinObjAlignmentInBytes = logMinObjAlignmentInBytes;
}
/** May be called by subclasses if desired to initialize the page
cache but may not be overridden */
protected final void initCache(long pageSize, long maxNumPages) {
@ -442,6 +454,16 @@ public abstract class DebuggerBase implements Debugger {
return readCInteger(address, machDesc.getAddressSize(), true);
}
protected long readCompOopAddressValue(long address)
throws UnmappedAddressException, UnalignedAddressException {
long value = readCInteger(address, getHeapOopSize(), true);
if (value != 0) {
// See oop.inline.hpp decode_heap_oop
value = (long)(heapBase + (long)(value << logMinObjAlignmentInBytes));
}
return value;
}
protected void writeAddressValue(long address, long value)
throws UnmappedAddressException, UnalignedAddressException {
writeCInteger(address, machDesc.getAddressSize(), value);
@ -518,4 +540,15 @@ public abstract class DebuggerBase implements Debugger {
public long getJShortSize() {
return jshortSize;
}
public long getHeapOopSize() {
return heapOopSize;
}
public long getHeapBase() {
return heapBase;
}
public long getLogMinObjAlignmentInBytes() {
return logMinObjAlignmentInBytes;
}
}

@ -42,4 +42,5 @@ public interface JVMDebugger extends Debugger {
long jintSize,
long jlongSize,
long jshortSize);
public void putHeapConst(long heapBase, long heapOopSize, long logMinObjAlignment);
}

@ -35,13 +35,6 @@ public interface MachineDescription extends Serializable {
able to traverse arrays of pointers or oops. */
public long getAddressSize();
/** Returns the size of an address in bytes. Currently needed to be
able to traverse arrays of pointers or oops. (FIXME: since we're
already reading the Java primitive types' sizes from the remote
VM, it would be nice to remove this routine, using a similar
mechanism to how the TypeDataBase deals with primitive types.) */
public long getOopSize();
/** Returns the maximum value of the C integer type with the given
size in bytes and signedness. Throws IllegalArgumentException if
the size in bytes is not legal for a C type (or can not be

@ -29,10 +29,6 @@ public class MachineDescriptionAMD64 extends MachineDescriptionTwosComplement im
return 8;
}
public long getOopSize() {
return 8;
}
public boolean isLP64() {
return true;
}

@ -29,10 +29,6 @@ public class MachineDescriptionIA64 extends MachineDescriptionTwosComplement imp
return 8;
}
public long getOopSize() {
return 8;
}
public boolean isLP64() {
return true;
}

@ -29,10 +29,6 @@ public class MachineDescriptionIntelX86 extends MachineDescriptionTwosComplement
return 4;
}
public long getOopSize() {
return 4;
}
public boolean isBigEndian() {
return false;
}

@ -29,10 +29,6 @@ public class MachineDescriptionSPARC32Bit extends MachineDescriptionTwosCompleme
return 4;
}
public long getOopSize() {
return 4;
}
public boolean isBigEndian() {
return true;
}

@ -29,9 +29,6 @@ public class MachineDescriptionSPARC64Bit extends MachineDescriptionTwosCompleme
return 8;
}
public long getOopSize() {
return 8;
}
public boolean isBigEndian() {
return true;

@ -71,6 +71,9 @@ class DbxAddress implements Address {
public Address getAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readAddress(addr + offset);
}
public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompOopAddress(addr + offset);
}
//
// Java-related routines
@ -113,6 +116,11 @@ class DbxAddress implements Address {
return debugger.readOopHandle(addr + offset);
}
public OopHandle getCompOopHandleAt(long offset)
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readCompOopHandle(addr + offset);
}
// Mutators -- not implemented for now (FIXME)
public void setCIntegerAt(long offset, long numBytes, long value) {
throw new DebuggerException("Unimplemented");

@ -43,7 +43,9 @@ public interface DbxDebugger extends JVMDebugger {
public long readCInteger(long address, long numBytes, boolean isUnsigned)
throws DebuggerException;
public DbxAddress readAddress(long address) throws DebuggerException;
public DbxAddress readCompOopAddress(long address) throws DebuggerException;
public DbxOopHandle readOopHandle(long address) throws DebuggerException;
public DbxOopHandle readCompOopHandle(long address) throws DebuggerException;
public long[] getThreadIntegerRegisterSet(int tid) throws DebuggerException;
public Address newAddress(long value) throws DebuggerException;

@ -460,12 +460,23 @@ public class DbxDebuggerLocal extends DebuggerBase implements DbxDebugger {
return (value == 0 ? null : new DbxAddress(this, value));
}
public DbxAddress readCompOopAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
long value = readCompOopAddressValue(address);
return (value == 0 ? null : new DbxAddress(this, value));
}
/** From the DbxDebugger interface */
public DbxOopHandle readOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
long value = readAddressValue(address);
return (value == 0 ? null : new DbxOopHandle(this, value));
}
public DbxOopHandle readCompOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
long value = readCompOopAddressValue(address);
return (value == 0 ? null : new DbxOopHandle(this, value));
}
//--------------------------------------------------------------------------------
// Thread context access. Can not be package private, but should

@ -76,6 +76,10 @@ class DummyAddress implements Address {
return new DummyAddress(debugger, badLong);
}
public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return new DummyAddress(debugger, badLong);
}
//
// Java-related routines
//
@ -116,6 +120,10 @@ class DummyAddress implements Address {
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return new DummyOopHandle(debugger, badLong);
}
public OopHandle getCompOopHandleAt(long offset)
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return new DummyOopHandle(debugger, badLong);
}
// Mutators -- not implemented
public void setCIntegerAt(long offset, long numBytes, long value) {

@ -74,6 +74,11 @@ class LinuxAddress implements Address {
return debugger.readAddress(addr + offset);
}
public Address getCompOopAddressAt(long offset)
throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompOopAddress(addr + offset);
}
//
// Java-related routines
//
@ -115,6 +120,11 @@ class LinuxAddress implements Address {
return debugger.readOopHandle(addr + offset);
}
public OopHandle getCompOopHandleAt(long offset)
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readCompOopHandle(addr + offset);
}
// Mutators -- not implemented for now (FIXME)
public void setCIntegerAt(long offset, long numBytes, long value) {
throw new DebuggerException("Unimplemented");

@ -45,7 +45,9 @@ public interface LinuxDebugger extends JVMDebugger {
public long readCInteger(long address, long numBytes, boolean isUnsigned)
throws DebuggerException;
public LinuxAddress readAddress(long address) throws DebuggerException;
public LinuxAddress readCompOopAddress(long address) throws DebuggerException;
public LinuxOopHandle readOopHandle(long address) throws DebuggerException;
public LinuxOopHandle readCompOopHandle(long address) throws DebuggerException;
public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException;
public long getAddressValue(Address addr) throws DebuggerException;
public Address newAddress(long value) throws DebuggerException;

@ -423,6 +423,11 @@ public class LinuxDebuggerLocal extends DebuggerBase implements LinuxDebugger {
long value = readAddressValue(address);
return (value == 0 ? null : new LinuxAddress(this, value));
}
public LinuxAddress readCompOopAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
long value = readCompOopAddressValue(address);
return (value == 0 ? null : new LinuxAddress(this, value));
}
/** From the LinuxDebugger interface */
public LinuxOopHandle readOopHandle(long address)
@ -431,6 +436,12 @@ public class LinuxDebuggerLocal extends DebuggerBase implements LinuxDebugger {
long value = readAddressValue(address);
return (value == 0 ? null : new LinuxOopHandle(this, value));
}
public LinuxOopHandle readCompOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException,
NotInHeapException {
long value = readCompOopAddressValue(address);
return (value == 0 ? null : new LinuxOopHandle(this, value));
}
//----------------------------------------------------------------------
// Thread context access

@ -72,6 +72,10 @@ class ProcAddress implements Address {
return debugger.readAddress(addr + offset);
}
public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompOopAddress(addr + offset);
}
//
// Java-related routines
//
@ -112,6 +116,10 @@ class ProcAddress implements Address {
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readOopHandle(addr + offset);
}
public OopHandle getCompOopHandleAt(long offset)
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readCompOopHandle(addr + offset);
}
// Mutators -- not implemented for now (FIXME)
public void setCIntegerAt(long offset, long numBytes, long value) {

@ -46,7 +46,9 @@ public interface ProcDebugger extends JVMDebugger {
public long readCInteger(long address, long numBytes, boolean isUnsigned)
throws DebuggerException;
public ProcAddress readAddress(long address) throws DebuggerException;
public ProcAddress readCompOopAddress(long address) throws DebuggerException;
public ProcOopHandle readOopHandle(long address) throws DebuggerException;
public ProcOopHandle readCompOopHandle(long address) throws DebuggerException;
public long[] getThreadIntegerRegisterSet(int tid) throws DebuggerException;
public long getAddressValue(Address addr) throws DebuggerException;
public Address newAddress(long value) throws DebuggerException;

@ -53,8 +53,6 @@ import sun.jvm.hotspot.utilities.*;
*/
public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger {
protected static final int cacheSize = 16 * 1024 * 1024; // 16 MB
//------------------------------------------------------------------------
@ -337,10 +335,21 @@ public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger {
return (value == 0 ? null : new ProcAddress(this, value));
}
public ProcAddress readCompOopAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
long value = readCompOopAddressValue(address);
return (value == 0 ? null : new ProcAddress(this, value));
}
/** From the ProcDebugger interface */
public ProcOopHandle readOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
long value = readAddressValue(address);
long value = readAddressValue(address);
return (value == 0 ? null : new ProcOopHandle(this, value));
}
public ProcOopHandle readCompOopHandle(long address) {
long value = readCompOopAddressValue(address);
return (value == 0 ? null : new ProcOopHandle(this, value));
}

@ -71,6 +71,9 @@ class RemoteAddress implements Address {
public Address getAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readAddress(addr + offset);
}
public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompOopAddress(addr + offset);
}
//
// Java-related routines
@ -112,6 +115,10 @@ class RemoteAddress implements Address {
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readOopHandle(addr + offset);
}
public OopHandle getCompOopHandleAt(long offset)
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readCompOopHandle(addr + offset);
}
// Mutators -- not implemented for now (FIXME)
public void setCIntegerAt(long offset, long numBytes, long value) {

@ -65,6 +65,9 @@ public interface RemoteDebugger extends Remote {
public long getJIntSize() throws RemoteException;
public long getJLongSize() throws RemoteException;
public long getJShortSize() throws RemoteException;
public long getHeapBase() throws RemoteException;
public long getHeapOopSize() throws RemoteException;
public long getLogMinObjAlignmentInBytes() throws RemoteException;
public boolean areThreadsEqual(long addrOrId1, boolean isAddress1,
long addrOrId2, boolean isAddress2) throws RemoteException;
public int getThreadHashCode(long addrOrId, boolean isAddress) throws RemoteException;

@ -85,6 +85,9 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger {
jlongSize = remoteDebugger.getJLongSize();
jshortSize = remoteDebugger.getJShortSize();
javaPrimitiveTypesConfigured = true;
heapBase = remoteDebugger.getHeapBase();
heapOopSize = remoteDebugger.getHeapOopSize();
logMinObjAlignmentInBytes = remoteDebugger.getLogMinObjAlignmentInBytes();
}
catch (RemoteException e) {
throw new DebuggerException(e);
@ -298,12 +301,24 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger {
return (value == 0 ? null : new RemoteAddress(this, value));
}
RemoteAddress readCompOopAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
long value = readCompOopAddressValue(address);
return (value == 0 ? null : new RemoteAddress(this, value));
}
RemoteOopHandle readOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
long value = readAddressValue(address);
return (value == 0 ? null : new RemoteOopHandle(this, value));
}
RemoteOopHandle readCompOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
long value = readCompOopAddressValue(address);
return (value == 0 ? null : new RemoteOopHandle(this, value));
}
boolean areThreadsEqual(Address addr1, Address addr2) {
try {
return remoteDebugger.areThreadsEqual(getAddressValue(addr1), true,

@ -114,6 +114,17 @@ public class RemoteDebuggerServer extends UnicastRemoteObject
return debugger.getJShortSize();
}
public long getHeapBase() throws RemoteException {
return debugger.getHeapBase();
}
public long getHeapOopSize() throws RemoteException {
return debugger.getHeapOopSize();
}
public long getLogMinObjAlignmentInBytes() throws RemoteException {
return debugger.getLogMinObjAlignmentInBytes();
}
public boolean areThreadsEqual(long addrOrId1, boolean isAddress1,
long addrOrId2, boolean isAddress2) throws RemoteException {
ThreadProxy t1 = getThreadProxy(addrOrId1, isAddress1);

@ -72,6 +72,10 @@ class Win32Address implements Address {
return debugger.readAddress(addr + offset);
}
public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompOopAddress(addr + offset);
}
//
// Java-related routines
//
@ -112,6 +116,10 @@ class Win32Address implements Address {
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readOopHandle(addr + offset);
}
public OopHandle getCompOopHandleAt(long offset)
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readCompOopHandle(addr + offset);
}
//
// C/C++-related mutators

@ -45,7 +45,9 @@ public interface Win32Debugger extends JVMDebugger {
public long readCInteger(long address, long numBytes, boolean isUnsigned)
throws DebuggerException;
public Win32Address readAddress(long address) throws DebuggerException;
public Win32Address readCompOopAddress(long address) throws DebuggerException;
public Win32OopHandle readOopHandle(long address) throws DebuggerException;
public Win32OopHandle readCompOopHandle(long address) throws DebuggerException;
public void writeJBoolean(long address, boolean value) throws DebuggerException;
public void writeJByte(long address, byte value) throws DebuggerException;
public void writeJChar(long address, char value) throws DebuggerException;

@ -306,12 +306,22 @@ public class Win32DebuggerLocal extends DebuggerBase implements Win32Debugger {
return (Win32Address) newAddress(readAddressValue(address));
}
public Win32Address readCompOopAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
return (Win32Address) newAddress(readCompOopAddressValue(address));
}
/** From the Win32Debugger interface */
public Win32OopHandle readOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
long value = readAddressValue(address);
return (value == 0 ? null : new Win32OopHandle(this, value));
}
public Win32OopHandle readCompOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
long value = readCompOopAddressValue(address);
return (value == 0 ? null : new Win32OopHandle(this, value));
}
/** From the Win32Debugger interface */
public void writeAddress(long address, Win32Address value) {

@ -72,6 +72,10 @@ class WindbgAddress implements Address {
return debugger.readAddress(addr + offset);
}
public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompOopAddress(addr + offset);
}
//
// Java-related routines
//
@ -113,6 +117,10 @@ class WindbgAddress implements Address {
return debugger.readOopHandle(addr + offset);
}
public OopHandle getCompOopHandleAt(long offset)
throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
return debugger.readCompOopHandle(addr + offset);
}
//
// C/C++-related mutators
//

@ -45,7 +45,9 @@ public interface WindbgDebugger extends JVMDebugger {
public long readCInteger(long address, long numBytes, boolean isUnsigned)
throws DebuggerException;
public WindbgAddress readAddress(long address) throws DebuggerException;
public WindbgAddress readCompOopAddress(long address) throws DebuggerException;
public WindbgOopHandle readOopHandle(long address) throws DebuggerException;
public WindbgOopHandle readCompOopHandle(long address) throws DebuggerException;
// The returned array of register contents is guaranteed to be in
// the same order as in the DbxDebugger for Solaris/x86 or amd64; that is,

@ -39,6 +39,7 @@ import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.debugger.cdbg.basic.BasicDebugEvent;
import sun.jvm.hotspot.utilities.*;
import sun.jvm.hotspot.utilities.memo.*;
import sun.jvm.hotspot.runtime.*;
/** <P> An implementation of the JVMDebugger interface which talks to
windbg and symbol table management is done in Java. </P>
@ -315,12 +316,22 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger
return (WindbgAddress) newAddress(readAddressValue(address));
}
public WindbgAddress readCompOopAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
return (WindbgAddress) newAddress(readCompOopAddressValue(address));
}
/** From the WindbgDebugger interface */
public WindbgOopHandle readOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
long value = readAddressValue(address);
return (value == 0 ? null : new WindbgOopHandle(this, value));
}
public WindbgOopHandle readCompOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
long value = readCompOopAddressValue(address);
return (value == 0 ? null : new WindbgOopHandle(this, value));
}
/** From the WindbgDebugger interface */
public int getAddressSize() {

@ -53,6 +53,8 @@ public class Universe {
// system obj array klass object
private static sun.jvm.hotspot.types.OopField systemObjArrayKlassObjField;
private static AddressField heapBaseField;
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
@ -83,6 +85,8 @@ public class Universe {
doubleArrayKlassObjField = type.getOopField("_doubleArrayKlassObj");
systemObjArrayKlassObjField = type.getOopField("_systemObjArrayKlassObj");
heapBaseField = type.getAddressField("_heap_base");
}
public Universe() {
@ -96,6 +100,14 @@ public class Universe {
}
}
public static long getHeapBase() {
if (heapBaseField.getValue() == null) {
return 0;
} else {
return heapBaseField.getValue().minus(null);
}
}
/** Returns "TRUE" iff "p" points into the allocated area of the heap. */
public boolean isIn(Address p) {
return heap().isIn(p);

@ -47,18 +47,52 @@ public class Array extends Oop {
private static void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("arrayOopDesc");
length = new CIntField(type.getCIntegerField("_length"), 0);
headerSize = type.getSize();
typeSize = (int)type.getSize();
}
// Size of the arrayOopDesc
private static long headerSize;
private static long headerSize=0;
private static long lengthOffsetInBytes=0;
private static long typeSize;
// Fields
private static CIntField length;
private static long headerSizeInBytes() {
if (headerSize != 0) {
return headerSize;
}
if (VM.getVM().isCompressedOopsEnabled()) {
headerSize = typeSize;
} else {
headerSize = VM.getVM().alignUp(typeSize + VM.getVM().getIntSize(),
VM.getVM().getHeapWordSize());
}
return headerSize;
}
private static long headerSize(BasicType type) {
if (Universe.elementTypeShouldBeAligned(type)) {
return alignObjectSize(headerSizeInBytes())/VM.getVM().getHeapWordSize();
} else {
return headerSizeInBytes()/VM.getVM().getHeapWordSize();
}
}
private long lengthOffsetInBytes() {
if (lengthOffsetInBytes != 0) {
return lengthOffsetInBytes;
}
if (VM.getVM().isCompressedOopsEnabled()) {
lengthOffsetInBytes = typeSize - VM.getVM().getIntSize();
} else {
lengthOffsetInBytes = typeSize;
}
return lengthOffsetInBytes;
}
// Accessors for declared fields
public long getLength() { return length.getValue(this); }
public long getLength() {
boolean isUnsigned = true;
return this.getHandle().getCIntegerAt(lengthOffsetInBytes(), VM.getVM().getIntSize(), isUnsigned);
}
public long getObjectSize() {
ArrayKlass klass = (ArrayKlass) getKlass();
@ -72,20 +106,12 @@ public class Array extends Oop {
}
public static long baseOffsetInBytes(BasicType type) {
if (Universe.elementTypeShouldBeAligned(type)) {
return (VM.getVM().isLP64()) ? alignObjectSize(headerSize)
: VM.getVM().alignUp(headerSize, 8);
} else {
return headerSize;
}
return headerSize(type) * VM.getVM().getHeapWordSize();
}
public boolean isArray() { return true; }
public void iterateFields(OopVisitor visitor, boolean doVMFields) {
super.iterateFields(visitor, doVMFields);
if (doVMFields) {
visitor.doCInt(length, true);
}
}
}

@ -31,10 +31,10 @@ import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
// A ConstantPool is an array containing class constants
// A ConstantPool is an oop containing class constants
// as described in the class file
public class ConstantPool extends Array implements ClassConstants {
public class ConstantPool extends Oop implements ClassConstants {
// Used for debugging this code
private static final boolean DEBUG = false;
@ -55,8 +55,9 @@ public class ConstantPool extends Array implements ClassConstants {
tags = new OopField(type.getOopField("_tags"), 0);
cache = new OopField(type.getOopField("_cache"), 0);
poolHolder = new OopField(type.getOopField("_pool_holder"), 0);
length = new CIntField(type.getCIntegerField("_length"), 0);
headerSize = type.getSize();
elementSize = db.getOopSize();
elementSize = 0;
}
ConstantPool(OopHandle handle, ObjectHeap heap) {
@ -68,7 +69,7 @@ public class ConstantPool extends Array implements ClassConstants {
private static OopField tags;
private static OopField cache;
private static OopField poolHolder;
private static CIntField length; // number of elements in oop
private static long headerSize;
private static long elementSize;
@ -76,12 +77,22 @@ public class ConstantPool extends Array implements ClassConstants {
public TypeArray getTags() { return (TypeArray) tags.getValue(this); }
public ConstantPoolCache getCache() { return (ConstantPoolCache) cache.getValue(this); }
public Klass getPoolHolder() { return (Klass) poolHolder.getValue(this); }
public int getLength() { return (int)length.getValue(this); }
private long getElementSize() {
if (elementSize !=0 ) {
return elementSize;
} else {
elementSize = VM.getVM().getOopSize();
}
return elementSize;
}
private long indexOffset(long index) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(index > 0 && index < getLength(), "invalid cp index");
Assert.that(index > 0 && index < getLength(), "invalid cp index " + index + " " + getLength());
}
return (index * elementSize) + headerSize;
return (index * getElementSize()) + headerSize;
}
public ConstantTag getTagAt(long index) {
@ -464,7 +475,7 @@ public class ConstantPool extends Array implements ClassConstants {
}
public long getObjectSize() {
return alignObjectSize(headerSize + (getLength() * elementSize));
return alignObjectSize(headerSize + (getLength() * getElementSize()));
}
//----------------------------------------------------------------------

@ -31,10 +31,10 @@ import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
// A ConstantPool is an array containing class constants
// as described in the class file
public class ConstantPoolCache extends Array {
// ConstantPoolCache : A constant pool cache (constantPoolCacheOopDesc).
// See cpCacheOop.hpp for details about this class.
//
public class ConstantPoolCache extends Oop {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
@ -47,9 +47,9 @@ public class ConstantPoolCache extends Array {
Type type = db.lookupType("constantPoolCacheOopDesc");
constants = new OopField(type.getOopField("_constant_pool"), 0);
baseOffset = type.getSize();
Type elType = db.lookupType("ConstantPoolCacheEntry");
elementSize = elType.getSize();
length = new CIntField(type.getCIntegerField("_length"), 0);
}
ConstantPoolCache(OopHandle handle, ObjectHeap heap) {
@ -62,6 +62,8 @@ public class ConstantPoolCache extends Array {
private static long baseOffset;
private static long elementSize;
private static CIntField length;
public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
@ -87,6 +89,10 @@ public class ConstantPoolCache extends Array {
tty.print("ConstantPoolCache for " + getConstants().getPoolHolder().getName().asString());
}
public int getLength() {
return (int) length.getValue(this);
}
public void iterateFields(OopVisitor visitor, boolean doVMFields) {
super.iterateFields(visitor, doVMFields);
if (doVMFields) {

@ -32,7 +32,7 @@ import sun.jvm.hotspot.types.*;
// A ConstantPoolCacheKlass is the klass of a ConstantPoolCache
public class ConstantPoolCacheKlass extends ArrayKlass {
public class ConstantPoolCacheKlass extends Klass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
@ -43,13 +43,20 @@ public class ConstantPoolCacheKlass extends ArrayKlass {
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("constantPoolCacheKlass");
headerSize = type.getSize() + Oop.getHeaderSize();
}
ConstantPoolCacheKlass(OopHandle handle, ObjectHeap heap) {
super(handle, heap);
}
public long getObjectSize() { return alignObjectSize(headerSize); }
public void printValueOn(PrintStream tty) {
tty.print("ConstantPoolCacheKlass");
}
private static long headerSize;
}

@ -32,7 +32,7 @@ import sun.jvm.hotspot.types.*;
// A ConstantPoolKlass is the klass of a ConstantPool
public class ConstantPoolKlass extends ArrayKlass {
public class ConstantPoolKlass extends Klass {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
@ -43,13 +43,19 @@ public class ConstantPoolKlass extends ArrayKlass {
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("constantPoolKlass");
headerSize = type.getSize() + Oop.getHeaderSize();
}
ConstantPoolKlass(OopHandle handle, ObjectHeap heap) {
super(handle, heap);
}
public long getObjectSize() { return alignObjectSize(headerSize); }
public void printValueOn(PrintStream tty) {
tty.print("ConstantPoolKlass");
}
};
private static long headerSize;
}

@ -46,6 +46,7 @@ public class DefaultOopVisitor implements OopVisitor {
// Callback methods for each field type in an object
public void doOop(OopField field, boolean isVMField) {}
public void doOop(NarrowOopField field, boolean isVMField) {}
public void doByte(ByteField field, boolean isVMField) {}
public void doChar(CharField field, boolean isVMField) {}
public void doBoolean(BooleanField field, boolean isVMField) {}

@ -40,15 +40,26 @@ public class Instance extends Oop {
}
});
}
private static long typeSize;
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("instanceOopDesc");
typeSize = type.getSize();
}
Instance(OopHandle handle, ObjectHeap heap) {
super(handle, heap);
}
// Returns header size in bytes.
public static long getHeaderSize() {
if (VM.getVM().isCompressedOopsEnabled()) {
return typeSize - VM.getVM().getIntSize();
} else {
return typeSize;
}
}
public boolean isInstance() { return true; }
public void iterateFields(OopVisitor visitor, boolean doVMFields) {

@ -467,7 +467,6 @@ public class InstanceKlass extends Klass {
for (int index = 0; index < length; index += NEXT_OFFSET) {
short accessFlags = fields.getShortAt(index + ACCESS_FLAGS_OFFSET);
short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex));
AccessFlags access = new AccessFlags(accessFlags);
if (access.isStatic()) {
@ -790,7 +789,11 @@ public class InstanceKlass extends Klass {
short signatureIndex = fields.getShortAt(index + SIGNATURE_INDEX_OFFSET);
FieldType type = new FieldType((Symbol) getConstants().getObjAt(signatureIndex));
if (type.isOop()) {
return new OopField(this, index);
if (VM.getVM().isCompressedOopsEnabled()) {
return new NarrowOopField(this, index);
} else {
return new OopField(this, index);
}
}
if (type.isByte()) {
return new ByteField(this, index);

@ -171,8 +171,7 @@ public class Klass extends Oop implements ClassConstants {
}
public long getObjectSize() {
System.out.println("should not reach here");
return 0;
throw new RuntimeException("should not reach here");
}
/** Array class with specific rank */

@ -0,0 +1,55 @@
/*
* Copyright 2000-2008 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.
*
*/
package sun.jvm.hotspot.oops;
import sun.jvm.hotspot.debugger.*;
// The class for an oop field simply provides access to the value.
public class NarrowOopField extends OopField {
public NarrowOopField(FieldIdentifier id, long offset, boolean isVMField) {
super(id, offset, isVMField);
}
public NarrowOopField(sun.jvm.hotspot.types.OopField vmField, long startOffset) {
super(new NamedFieldIdentifier(vmField.getName()), vmField.getOffset() + startOffset, true);
}
public NarrowOopField(InstanceKlass holder, int fieldArrayIndex) {
super(holder, fieldArrayIndex);
}
public Oop getValue(Oop obj) {
return obj.getHeap().newOop(getValueAsOopHandle(obj));
}
/** Debugging support */
public OopHandle getValueAsOopHandle(Oop obj) {
return obj.getHandle().getCompOopHandleAt(getOffset());
}
public void setValue(Oop obj) throws MutationException {
// Fix this: setOopAt is missing in Address
}
}

@ -43,7 +43,7 @@ public class ObjArray extends Array {
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("objArrayOopDesc");
elementSize = db.getOopSize();
elementSize = VM.getVM().getHeapOopSize();
}
ObjArray(OopHandle handle, ObjectHeap heap) {
@ -54,9 +54,17 @@ public class ObjArray extends Array {
private static long elementSize;
public Oop getObjAt(long index) {
public OopHandle getOopHandleAt(long index) {
long offset = baseOffsetInBytes(BasicType.T_OBJECT) + (index * elementSize);
return getHeap().newOop(getHandle().getOopHandleAt(offset));
if (VM.getVM().isCompressedOopsEnabled()) {
return getHandle().getCompOopHandleAt(offset);
} else {
return getHandle().getOopHandleAt(offset);
}
}
public Oop getObjAt(long index) {
return getHeap().newOop(getOopHandleAt(index));
}
public void printValueOn(PrintStream tty) {
@ -69,7 +77,13 @@ public class ObjArray extends Array {
long baseOffset = baseOffsetInBytes(BasicType.T_OBJECT);
for (int index = 0; index < length; index++) {
long offset = baseOffset + (index * elementSize);
visitor.doOop(new OopField(new IndexableFieldIdentifier(index), offset, false), false);
OopField field;
if (VM.getVM().isCompressedOopsEnabled()) {
field = new NarrowOopField(new IndexableFieldIdentifier(index), offset, false);
} else {
field = new OopField(new IndexableFieldIdentifier(index), offset, false);
}
visitor.doOop(field, false);
}
}
}

@ -41,6 +41,12 @@ import sun.jvm.hotspot.utilities.*;
public class ObjectHeap {
private static final boolean DEBUG;
static {
DEBUG = System.getProperty("sun.jvm.hotspot.oops.ObjectHeap.DEBUG") != null;
}
private OopHandle symbolKlassHandle;
private OopHandle methodKlassHandle;
private OopHandle constMethodKlassHandle;
@ -152,7 +158,7 @@ public class ObjectHeap {
public ObjectHeap(TypeDataBase db) throws WrongTypeException {
// Get commonly used sizes of basic types
oopSize = db.getOopSize();
oopSize = VM.getVM().getOopSize();
byteSize = db.getJByteType().getSize();
charSize = db.getJCharType().getSize();
booleanSize = db.getJBooleanType().getSize();
@ -440,12 +446,16 @@ public class ObjectHeap {
try {
// Traverses the space from bottom to top
OopHandle handle = bottom.addOffsetToAsOopHandle(0);
while (handle.lessThan(top)) {
Oop obj = null;
try {
obj = newOop(handle);
} catch (UnknownOopException exp) {
if (DEBUG) {
throw new RuntimeException(" UnknownOopException " + exp);
}
}
if (obj == null) {
//Find the object size using Printezis bits and skip over

@ -64,8 +64,17 @@ public class ObjectHistogram implements HeapVisitor {
List list = getElements();
ObjectHistogramElement.titleOn(tty);
Iterator iterator = list.listIterator();
int num=0;
int totalCount=0;
int totalSize=0;
while (iterator.hasNext()) {
((ObjectHistogramElement) iterator.next()).printOn(tty);
ObjectHistogramElement el = (ObjectHistogramElement) iterator.next();
num++;
totalCount+=el.getCount();
totalSize+=el.getSize();
tty.print(num + ":" + "\t\t");
el.printOn(tty);
}
tty.println("Total : " + "\t" + totalCount + "\t" + totalSize);
}
}

@ -110,12 +110,12 @@ public class ObjectHistogramElement {
public static void titleOn(PrintStream tty) {
tty.println("Object Histogram:");
tty.println();
tty.println("Size" + "\t" + "Count" + "\t" + "Class description");
tty.println("-------------------------------------------------------");
tty.println("num " + "\t" + " #instances" + "\t" + "#bytes" + "\t" + "Class description");
tty.println("--------------------------------------------------------------------------");
}
public void printOn(PrintStream tty) {
tty.print(size + "\t" + count + "\t");
tty.print(count + "\t" + size + "\t");
tty.print(getDescription());
tty.println();
}

@ -47,7 +47,8 @@ public class Oop {
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("oopDesc");
mark = new CIntField(type.getCIntegerField("_mark"), 0);
klass = new OopField(type.getOopField("_klass"), 0);
klass = new OopField(type.getOopField("_metadata._klass"), 0);
compressedKlass = new NarrowOopField(type.getOopField("_metadata._compressed_klass"), 0);
headerSize = type.getSize();
}
@ -67,10 +68,11 @@ public class Oop {
public OopHandle getHandle() { return handle; }
private static long headerSize;
public static long getHeaderSize() { return headerSize; }
public static long getHeaderSize() { return headerSize; } // Header size in bytes.
private static CIntField mark;
private static OopField klass;
private static NarrowOopField compressedKlass;
public boolean isShared() {
return CompactingPermGenGen.isShared(handle);
@ -86,7 +88,13 @@ public class Oop {
// Accessors for declared fields
public Mark getMark() { return new Mark(getHandle()); }
public Klass getKlass() { return (Klass) klass.getValue(this); }
public Klass getKlass() {
if (VM.getVM().isCompressedOopsEnabled()) {
return (Klass) compressedKlass.getValue(this);
} else {
return (Klass) klass.getValue(this);
}
}
public boolean isA(Klass k) {
return getKlass().isSubtypeOf(k);
@ -120,7 +128,7 @@ public class Oop {
// Align the object size.
public static long alignObjectSize(long size) {
return VM.getVM().alignUp(size, VM.getVM().getMinObjAlignmentInBytes());
return VM.getVM().alignUp(size, VM.getVM().getMinObjAlignment());
}
// All vm's align longs, so pad out certain offsets.
@ -163,7 +171,11 @@ public class Oop {
void iterateFields(OopVisitor visitor, boolean doVMFields) {
if (doVMFields) {
visitor.doCInt(mark, true);
visitor.doOop(klass, true);
if (VM.getVM().isCompressedOopsEnabled()) {
visitor.doOop(compressedKlass, true);
} else {
visitor.doOop(klass, true);
}
}
}
@ -219,6 +231,10 @@ public class Oop {
if (handle == null) {
return null;
}
return handle.getOopHandleAt(klass.getOffset());
if (VM.getVM().isCompressedOopsEnabled()) {
return handle.getCompOopHandleAt(compressedKlass.getOffset());
} else {
return handle.getOopHandleAt(klass.getOffset());
}
}
};

@ -57,6 +57,13 @@ public class OopPrinter implements OopVisitor {
Oop.printOopValueOn(field.getValue(getObj()), tty);
tty.println();
}
public void doOop(NarrowOopField field, boolean isVMField) {
printField(field);
Oop.printOopValueOn(field.getValue(getObj()), tty);
tty.println();
}
public void doChar(CharField field, boolean isVMField) {
printField(field);
char c = field.getValue(getObj());

@ -281,8 +281,11 @@ public class OopUtilities implements /* imports */ JVMTIThreadState {
} catch (RuntimeException re) {
// ignore, currently java_lang_Class::hc_klass_offset is zero
}
hcKlassField = new OopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true);
if (VM.getVM().isCompressedOopsEnabled()) {
hcKlassField = new NarrowOopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true);
} else {
hcKlassField = new OopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true);
}
}
}

@ -41,6 +41,7 @@ public interface OopVisitor {
// Callback methods for each field type in an object
public void doOop(OopField field, boolean isVMField);
public void doOop(NarrowOopField field, boolean isVMField);
public void doByte(ByteField field, boolean isVMField);
public void doChar(CharField field, boolean isVMField);
public void doBoolean(BooleanField field, boolean isVMField);

@ -31,4 +31,5 @@ import sun.jvm.hotspot.debugger.*;
public interface AddressVisitor {
public void visitAddress(Address addr);
public void visitCompOopAddress(Address addr);
}

@ -534,7 +534,8 @@ public abstract class Frame implements Cloneable {
public void visitValueLocation(Address valueAddr) {
}
public void visitDeadLocation(Address deadAddr) {
public void visitNarrowOopLocation(Address compOopAddr) {
addressVisitor.visitCompOopAddress(compOopAddr);
}
}

@ -36,6 +36,7 @@ import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
import sun.jvm.hotspot.runtime.*;
/** <P> This class encapsulates the global state of the VM; the
universe, object heap, interpreter, etc. It is a Singleton and
@ -93,6 +94,10 @@ public class VM {
private boolean isLP64;
private int bytesPerLong;
private int minObjAlignmentInBytes;
private int logMinObjAlignmentInBytes;
private int heapWordSize;
private int heapOopSize;
private int oopSize;
/** This is only present in a non-core build */
private CodeCache codeCache;
/** This is only present in a C1 build */
@ -117,6 +122,7 @@ public class VM {
private static Type uintxType;
private static CIntegerType boolType;
private Boolean sharingEnabled;
private Boolean compressedOopsEnabled;
// command line flags supplied to VM - see struct Flag in globals.hpp
public static final class Flag {
@ -308,6 +314,11 @@ public class VM {
}
bytesPerLong = db.lookupIntConstant("BytesPerLong").intValue();
minObjAlignmentInBytes = db.lookupIntConstant("MinObjAlignmentInBytes").intValue();
// minObjAlignment = db.lookupIntConstant("MinObjAlignment").intValue();
logMinObjAlignmentInBytes = db.lookupIntConstant("LogMinObjAlignmentInBytes").intValue();
heapWordSize = db.lookupIntConstant("HeapWordSize").intValue();
oopSize = db.lookupIntConstant("oopSize").intValue();
heapOopSize = db.lookupIntConstant("heapOopSize").intValue();
intxType = db.lookupType("intx");
uintxType = db.lookupType("uintx");
@ -331,6 +342,8 @@ public class VM {
throw new RuntimeException("Attempt to initialize VM twice");
}
soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian());
debugger.putHeapConst(Universe.getHeapBase(), soleInstance.getHeapOopSize(),
soleInstance.logMinObjAlignmentInBytes);
for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) {
((Observer) iter.next()).update(null, null);
}
@ -440,13 +453,17 @@ public class VM {
}
public long getOopSize() {
return db.getOopSize();
return oopSize;
}
public long getLogAddressSize() {
return logAddressSize;
}
public long getIntSize() {
return db.getJIntType().getSize();
}
/** NOTE: this offset is in BYTES in this system! */
public long getStackBias() {
return stackBias;
@ -467,10 +484,24 @@ public class VM {
}
/** Get minimum object alignment in bytes. */
public int getMinObjAlignmentInBytes() {
public int getMinObjAlignment() {
return minObjAlignmentInBytes;
}
public int getMinObjAlignmentInBytes() {
return minObjAlignmentInBytes;
}
public int getLogMinObjAlignmentInBytes() {
return logMinObjAlignmentInBytes;
}
public int getHeapWordSize() {
return heapWordSize;
}
public int getHeapOopSize() {
return heapOopSize;
}
/** Utility routine for getting data structure alignment correct */
public long alignUp(long size, long alignment) {
return (size + alignment - 1) & ~(alignment - 1);
@ -701,6 +732,14 @@ public class VM {
return sharingEnabled.booleanValue();
}
public boolean isCompressedOopsEnabled() {
if (compressedOopsEnabled == null) {
Flag flag = getCommandLineFlag("UseCompressedOops");
compressedOopsEnabled = (flag == null) ? Boolean.FALSE:
(flag.getBool()? Boolean.TRUE: Boolean.FALSE);
}
return compressedOopsEnabled.booleanValue();
}
// returns null, if not available.
public Flag[] getCommandLineFlags() {

@ -109,6 +109,8 @@ public interface Field {
public Address getAddress (Address addr) throws UnmappedAddressException, UnalignedAddressException, WrongTypeException;
public OopHandle getOopHandle(Address addr)
throws UnmappedAddressException, UnalignedAddressException, WrongTypeException, NotInHeapException;
public OopHandle getNarrowOopHandle(Address addr)
throws UnmappedAddressException, UnalignedAddressException, WrongTypeException, NotInHeapException;
/** <P> These accessors require that the field be static; otherwise,
a WrongTypeException will be thrown. Note that type checking is
@ -138,4 +140,6 @@ public interface Field {
public Address getAddress () throws UnmappedAddressException, UnalignedAddressException;
public OopHandle getOopHandle()
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException;
public OopHandle getNarrowOopHandle()
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException;
}

@ -0,0 +1,41 @@
/*
* Copyright 2008 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.
*
*/
package sun.jvm.hotspot.types;
import sun.jvm.hotspot.debugger.*;
/** A specialization of Field which represents a field containing an
narrow oop value and which adds typechecked getValue() routines returning
OopHandles. */
public interface NarrowOopField extends OopField {
/** The field must be nonstatic and the type of the field must be an
oop type, or a WrongTypeException will be thrown. */
public OopHandle getValue(Address addr) throws UnmappedAddressException, UnalignedAddressException, WrongTypeException;
/** The field must be static and the type of the field must be an
oop type, or a WrongTypeException will be thrown. */
public OopHandle getValue() throws UnmappedAddressException, UnalignedAddressException, WrongTypeException;
}

@ -122,5 +122,6 @@ public interface Type {
public JShortField getJShortField (String fieldName) throws WrongTypeException;
public CIntegerField getCIntegerField (String fieldName) throws WrongTypeException;
public OopField getOopField (String fieldName) throws WrongTypeException;
public NarrowOopField getNarrowOopField (String fieldName) throws WrongTypeException;
public AddressField getAddressField (String fieldName);
}

@ -43,6 +43,19 @@ public class BasicField implements Field {
/** Used for static fields only */
private Address staticFieldAddress;
// Copy constructor to create NarrowOopField from OopField.
public BasicField(Field fld) {
BasicField field = (BasicField)fld;
this.db = field.db;
this.containingType = field.containingType;
this.name = field.name;
this.type = field.type;
this.size = field.size;
this.isStatic = field.isStatic;
this.offset = field.offset;
this.staticFieldAddress = field.staticFieldAddress;
}
/** offsetInBytes is ignored if the field is static;
staticFieldAddress is used only if the field is static. */
public BasicField(BasicTypeDataBase db, Type containingType, String name, Type type,
@ -161,6 +174,13 @@ public class BasicField implements Field {
}
return addr.getOopHandleAt(offset);
}
public OopHandle getNarrowOopHandle(Address addr)
throws UnmappedAddressException, UnalignedAddressException, WrongTypeException, NotInHeapException {
if (isStatic) {
throw new WrongTypeException();
}
return addr.getCompOopHandleAt(offset);
}
//--------------------------------------------------------------------------------
// Dereferencing operations for static fields
@ -234,4 +254,11 @@ public class BasicField implements Field {
}
return staticFieldAddress.getOopHandleAt(0);
}
public OopHandle getNarrowOopHandle()
throws UnmappedAddressException, UnalignedAddressException, WrongTypeException, NotInHeapException {
if (!isStatic) {
throw new WrongTypeException();
}
return staticFieldAddress.getCompOopHandleAt(0);
}
}

@ -95,6 +95,10 @@ public class BasicFieldWrapper implements Field {
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
return field.getOopHandle(addr);
}
public OopHandle getNarrowOopHandle(Address addr)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
return field.getNarrowOopHandle(addr);
}
public boolean getJBoolean () throws UnmappedAddressException, UnalignedAddressException, WrongTypeException {
return field.getJBoolean();
@ -130,4 +134,8 @@ public class BasicFieldWrapper implements Field {
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
return field.getOopHandle();
}
public OopHandle getNarrowOopHandle()
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
return field.getNarrowOopHandle();
}
}

@ -0,0 +1,65 @@
/*
* Copyright 2008 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.
*
*/
package sun.jvm.hotspot.types.basic;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.types.*;
/** A specialization of BasicField which represents a field containing
an oop value and which adds typechecked getValue() routines
returning OopHandles. */
public class BasicNarrowOopField extends BasicOopField implements NarrowOopField {
private static final boolean DEBUG = false;
public BasicNarrowOopField (OopField oopf) {
super(oopf);
}
public BasicNarrowOopField(BasicTypeDataBase db, Type containingType, String name, Type type,
boolean isStatic, long offset, Address staticFieldAddress) {
super(db, containingType, name, type, isStatic, offset, staticFieldAddress);
if (DEBUG) {
System.out.println(" name " + name + " type " + type + " isStatic " + isStatic + " offset " + offset + " static addr " + staticFieldAddress);
}
if (!type.isOopType()) {
throw new WrongTypeException("Type of a BasicOopField must be an oop type");
}
}
/** The field must be nonstatic and the type of the field must be a
Java oop, or a WrongTypeException will be thrown. */
public OopHandle getValue(Address addr) throws UnmappedAddressException, UnalignedAddressException, WrongTypeException {
return getNarrowOopHandle(addr);
}
/** The field must be static and the type of the field must be a
Java oop, or a WrongTypeException will be thrown. */
public OopHandle getValue() throws UnmappedAddressException, UnalignedAddressException, WrongTypeException {
return getNarrowOopHandle();
}
}

@ -32,6 +32,12 @@ import sun.jvm.hotspot.types.*;
returning OopHandles. */
public class BasicOopField extends BasicField implements OopField {
public BasicOopField(OopField oopf) {
super(oopf);
}
public BasicOopField(BasicTypeDataBase db, Type containingType, String name, Type type,
boolean isStatic, long offset, Address staticFieldAddress) {
super(db, containingType, name, type, isStatic, offset, staticFieldAddress);

@ -273,6 +273,10 @@ public class BasicType implements Type {
return (OopField) field;
}
public NarrowOopField getNarrowOopField(String fieldName) throws WrongTypeException {
return (NarrowOopField) new BasicNarrowOopField(getOopField(fieldName));
}
public AddressField getAddressField(String fieldName) {
// This type can not be inferred (for now), so provide a wrapper
Field field = getField(fieldName);
@ -287,7 +291,7 @@ public class BasicType implements Type {
name was already present in this class. */
public void addField(Field field) {
if (nameToFieldMap.get(field.getName()) != null) {
throw new RuntimeException("field of name \"" + field.getName() + "\" already present");
throw new RuntimeException("field of name \"" + field.getName() + "\" already present in type " + this);
}
nameToFieldMap.put(field.getName(), field);

@ -27,6 +27,7 @@ package sun.jvm.hotspot.types.basic;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.runtime.VM;
/** <P> This is a basic implementation of the TypeDataBase interface.
It allows an external type database builder to add types to be
@ -146,7 +147,7 @@ public class BasicTypeDataBase implements TypeDataBase {
}
public long getOopSize() {
return machDesc.getOopSize();
return VM.getVM().getOopSize();
}
public boolean addressTypeIsEqualToType(Address addr, Type type) {

@ -92,7 +92,17 @@ public class FindInHeapPanel extends JPanel {
iterated += addressSize;
updateProgressBar();
}
public void visitCompOopAddress(Address addr) {
if (error) return;
Address val = addr.getCompOopAddressAt(0);
if (AddressOps.equal(val, value)) {
error = reportResult(addr);
}
iterated += addressSize;
updateProgressBar();
}
public void epilogue() {
iterated = 0;
updateProgressBar();

@ -1077,8 +1077,8 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
oms = new OopMapStream(map, OopMapValue.OopTypes.VALUE_VALUE);
buf.append(omvIterator.iterate(oms, "Value:", false));
oms = new OopMapStream(map, OopMapValue.OopTypes.DEAD_VALUE);
buf.append(omvIterator.iterate(oms, "Dead:", false));
oms = new OopMapStream(map, OopMapValue.OopTypes.NARROWOOP_VALUE);
buf.append(omvIterator.iterate(oms, "Oop:", false));
oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE);
buf.append(omvIterator.iterate(oms, "Callee saved:", true));

@ -155,6 +155,9 @@ public abstract class AbstractHeapGraphWriter implements HeapGraphWriter {
} catch (IOException exp) {
throw new RuntimeException(exp);
}
}
public void visitCompOopAddress(Address handleAddr) {
throw new RuntimeException("Should not reach here. JNIHandles are not compressed");
}
});
} catch (RuntimeException re) {

@ -574,6 +574,10 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
throw new RuntimeException(exp);
}
}
public void visitCompOopAddress(Address handleAddr) {
throw new RuntimeException(
" Should not reach here. JNIHandles are not compressed \n");
}
});
} catch (RuntimeException re) {
handleRuntimeException(re);
@ -601,8 +605,7 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
writeObjectID(array.getKlass().getJavaMirror());
final int length = (int) array.getLength();
for (int index = 0; index < length; index++) {
long offset = OBJECT_BASE_OFFSET + index * OBJ_ID_SIZE;
OopHandle handle = array.getHandle().getOopHandleAt(offset);
OopHandle handle = array.getOopHandleAt(index);
writeObjectID(getAddressValue(handle));
}
}
@ -803,8 +806,13 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
break;
case JVM_SIGNATURE_CLASS:
case JVM_SIGNATURE_ARRAY: {
OopHandle handle = ((OopField)field).getValueAsOopHandle(oop);
writeObjectID(getAddressValue(handle));
if (VM.getVM().isCompressedOopsEnabled()) {
OopHandle handle = ((NarrowOopField)field).getValueAsOopHandle(oop);
writeObjectID(getAddressValue(handle));
} else {
OopHandle handle = ((OopField)field).getValueAsOopHandle(oop);
writeObjectID(getAddressValue(handle));
}
break;
}
default:

@ -282,6 +282,15 @@ public class ReversePtrsAnalysis {
markAndTraverse(next);
}
public void visitCompOopAddress(Address addr) {
Oop next = heap.newOop(addr.getCompOopHandleAt(0));
LivenessPathElement lp = new LivenessPathElement(null,
new NamedFieldIdentifier(baseRootDescription +
" @ " + addr));
rp.put(lp, next);
markAndTraverse(next);
}
private String baseRootDescription;
}

@ -51,7 +51,11 @@ public class RobustOopDeterminator {
private static void initialize(TypeDataBase db) {
Type type = db.lookupType("oopDesc");
klassField = type.getOopField("_klass");
if (VM.getVM().isCompressedOopsEnabled()) {
klassField = type.getNarrowOopField("_metadata._compressed_klass");
} else {
klassField = type.getOopField("_metadata._klass");
}
}
public static boolean oopLooksValid(OopHandle oop) {

@ -85,6 +85,9 @@ C1_VM_TARGETS=product1 fastdebug1 optimized1 jvmg1
C2_VM_TARGETS=product fastdebug optimized jvmg
KERNEL_VM_TARGETS=productkernel fastdebugkernel optimizedkernel jvmgkernel
# JDK directory list
JDK_DIRS=bin include jre lib demo
all: all_product all_fastdebug
all_product: product product1 productkernel docs export_product
all_fastdebug: fastdebug fastdebug1 fastdebugkernel docs export_fastdebug
@ -341,7 +344,7 @@ copy_product_jdk:
$(RM) -r $(JDK_IMAGE_DIR)
$(MKDIR) -p $(JDK_IMAGE_DIR)
($(CD) $(JDK_IMPORT_PATH) && \
$(TAR) -cf - bin include jre lib) | \
$(TAR) -cf - $(JDK_DIRS)) | \
($(CD) $(JDK_IMAGE_DIR) && $(TAR) -xf -)
copy_fastdebug_jdk:
@ -349,11 +352,11 @@ copy_fastdebug_jdk:
$(MKDIR) -p $(JDK_IMAGE_DIR)/fastdebug
if [ -d $(JDK_IMPORT_PATH)/fastdebug ] ; then \
($(CD) $(JDK_IMPORT_PATH)/fastdebug && \
$(TAR) -cf - bin include jre lib) | \
$(TAR) -cf - $(JDK_DIRS)) | \
($(CD) $(JDK_IMAGE_DIR)/fastdebug && $(TAR) -xf -) ; \
else \
($(CD) $(JDK_IMPORT_PATH) && \
$(TAR) -cf - bin include jre lib) | \
$(TAR) -cf - $(JDK_DIRS)) | \
($(CD) $(JDK_IMAGE_DIR)/fastdebug && $(TAR) -xf -) ; \
fi
@ -362,15 +365,15 @@ copy_debug_jdk:
$(MKDIR) -p $(JDK_IMAGE_DIR)/debug
if [ -d $(JDK_IMPORT_PATH)/debug ] ; then \
($(CD) $(JDK_IMPORT_PATH)/debug && \
$(TAR) -cf - bin include jre lib) | \
$(TAR) -cf - $(JDK_DIRS)) | \
($(CD) $(JDK_IMAGE_DIR)/debug && $(TAR) -xf -) ; \
elif [ -d $(JDK_IMPORT_PATH)/fastdebug ] ; then \
($(CD) $(JDK_IMPORT_PATH)/fastdebug && \
$(TAR) -cf - bin include jre lib) | \
$(TAR) -cf - $(JDK_DIRS)) | \
($(CD) $(JDK_IMAGE_DIR)/debug && $(TAR) -xf -) ; \
else \
($(CD) $(JDK_IMPORT_PATH) && \
$(TAR) -cf - bin include jre lib) | \
$(TAR) -cf - $(JDK_DIRS)) | \
($(CD) $(JDK_IMAGE_DIR)/debug && $(TAR) -xf -) ; \
fi

@ -185,6 +185,12 @@ CFLAGS += $(GAMMADIR)/src/os_cpu/solaris_${Platform_arch}/vm/solaris_${Platform_
# no more exceptions
CFLAGS/NOEX=-features=no%except
# avoid compilation problems arising from fact that C++ compiler tries
# to search for external template definition by just compiling additional
# source files in th same context
CFLAGS += -template=no%extdef
# Reduce code bloat by reverting back to 5.0 behavior for static initializers
CFLAGS += -features=no%split_init

@ -1779,7 +1779,7 @@ void MacroAssembler::verify_oop_subroutine() {
// Check the klassOop of this object for being in the right area of memory.
// Cannot do the load in the delay above slot in case O0 is null
ld_ptr(Address(O0_obj, 0, oopDesc::klass_offset_in_bytes()), O0_obj);
load_klass(O0_obj, O0_obj);
// assert((klass & klass_mask) == klass_bits);
if( Universe::verify_klass_mask() != Universe::verify_oop_mask() )
set(Universe::verify_klass_mask(), O2_mask);
@ -1788,8 +1788,9 @@ void MacroAssembler::verify_oop_subroutine() {
and3(O0_obj, O2_mask, O4_temp);
cmp(O4_temp, O3_bits);
brx(notEqual, false, pn, fail);
delayed()->nop();
// Check the klass's klass
delayed()->ld_ptr(Address(O0_obj, 0, oopDesc::klass_offset_in_bytes()), O0_obj);
load_klass(O0_obj, O0_obj);
and3(O0_obj, O2_mask, O4_temp);
cmp(O4_temp, O3_bits);
brx(notEqual, false, pn, fail);
@ -2588,8 +2589,9 @@ void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, R
and3(mark_reg, markOopDesc::biased_lock_mask_in_place, temp_reg);
cmp(temp_reg, markOopDesc::biased_lock_pattern);
brx(Assembler::notEqual, false, Assembler::pn, cas_label);
delayed()->nop();
delayed()->ld_ptr(Address(obj_reg, 0, oopDesc::klass_offset_in_bytes()), temp_reg);
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);
or3(G2_thread, temp_reg, temp_reg);
xor3(mark_reg, temp_reg, temp_reg);
@ -2668,7 +2670,7 @@ void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, R
//
// FIXME: due to a lack of registers we currently blow away the age
// bits in this situation. Should attempt to preserve them.
ld_ptr(Address(obj_reg, 0, oopDesc::klass_offset_in_bytes()), temp_reg);
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);
or3(G2_thread, temp_reg, temp_reg);
casx_under_lock(mark_addr.base(), mark_reg, temp_reg,
@ -2700,7 +2702,7 @@ void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg, R
//
// FIXME: due to a lack of registers we currently blow away the age
// bits in this situation. Should attempt to preserve them.
ld_ptr(Address(obj_reg, 0, oopDesc::klass_offset_in_bytes()), temp_reg);
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);
casx_under_lock(mark_addr.base(), mark_reg, temp_reg,
(address)StubRoutines::Sparc::atomic_memory_operation_lock_addr());
@ -3406,7 +3408,7 @@ void MacroAssembler::tlab_refill(Label& retry, Label& try_eden, Label& slow_case
// set klass to intArrayKlass
set((intptr_t)Universe::intArrayKlassObj_addr(), t2);
ld_ptr(t2, 0, t2);
st_ptr(t2, top, oopDesc::klass_offset_in_bytes());
store_klass(t2, top);
sub(t1, typeArrayOopDesc::header_size(T_INT), t1);
add(t1, ThreadLocalAllocBuffer::alignment_reserve(), t1);
sll_ptr(t1, log2_intptr(HeapWordSize/sizeof(jint)), t1);
@ -3534,3 +3536,139 @@ void MacroAssembler::bang_stack_size(Register Rsize, Register Rtsp,
st(G0, Rtsp, Rscratch);
}
}
void MacroAssembler::load_klass(Register s, Register d) {
// The number of bytes in this code is used by
// MachCallDynamicJavaNode::ret_addr_offset()
// if this changes, change that.
if (UseCompressedOops) {
lduw(s, oopDesc::klass_offset_in_bytes(), d);
decode_heap_oop_not_null(d);
} else {
ld_ptr(s, oopDesc::klass_offset_in_bytes(), d);
}
}
// ??? figure out src vs. dst!
void MacroAssembler::store_klass(Register d, Register s1) {
if (UseCompressedOops) {
assert(s1 != d, "not enough registers");
encode_heap_oop_not_null(d);
// Zero out entire klass field first.
st_ptr(G0, s1, oopDesc::klass_offset_in_bytes());
st(d, s1, oopDesc::klass_offset_in_bytes());
} else {
st_ptr(d, s1, oopDesc::klass_offset_in_bytes());
}
}
void MacroAssembler::load_heap_oop(const Address& s, Register d, int offset) {
if (UseCompressedOops) {
lduw(s, d, offset);
decode_heap_oop(d);
} else {
ld_ptr(s, d, offset);
}
}
void MacroAssembler::load_heap_oop(Register s1, Register s2, Register d) {
if (UseCompressedOops) {
lduw(s1, s2, d);
decode_heap_oop(d, d);
} else {
ld_ptr(s1, s2, d);
}
}
void MacroAssembler::load_heap_oop(Register s1, int simm13a, Register d) {
if (UseCompressedOops) {
lduw(s1, simm13a, d);
decode_heap_oop(d, d);
} else {
ld_ptr(s1, simm13a, d);
}
}
void MacroAssembler::store_heap_oop(Register d, Register s1, Register s2) {
if (UseCompressedOops) {
assert(s1 != d && s2 != d, "not enough registers");
encode_heap_oop(d);
st(d, s1, s2);
} else {
st_ptr(d, s1, s2);
}
}
void MacroAssembler::store_heap_oop(Register d, Register s1, int simm13a) {
if (UseCompressedOops) {
assert(s1 != d, "not enough registers");
encode_heap_oop(d);
st(d, s1, simm13a);
} else {
st_ptr(d, s1, simm13a);
}
}
void MacroAssembler::store_heap_oop(Register d, const Address& a, int offset) {
if (UseCompressedOops) {
assert(a.base() != d, "not enough registers");
encode_heap_oop(d);
st(d, a, offset);
} else {
st_ptr(d, a, offset);
}
}
void MacroAssembler::encode_heap_oop(Register src, Register dst) {
assert (UseCompressedOops, "must be compressed");
Label done;
if (src == dst) {
// optimize for frequent case src == dst
bpr(rc_nz, true, Assembler::pt, src, done);
delayed() -> sub(src, G6_heapbase, dst); // annuled if not taken
bind(done);
srlx(src, LogMinObjAlignmentInBytes, dst);
} else {
bpr(rc_z, false, Assembler::pn, src, done);
delayed() -> mov(G0, dst);
// could be moved before branch, and annulate delay,
// but may add some unneeded work decoding null
sub(src, G6_heapbase, dst);
srlx(dst, LogMinObjAlignmentInBytes, dst);
bind(done);
}
}
void MacroAssembler::encode_heap_oop_not_null(Register r) {
assert (UseCompressedOops, "must be compressed");
sub(r, G6_heapbase, r);
srlx(r, LogMinObjAlignmentInBytes, r);
}
// Same algorithm as oops.inline.hpp decode_heap_oop.
void MacroAssembler::decode_heap_oop(Register src, Register dst) {
assert (UseCompressedOops, "must be compressed");
Label done;
sllx(src, LogMinObjAlignmentInBytes, dst);
bpr(rc_nz, true, Assembler::pt, dst, done);
delayed() -> add(dst, G6_heapbase, dst); // annuled if not taken
bind(done);
}
void MacroAssembler::decode_heap_oop_not_null(Register r) {
// Do not add assert code to this unless you change vtableStubs_sparc.cpp
// pd_code_size_limit.
assert (UseCompressedOops, "must be compressed");
sllx(r, LogMinObjAlignmentInBytes, r);
add(r, G6_heapbase, r);
}
void MacroAssembler::reinit_heapbase() {
if (UseCompressedOops) {
// call indirectly to solve generation ordering problem
Address base(G6_heapbase, (address)Universe::heap_base_addr());
load_ptr_contents(base, G6_heapbase);
}
}

@ -59,6 +59,7 @@ class BiasedLockingCounters;
// This global always holds the current JavaThread pointer:
REGISTER_DECLARATION(Register, G2_thread , G2);
REGISTER_DECLARATION(Register, G6_heapbase , G6);
// The following globals are part of the Java calling convention:
@ -1975,6 +1976,29 @@ class MacroAssembler: public Assembler {
inline void tstbool( Register s ) { tst(s); }
inline void movbool( bool boolconst, Register d) { mov( (int) boolconst, d); }
// klass oop manipulations if compressed
void load_klass(Register src_oop, Register dst);
void store_klass(Register dst_oop, Register s1);
// oop manipulations
void load_heap_oop(const Address& s, Register d, int offset = 0);
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);
void store_heap_oop(Register d, Register s1, int simm13a);
void store_heap_oop(Register d, const Address& a, int offset = 0);
void encode_heap_oop(Register src, Register dst);
void encode_heap_oop(Register r) {
encode_heap_oop(r, r);
}
void decode_heap_oop(Register src, Register dst);
void decode_heap_oop(Register r) {
decode_heap_oop(r, r);
}
void encode_heap_oop_not_null(Register r);
void decode_heap_oop_not_null(Register r);
// Support for managing the JavaThread pointer (i.e.; the reference to
// thread-local information).
void get_thread(); // load G2_thread
@ -2050,6 +2074,9 @@ class MacroAssembler: public Assembler {
void push_CPU_state();
void pop_CPU_state();
// if heap base register is used - reinit it with the correct value
void reinit_heapbase();
// Debugging
void _verify_oop(Register reg, const char * msg, const char * file, int line);
void _verify_oop_addr(Address addr, const char * msg, const char * file, int line);

@ -236,7 +236,7 @@ void C1_MacroAssembler::initialize_object(
Register t1, // temp register
Register t2 // temp register
) {
const int hdr_size_in_bytes = oopDesc::header_size_in_bytes();
const int hdr_size_in_bytes = instanceOopDesc::base_offset_in_bytes();
initialize_header(obj, klass, noreg, t1, t2);

@ -137,24 +137,20 @@ static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count)
}
static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) {
#if 0
if (HeapWordsPerLong == 1 ||
(HeapWordsPerLong == 2 &&
mask_bits((uintptr_t)tohw, right_n_bits(LogBytesPerLong)) == 0 &&
((count & 1) ? false : count >>= 1))) {
julong* to = (julong*)tohw;
julong v = ((julong)value << 32) | value;
while (count-- > 0) {
*to++ = v;
}
} else {
#endif
juint* to = (juint*)tohw;
count *= HeapWordSize / BytesPerInt;
while (count-- > 0) {
*to++ = value;
}
// }
#ifdef _LP64
guarantee(mask_bits((uintptr_t)tohw, right_n_bits(LogBytesPerLong)) == 0,
"unaligned fill words");
julong* to = (julong*)tohw;
julong v = ((julong)value << 32) | value;
while (count-- > 0) {
*to++ = v;
}
#else // _LP64
juint* to = (juint*)tohw;
while (count-- > 0) {
*to++ = value;
}
#endif // _LP64
}
static void pd_fill_to_aligned_words(HeapWord* tohw, size_t count, juint value) {

@ -859,7 +859,7 @@ void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, R
// Generate a subtype check: branch to ok_is_subtype if sub_klass is
// a subtype of super_klass. Blows registers Rsub_klass, tmp1, tmp2.
// a subtype of super_klass. Blows registers Rsuper_klass, Rsub_klass, tmp1, tmp2.
void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
Register Rsuper_klass,
Register Rtmp1,
@ -891,6 +891,9 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
// Now do a linear scan of the secondary super-klass chain.
delayed()->ld_ptr( Rsub_klass, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes(), Rtmp2 );
// compress superclass
if (UseCompressedOops) encode_heap_oop(Rsuper_klass);
// Rtmp2 holds the objArrayOop of secondary supers.
ld( Rtmp2, arrayOopDesc::length_offset_in_bytes(), Rtmp1 );// Load the array length
// Check for empty secondary super list
@ -900,20 +903,28 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
bind( loop );
br( Assembler::equal, false, Assembler::pn, not_subtype );
delayed()->nop();
// load next super to check
ld_ptr( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3 );
// Bump array pointer forward one oop
add( Rtmp2, wordSize, Rtmp2 );
// load next super to check
if (UseCompressedOops) {
ld( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3);
// Bump array pointer forward one oop
add( Rtmp2, 4, Rtmp2 );
} else {
ld_ptr( Rtmp2, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rtmp3);
// Bump array pointer forward one oop
add( Rtmp2, wordSize, Rtmp2);
}
// Look for Rsuper_klass on Rsub_klass's secondary super-class-overflow list
cmp( Rtmp3, Rsuper_klass );
// A miss means we are NOT a subtype and need to keep looping
brx( Assembler::notEqual, false, Assembler::pt, loop );
delayed()->deccc( Rtmp1 ); // dec trip counter in delay slot
// Falling out the bottom means we found a hit; we ARE a subtype
if (UseCompressedOops) decode_heap_oop(Rsuper_klass);
br( Assembler::always, false, Assembler::pt, ok_is_subtype );
// Update the cache
delayed()->st_ptr( Rsuper_klass, Rsub_klass, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() );
delayed()->st_ptr( Rsuper_klass, Rsub_klass,
sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() );
bind(not_subtype);
profile_typecheck_failed(Rtmp1);

@ -131,6 +131,7 @@ REGISTER_DEFINITION(FloatRegister, Ftos_d2);
REGISTER_DEFINITION(Register, G2_thread);
REGISTER_DEFINITION(Register, G6_heapbase);
REGISTER_DEFINITION(Register, G5_method);
REGISTER_DEFINITION(Register, G5_megamorphic_method);
REGISTER_DEFINITION(Register, G5_inline_cache_reg);

@ -160,18 +160,24 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
map->set_callee_saved(VMRegImpl::stack2reg((o5_offset + 4)>>2), O5->as_VMReg());
#endif /* _LP64 */
#ifdef _LP64
int debug_offset = 0;
#else
int debug_offset = 4;
#endif
// Save the G's
__ stx(G1, SP, g1_offset+STACK_BIAS);
map->set_callee_saved(VMRegImpl::stack2reg((g1_offset + 4)>>2), G1->as_VMReg());
map->set_callee_saved(VMRegImpl::stack2reg((g1_offset + debug_offset)>>2), G1->as_VMReg());
__ stx(G3, SP, g3_offset+STACK_BIAS);
map->set_callee_saved(VMRegImpl::stack2reg((g3_offset + 4)>>2), G3->as_VMReg());
map->set_callee_saved(VMRegImpl::stack2reg((g3_offset + debug_offset)>>2), G3->as_VMReg());
__ stx(G4, SP, g4_offset+STACK_BIAS);
map->set_callee_saved(VMRegImpl::stack2reg((g4_offset + 4)>>2), G4->as_VMReg());
map->set_callee_saved(VMRegImpl::stack2reg((g4_offset + debug_offset)>>2), G4->as_VMReg());
__ stx(G5, SP, g5_offset+STACK_BIAS);
map->set_callee_saved(VMRegImpl::stack2reg((g5_offset + 4)>>2), G5->as_VMReg());
map->set_callee_saved(VMRegImpl::stack2reg((g5_offset + debug_offset)>>2), G5->as_VMReg());
// This is really a waste but we'll keep things as they were for now
if (true) {
@ -182,11 +188,11 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
map->set_callee_saved(VMRegImpl::stack2reg((o3_offset)>>2), O3->as_VMReg()->next());
map->set_callee_saved(VMRegImpl::stack2reg((o4_offset)>>2), O4->as_VMReg()->next());
map->set_callee_saved(VMRegImpl::stack2reg((o5_offset)>>2), O5->as_VMReg()->next());
#endif /* _LP64 */
map->set_callee_saved(VMRegImpl::stack2reg((g1_offset)>>2), G1->as_VMReg()->next());
map->set_callee_saved(VMRegImpl::stack2reg((g3_offset)>>2), G3->as_VMReg()->next());
map->set_callee_saved(VMRegImpl::stack2reg((g4_offset)>>2), G4->as_VMReg()->next());
map->set_callee_saved(VMRegImpl::stack2reg((g5_offset)>>2), G5->as_VMReg()->next());
#endif /* _LP64 */
}
@ -1217,7 +1223,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
__ verify_oop(O0);
__ verify_oop(G5_method);
__ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch);
__ load_klass(O0, G3_scratch);
__ verify_oop(G3_scratch);
#if !defined(_LP64) && defined(COMPILER2)
@ -1820,7 +1826,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
const Register temp_reg = G3_scratch;
Address ic_miss(temp_reg, SharedRuntime::get_ic_miss_stub());
__ verify_oop(O0);
__ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), temp_reg);
__ load_klass(O0, temp_reg);
__ cmp(temp_reg, G5_inline_cache_reg);
__ brx(Assembler::equal, true, Assembler::pt, L);
__ delayed()->nop();

@ -544,11 +544,19 @@ int MachCallDynamicJavaNode::ret_addr_offset() {
assert(!UseInlineCaches, "expect vtable calls only if not using ICs");
int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
int klass_load_size;
if (UseCompressedOops) {
klass_load_size = 3*BytesPerInstWord; // see MacroAssembler::load_klass()
} else {
klass_load_size = 1*BytesPerInstWord;
}
if( Assembler::is_simm13(v_off) ) {
return (3*BytesPerInstWord + // ld_ptr, ld_ptr, ld_ptr
return klass_load_size +
(2*BytesPerInstWord + // ld_ptr, ld_ptr
NativeCall::instruction_size); // call; delay slot
} else {
return (5*BytesPerInstWord + // ld_ptr, set_hi, set, ld_ptr, ld_ptr
return klass_load_size +
(4*BytesPerInstWord + // set_hi, set, ld_ptr, ld_ptr
NativeCall::instruction_size); // call; delay slot
}
}
@ -1591,7 +1599,13 @@ uint reloc_java_to_interp() {
void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
st->print_cr("\nUEP:");
#ifdef _LP64
st->print_cr("\tLDX [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check");
if (UseCompressedOops) {
st->print_cr("\tLDUW [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check - compressed klass");
st->print_cr("\tSLL R_G5,3,R_G5");
st->print_cr("\tADD R_G5,R_G6_heap_base,R_G5");
} else {
st->print_cr("\tLDX [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check");
}
st->print_cr("\tCMP R_G5,R_G3" );
st->print ("\tTne xcc,R_G0+ST_RESERVED_FOR_USER_0+2");
#else // _LP64
@ -1610,7 +1624,7 @@ void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
assert( G5_ic_reg != temp_reg, "conflicting registers" );
// Load klass from reciever
__ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), temp_reg);
__ load_klass(O0, temp_reg);
// Compare against expected klass
__ cmp(temp_reg, G5_ic_reg);
// Branch to miss code, checks xcc or icc depending
@ -1811,6 +1825,11 @@ bool Matcher::can_be_java_arg( int reg ) {
reg == R_I3H_num ||
reg == R_I4H_num ||
reg == R_I5H_num ) return true;
if ((UseCompressedOops) && (reg == R_G6_num || reg == R_G6H_num)) {
return true;
}
#else
// 32-bit builds with longs-in-one-entry pass longs in G1 & G4.
// Longs cannot be passed in O regs, because O regs become I regs
@ -2474,7 +2493,13 @@ encode %{
// get receiver klass (receiver already checked for non-null)
// If we end up going thru a c2i adapter interpreter expects method in G5
int off = __ offset();
__ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch);
__ load_klass(O0, G3_scratch);
int klass_load_size;
if (UseCompressedOops) {
klass_load_size = 3*BytesPerInstWord;
} else {
klass_load_size = 1*BytesPerInstWord;
}
int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
if( __ is_simm13(v_off) ) {
@ -2484,7 +2509,8 @@ encode %{
__ Assembler::sethi(v_off & ~0x3ff, G5_method);
__ or3(G5_method, v_off & 0x3ff, G5_method);
// ld_ptr, set_hi, set
assert(__ offset() - off == 3*BytesPerInstWord, "Unexpected instruction size(s)");
assert(__ offset() - off == klass_load_size + 2*BytesPerInstWord,
"Unexpected instruction size(s)");
__ ld_ptr(G3, G5_method, G5_method);
}
// NOTE: for vtable dispatches, the vtable entry will never be null.
@ -2860,12 +2886,12 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
int count_offset = java_lang_String:: count_offset_in_bytes();
// load str1 (jchar*) base address into tmp1_reg
__ ld_ptr(Address(str1_reg, 0, value_offset), tmp1_reg);
__ load_heap_oop(Address(str1_reg, 0, value_offset), tmp1_reg);
__ ld(Address(str1_reg, 0, 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
__ sll(result_reg, exact_log2(sizeof(jchar)), result_reg);
__ ld_ptr(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted
__ load_heap_oop(Address(str2_reg, 0, value_offset), tmp2_reg); // hoisted
__ add(result_reg, tmp1_reg, tmp1_reg);
// load str2 (jchar*) base address into tmp2_reg
@ -3016,6 +3042,7 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
MacroAssembler _masm(&cbuf);
__ membar( Assembler::Membar_mask_bits(Assembler::StoreLoad) );
%}
enc_class enc_repl8b( iRegI src, iRegL dst ) %{
MacroAssembler _masm(&cbuf);
Register src_reg = reg_to_register_object($src$$reg);
@ -3189,15 +3216,15 @@ frame %{
c_return_value %{
assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" );
#ifdef _LP64
static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num };
static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num};
static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num };
static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num};
static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num };
static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num};
static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num };
static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num};
#else // !_LP64
static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num };
static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num };
static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num };
static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num };
static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num };
static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num };
static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num };
static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num };
#endif
return OptoRegPair( (is_outgoing?hi_out:hi_in)[ideal_reg],
(is_outgoing?lo_out:lo_in)[ideal_reg] );
@ -3207,15 +3234,15 @@ frame %{
return_value %{
assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" );
#ifdef _LP64
static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num };
static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num};
static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num };
static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num};
static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num };
static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num};
static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num };
static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num};
#else // !_LP64
static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num };
static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num};
static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num };
static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num};
static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num };
static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num};
static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num };
static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num};
#endif
return OptoRegPair( (is_outgoing?hi_out:hi_in)[ideal_reg],
(is_outgoing?lo_out:lo_in)[ideal_reg] );
@ -3408,6 +3435,27 @@ operand immP_poll() %{
interface(CONST_INTER);
%}
// Pointer Immediate
operand immN()
%{
match(ConN);
op_cost(10);
format %{ %}
interface(CONST_INTER);
%}
// NULL Pointer Immediate
operand immN0()
%{
predicate(n->get_narrowcon() == 0);
match(ConN);
op_cost(0);
format %{ %}
interface(CONST_INTER);
%}
operand immL() %{
match(ConL);
op_cost(40);
@ -3672,6 +3720,14 @@ operand o7RegI() %{
interface(REG_INTER);
%}
operand iRegN() %{
constraint(ALLOC_IN_RC(int_reg));
match(RegN);
format %{ %}
interface(REG_INTER);
%}
// Long Register
operand iRegL() %{
constraint(ALLOC_IN_RC(long_reg));
@ -5392,9 +5448,30 @@ instruct loadP(iRegP dst, memory mem) %{
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 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);
}
%}
ins_pipe(iload_mem);
%}
// Load Klass Pointer
instruct loadKlass(iRegP dst, memory mem) %{
match(Set dst (LoadKlass mem));
predicate(!n->in(MemNode::Address)->bottom_type()->is_narrow());
ins_cost(MEMORY_REF_COST);
size(4);
@ -5409,6 +5486,30 @@ instruct loadKlass(iRegP dst, memory mem) %{
ins_pipe(iload_mem);
%}
// Load Klass Pointer
instruct loadKlassComp(iRegP dst, memory mem) %{
match(Set dst (LoadKlass mem));
predicate(n->in(MemNode::Address)->bottom_type()->is_narrow());
ins_cost(MEMORY_REF_COST);
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);
}
// klass oop never null but this is generated for nonheader klass loads
// too which can be null.
__ decode_heap_oop(dst);
%}
ins_pipe(iload_mem);
%}
// Load Short (16bit signed)
instruct loadS(iRegI dst, memory mem) %{
match(Set dst (LoadS mem));
@ -5508,6 +5609,24 @@ instruct loadConP_poll(iRegP dst, immP_poll src) %{
ins_pipe(loadConP_poll);
%}
instruct loadConN(iRegN dst, immN src) %{
match(Set dst src);
ins_cost(DEFAULT_COST * 2);
format %{ "SET $src,$dst\t!ptr" %}
ins_encode %{
address con = (address)$src$$constant;
Register dst = $dst$$Register;
if (con == NULL) {
__ mov(G0, dst);
} else {
__ set_oop((jobject)$src$$constant, dst);
__ encode_heap_oop(dst);
}
%}
ins_pipe(loadConP);
%}
instruct loadConL(iRegL dst, immL src, o7RegL tmp) %{
// %%% maybe this should work like loadConD
match(Set dst src);
@ -5741,6 +5860,44 @@ instruct storeP0(memory dst, immP0 src) %{
ins_pipe(istore_mem_zero);
%}
// Store Compressed Pointer
instruct storeN(memory dst, iRegN src) %{
match(Set dst (StoreN dst src));
ins_cost(MEMORY_REF_COST);
size(4);
format %{ "STW $src,$dst\t! compressed ptr" %}
ins_encode %{
Register base = as_Register($dst$$base);
Register index = as_Register($dst$$index);
Register src = $src$$Register;
if (index != G0) {
__ stw(src, base, index);
} else {
__ stw(src, base, $dst$$disp);
}
%}
ins_pipe(istore_mem_spORreg);
%}
instruct storeN0(memory dst, immN0 src) %{
match(Set dst (StoreN dst src));
ins_cost(MEMORY_REF_COST);
size(4);
format %{ "STW $src,$dst\t! compressed ptr" %}
ins_encode %{
Register base = as_Register($dst$$base);
Register index = as_Register($dst$$index);
if (index != G0) {
__ stw(0, base, index);
} else {
__ stw(0, base, $dst$$disp);
}
%}
ins_pipe(istore_mem_zero);
%}
// Store Double
instruct storeD( memory mem, regD src) %{
match(Set mem (StoreD mem src));
@ -5798,6 +5955,26 @@ instruct storeA8B(memory mem, regD src) %{
ins_pipe(fstoreD_mem_reg);
%}
// Convert oop pointer into compressed form
instruct encodeHeapOop(iRegN dst, iRegP src) %{
match(Set dst (EncodeP src));
format %{ "SRL $src,3,$dst\t encodeHeapOop" %}
ins_encode %{
__ encode_heap_oop($src$$Register, $dst$$Register);
%}
ins_pipe(ialu_reg);
%}
instruct decodeHeapOop(iRegP dst, iRegN src) %{
match(Set dst (DecodeN src));
format %{ "decode_heap_oop $src, $dst" %}
ins_encode %{
__ decode_heap_oop($src$$Register, $dst$$Register);
%}
ins_pipe(ialu_reg);
%}
// Store Zero into Aligned Packed Bytes
instruct storeA8B0(memory mem, immI0 zero) %{
match(Set mem (Store8B mem zero));
@ -6434,17 +6611,27 @@ instruct compareAndSwapI_bool(iRegP mem_ptr, iRegI oldval, iRegI newval, iRegI r
instruct compareAndSwapP_bool(iRegP mem_ptr, iRegP oldval, iRegP newval, iRegI res, o7RegI tmp1, flagsReg ccr ) %{
match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval)));
effect( USE mem_ptr, KILL ccr, KILL tmp1);
#ifdef _LP64
format %{
"MOV $newval,O7\n\t"
"CASXA [$mem_ptr],$oldval,O7\t! If $oldval==[$mem_ptr] Then store O7 into [$mem_ptr], set O7=[$mem_ptr] in any case\n\t"
"CASA_PTR [$mem_ptr],$oldval,O7\t! If $oldval==[$mem_ptr] Then store O7 into [$mem_ptr], set O7=[$mem_ptr] in any case\n\t"
"CMP $oldval,O7\t\t! See if we made progress\n\t"
"MOV 1,$res\n\t"
"MOVne xcc,R_G0,$res"
%}
#ifdef _LP64
ins_encode( enc_casx(mem_ptr, oldval, newval),
enc_lflags_ne_to_boolean(res) );
#else
ins_encode( enc_casi(mem_ptr, oldval, newval),
enc_iflags_ne_to_boolean(res) );
#endif
ins_pipe( long_memory_op );
%}
instruct compareAndSwapN_bool_comp(iRegP mem_ptr, iRegN oldval, iRegN newval, iRegI res, o7RegI tmp, flagsReg ccr ) %{
match(Set res (CompareAndSwapN mem_ptr (Binary oldval newval)));
effect( USE mem_ptr, KILL ccr, KILL tmp);
format %{
"MOV $newval,O7\n\t"
"CASA [$mem_ptr],$oldval,O7\t! If $oldval==[$mem_ptr] Then store O7 into [$mem_ptr], set O7=[$mem_ptr] in any case\n\t"
@ -6452,9 +6639,18 @@ instruct compareAndSwapP_bool(iRegP mem_ptr, iRegP oldval, iRegP newval, iRegI r
"MOV 1,$res\n\t"
"MOVne icc,R_G0,$res"
%}
ins_encode( enc_casi(mem_ptr, oldval, newval),
enc_iflags_ne_to_boolean(res) );
#endif
ins_encode %{
Register Rmem = reg_to_register_object($mem_ptr$$reg);
Register Rold = reg_to_register_object($oldval$$reg);
Register Rnew = reg_to_register_object($newval$$reg);
Register Rres = reg_to_register_object($res$$reg);
__ cas(Rmem, Rold, Rnew);
__ cmp( Rold, Rnew );
__ mov(1, Rres);
__ movcc( Assembler::notEqual, false, Assembler::icc, G0, Rres );
%}
ins_pipe( long_memory_op );
%}
@ -8607,6 +8803,17 @@ instruct partialSubtypeCheck_vs_zero( flagsRegP pcc, o1RegP sub, o2RegP super, i
ins_pipe(partial_subtype_check_pipe);
%}
instruct compP_iRegN_immN0(flagsRegP pcc, iRegN op1, immN0 op2 ) %{
match(Set pcc (CmpN op1 op2));
size(4);
format %{ "CMP $op1,$op2\t! ptr" %}
opcode(Assembler::subcc_op3, Assembler::arith_op);
ins_encode( form3_rs1_simm13_rd( op1, op2, R_G0 ) );
ins_pipe(ialu_cconly_reg_imm);
%}
// ============================================================================
// inlined locking and unlocking
@ -8648,9 +8855,10 @@ instruct clear_array(iRegX cnt, iRegP base, iRegX temp, Universe dummy, flagsReg
ins_pipe(long_memory_op);
%}
instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, flagsReg ccr) %{
instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result,
o7RegI tmp3, flagsReg ccr) %{
match(Set result (StrComp str1 str2));
effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr);
effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3);
ins_cost(300);
format %{ "String Compare $str1,$str2 -> $result" %}
ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, result) );

@ -127,6 +127,7 @@ class StubGenerator: public StubCodeGenerator {
// setup thread register
__ ld_ptr(thread.as_address(), G2_thread);
__ reinit_heapbase();
#ifdef ASSERT
// make sure we have no pending exceptions
@ -896,6 +897,7 @@ class StubGenerator: public StubCodeGenerator {
// super: O2, argument, not changed
// raddr: O7, blown by call
address generate_partial_subtype_check() {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "partial_subtype_check");
address start = __ pc();
Label loop, miss;
@ -914,7 +916,7 @@ class StubGenerator: public StubCodeGenerator {
#if defined(COMPILER2) && !defined(_LP64)
// Do not use a 'save' because it blows the 64-bit O registers.
__ add(SP,-4*wordSize,SP); // Make space for 4 temps
__ add(SP,-4*wordSize,SP); // Make space for 4 temps (stack must be 2 words aligned)
__ st_ptr(L0,SP,(frame::register_save_words+0)*wordSize);
__ st_ptr(L1,SP,(frame::register_save_words+1)*wordSize);
__ st_ptr(L2,SP,(frame::register_save_words+2)*wordSize);
@ -934,6 +936,17 @@ class StubGenerator: public StubCodeGenerator {
Register L2_super = L2;
Register L3_index = L3;
#ifdef _LP64
Register L4_ooptmp = L4;
if (UseCompressedOops) {
// this must be under UseCompressedOops check, as we rely upon fact
// that L4 not clobbered in C2 on 32-bit platforms, where we do explicit save
// on stack, see several lines above
__ encode_heap_oop(Rsuper, L4_ooptmp);
}
#endif
inc_counter_np(SharedRuntime::_partial_subtype_ctr, L0, L1);
__ ld_ptr( Rsub, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes(), L3 );
@ -942,18 +955,33 @@ class StubGenerator: public StubCodeGenerator {
__ clr(L3_index); // zero index
// Load a little early; will load 1 off the end of the array.
// Ok for now; revisit if we have other uses of this routine.
__ ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early
__ align(CodeEntryAlignment);
if (UseCompressedOops) {
__ ld(L1_ary_ptr,0,L2_super);// Will load a little early
} else {
__ ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early
}
assert(heapOopSize != 0, "heapOopSize should be initialized");
// The scan loop
__ BIND(loop);
__ add(L1_ary_ptr,wordSize,L1_ary_ptr); // Bump by OOP size
__ add(L1_ary_ptr, heapOopSize, L1_ary_ptr); // Bump by OOP size
__ cmp(L3_index,L0_ary_len);
__ br(Assembler::equal,false,Assembler::pn,miss);
__ delayed()->inc(L3_index); // Bump index
__ subcc(L2_super,Rsuper,Rret); // Check for match; zero in Rret for a hit
__ brx( Assembler::notEqual, false, Assembler::pt, loop );
__ delayed()->ld_ptr(L1_ary_ptr,0,L2_super); // Will load a little early
if (UseCompressedOops) {
#ifdef _LP64
__ subcc(L2_super,L4_ooptmp,Rret); // Check for match; zero in Rret for a hit
__ br( Assembler::notEqual, false, Assembler::pt, loop );
__ delayed()->ld(L1_ary_ptr,0,L2_super);// Will load a little early
#else
ShouldNotReachHere();
#endif
} else {
__ subcc(L2_super,Rsuper,Rret); // Check for match; zero in Rret for a hit
__ brx( Assembler::notEqual, false, Assembler::pt, loop );
__ delayed()->ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early
}
// Got a hit; report success; set cache. Cache load doesn't
// happen here; for speed it is directly emitted by the compiler.
@ -1107,7 +1135,6 @@ class StubGenerator: public StubCodeGenerator {
}
#endif // 0
}
//
// Generate post-write barrier for array.
//
@ -1148,8 +1175,8 @@ class StubGenerator: public StubCodeGenerator {
Label L_loop;
__ sll_ptr(count, LogBytesPerOop, count);
__ sub(count, BytesPerOop, count);
__ sll_ptr(count, LogBytesPerHeapOop, count);
__ sub(count, BytesPerHeapOop, count);
__ add(count, addr, count);
// Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
__ srl_ptr(addr, CardTableModRefBS::card_shift, addr);
@ -1171,7 +1198,6 @@ class StubGenerator: public StubCodeGenerator {
ShouldNotReachHere();
}
}
@ -2226,7 +2252,12 @@ class StubGenerator: public StubCodeGenerator {
__ mov(count, G5);
gen_write_ref_array_pre_barrier(G1, G5);
#ifdef _LP64
generate_disjoint_long_copy_core(aligned);
assert_clean_int(count, O3); // Make sure 'count' is clean int.
if (UseCompressedOops) {
generate_disjoint_int_copy_core(aligned);
} else {
generate_disjoint_long_copy_core(aligned);
}
#else
generate_disjoint_int_copy_core(aligned);
#endif
@ -2274,10 +2305,14 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::arrayof_oop_disjoint_arraycopy() :
disjoint_oop_copy_entry;
array_overlap_test(nooverlap_target, LogBytesPerWord);
array_overlap_test(nooverlap_target, LogBytesPerHeapOop);
#ifdef _LP64
generate_conjoint_long_copy_core(aligned);
if (UseCompressedOops) {
generate_conjoint_int_copy_core(aligned);
} else {
generate_conjoint_long_copy_core(aligned);
}
#else
generate_conjoint_int_copy_core(aligned);
#endif
@ -2377,8 +2412,6 @@ class StubGenerator: public StubCodeGenerator {
StubCodeMark mark(this, "StubRoutines", name);
address start = __ pc();
int klass_off = oopDesc::klass_offset_in_bytes();
gen_write_ref_array_pre_barrier(G1, G5);
@ -2395,7 +2428,7 @@ class StubGenerator: public StubCodeGenerator {
{ Label L;
__ mov(O3, G1); // spill: overlap test smashes O3
__ mov(O4, G4); // spill: overlap test smashes O4
array_overlap_test(L, LogBytesPerWord);
array_overlap_test(L, LogBytesPerHeapOop);
__ stop("checkcast_copy within a single array");
__ bind(L);
__ mov(G1, O3);
@ -2429,18 +2462,18 @@ class StubGenerator: public StubCodeGenerator {
__ bind(store_element);
// deccc(G1_remain); // decrement the count (hoisted)
__ st_ptr(G3_oop, O1_to, O5_offset); // store the oop
__ inc(O5_offset, wordSize); // step to next offset
__ store_heap_oop(G3_oop, O1_to, O5_offset); // store the oop
__ inc(O5_offset, heapOopSize); // step to next offset
__ brx(Assembler::zero, true, Assembler::pt, do_card_marks);
__ delayed()->set(0, O0); // return -1 on success
// ======== loop entry is here ========
__ bind(load_element);
__ ld_ptr(O0_from, O5_offset, G3_oop); // load the oop
__ load_heap_oop(O0_from, O5_offset, G3_oop); // load the oop
__ br_null(G3_oop, true, Assembler::pt, store_element);
__ delayed()->deccc(G1_remain); // decrement the count
__ ld_ptr(G3_oop, klass_off, G4_klass); // query the object klass
__ load_klass(G3_oop, G4_klass); // query the object klass
generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super,
// branch to this on success:
@ -2642,17 +2675,23 @@ class StubGenerator: public StubCodeGenerator {
BLOCK_COMMENT("arraycopy argument klass checks");
// get src->klass()
__ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), G3_src_klass);
if (UseCompressedOops) {
__ delayed()->nop(); // ??? not good
__ load_klass(src, G3_src_klass);
} else {
__ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), G3_src_klass);
}
#ifdef ASSERT
// assert(src->klass() != NULL);
BLOCK_COMMENT("assert klasses not null");
{ Label L_a, L_b;
__ br_notnull(G3_src_klass, false, Assembler::pt, L_b); // it is broken if klass is NULL
__ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass);
__ delayed()->nop();
__ bind(L_a);
__ stop("broken null klass");
__ bind(L_b);
__ load_klass(dst, G4_dst_klass);
__ br_null(G4_dst_klass, false, Assembler::pn, L_a); // this would be broken also
__ delayed()->mov(G0, G4_dst_klass); // scribble the temp
BLOCK_COMMENT("assert done");
@ -2673,12 +2712,19 @@ class StubGenerator: public StubCodeGenerator {
// Load 32-bits signed value. Use br() instruction with it to check icc.
__ lduw(G3_src_klass, lh_offset, G5_lh);
if (UseCompressedOops) {
__ load_klass(dst, G4_dst_klass);
}
// Handle objArrays completely differently...
juint objArray_lh = Klass::array_layout_helper(T_OBJECT);
__ set(objArray_lh, O5_temp);
__ cmp(G5_lh, O5_temp);
__ br(Assembler::equal, false, Assembler::pt, L_objArray);
__ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass);
if (UseCompressedOops) {
__ delayed()->nop();
} else {
__ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass);
}
// if (src->klass() != dst->klass()) return -1;
__ cmp(G3_src_klass, G4_dst_klass);
@ -2777,8 +2823,8 @@ class StubGenerator: public StubCodeGenerator {
__ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset
__ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset
__ sll_ptr(src_pos, LogBytesPerOop, src_pos);
__ sll_ptr(dst_pos, LogBytesPerOop, dst_pos);
__ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos);
__ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos);
__ add(src, src_pos, from); // src_addr
__ add(dst, dst_pos, to); // dst_addr
__ BIND(L_plain_copy);
@ -2801,8 +2847,8 @@ class StubGenerator: public StubCodeGenerator {
// Marshal the base address arguments now, freeing registers.
__ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset
__ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset
__ sll_ptr(src_pos, LogBytesPerOop, src_pos);
__ sll_ptr(dst_pos, LogBytesPerOop, dst_pos);
__ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos);
__ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos);
__ add(src, src_pos, from); // src_addr
__ add(dst, dst_pos, to); // dst_addr
__ signx(length, count); // length (reloaded)

@ -591,7 +591,10 @@ address InterpreterGenerator::generate_accessor_entry(void) {
address entry = __ pc();
Label slow_path;
if ( UseFastAccessorMethods) {
// XXX: for compressed oops pointer loading and decoding doesn't fit in
// delay slot and damages G1
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());
@ -953,6 +956,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
// Back from jni method Lmethod in this frame is DEAD, DEAD, DEAD
__ restore_thread(L7_thread_cache); // restore G2_thread
__ reinit_heapbase();
// must we block?

@ -462,8 +462,8 @@ void TemplateTable::aaload() {
transition(itos, atos);
// Otos_i: index
// tos: array
__ index_check(O2, Otos_i, LogBytesPerWord, G3_scratch, O3);
__ ld_ptr(O3, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i);
__ index_check(O2, Otos_i, UseCompressedOops ? 2 : LogBytesPerWord, G3_scratch, O3);
__ load_heap_oop(O3, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i);
__ verify_oop(Otos_i);
}
@ -736,15 +736,16 @@ void TemplateTable::aastore() {
// O2: index
// O3: array
__ verify_oop(Otos_i);
__ index_check_without_pop(O3, O2, LogBytesPerWord, G3_scratch, O1);
__ index_check_without_pop(O3, O2, UseCompressedOops ? 2 : LogBytesPerWord, G3_scratch, O1);
// do array store check - check for NULL value first
__ br_null( Otos_i, false, Assembler::pn, is_null );
__ delayed()->
ld_ptr(O3, oopDesc::klass_offset_in_bytes(), O4); // get array klass
__ delayed()->nop();
__ load_klass(O3, O4); // get array klass
__ load_klass(Otos_i, O5); // get value klass
// do fast instanceof cache test
__ ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), O5); // get value klass
__ ld_ptr(O4, sizeof(oopDesc) + objArrayKlass::element_klass_offset_in_bytes(), O4);
@ -766,7 +767,7 @@ void TemplateTable::aastore() {
// Store is OK.
__ bind(store_ok);
__ st_ptr(Otos_i, O1, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
__ store_heap_oop(Otos_i, O1, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
// Quote from rememberedSet.hpp: For objArrays, the precise card
// corresponding to the pointer store is dirtied so we don't need to
// scavenge the entire array.
@ -777,7 +778,7 @@ void TemplateTable::aastore() {
__ delayed()->inc(Lesp, 3* Interpreter::stackElementSize()); // adj sp (pops array, index and value)
__ bind(is_null);
__ st_ptr(Otos_i, element);
__ store_heap_oop(Otos_i, element);
__ profile_null_seen(G3_scratch);
__ inc(Lesp, 3* Interpreter::stackElementSize()); // adj sp (pops array, index and value)
__ bind(done);
@ -1833,7 +1834,7 @@ void TemplateTable::_return(TosState state) {
assert(state == vtos, "only valid state");
__ mov(G0, G3_scratch);
__ access_local_ptr(G3_scratch, Otos_i);
__ ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), O2);
__ load_klass(Otos_i, O2);
__ set(JVM_ACC_HAS_FINALIZER, G3);
__ ld(O2, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc), O2);
__ andcc(G3, O2, G0);
@ -2078,7 +2079,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
__ delayed() ->cmp(Rflags, itos);
// atos
__ ld_ptr(Rclass, Roffset, Otos_i);
__ load_heap_oop(Rclass, Roffset, Otos_i);
__ verify_oop(Otos_i);
__ push(atos);
if (!is_static) {
@ -2259,7 +2260,7 @@ void TemplateTable::fast_accessfield(TosState state) {
__ ldf(FloatRegisterImpl::D, Otos_i, Roffset, Ftos_d);
break;
case Bytecodes::_fast_agetfield:
__ ld_ptr(Otos_i, Roffset, Otos_i);
__ load_heap_oop(Otos_i, Roffset, Otos_i);
break;
default:
ShouldNotReachHere();
@ -2448,7 +2449,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
// atos
__ pop_ptr();
__ verify_oop(Otos_i);
__ st_ptr(Otos_i, Rclass, Roffset);
__ store_heap_oop(Otos_i, Rclass, Roffset);
__ store_check(G1_scratch, Rclass, Roffset);
__ ba(false, checkVolatile);
__ delayed()->tst(Lscratch);
@ -2490,7 +2491,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
__ pop_ptr();
pop_and_check_object(Rclass);
__ verify_oop(Otos_i);
__ st_ptr(Otos_i, Rclass, Roffset);
__ store_heap_oop(Otos_i, Rclass, Roffset);
__ store_check(G1_scratch, Rclass, Roffset);
patch_bytecode(Bytecodes::_fast_aputfield, G3_scratch, G4_scratch);
__ ba(false, checkVolatile);
@ -2645,7 +2646,7 @@ void TemplateTable::fast_storefield(TosState state) {
__ stf(FloatRegisterImpl::D, Ftos_d, Rclass, Roffset);
break;
case Bytecodes::_fast_aputfield:
__ st_ptr(Otos_i, Rclass, Roffset);
__ store_heap_oop(Otos_i, Rclass, Roffset);
__ store_check(G1_scratch, Rclass, Roffset);
break;
default:
@ -2688,7 +2689,7 @@ void TemplateTable::fast_xaccess(TosState state) {
__ verify_oop(Rreceiver);
__ null_check(Rreceiver);
if (state == atos) {
__ ld_ptr(Rreceiver, Roffset, Otos_i);
__ load_heap_oop(Rreceiver, Roffset, Otos_i);
} else if (state == itos) {
__ ld (Rreceiver, Roffset, Otos_i) ;
} else if (state == ftos) {
@ -2790,7 +2791,7 @@ void TemplateTable::invokevirtual(int byte_no) {
// get receiver klass
__ null_check(O0, oopDesc::klass_offset_in_bytes());
__ ld_ptr(Address(O0, 0, oopDesc::klass_offset_in_bytes()), Rrecv);
__ load_klass(O0, Rrecv);
__ verify_oop(Rrecv);
__ profile_virtual_call(Rrecv, O4);
@ -2958,7 +2959,7 @@ void TemplateTable::invokeinterface(int byte_no) {
// get receiver klass
__ null_check(O0, oopDesc::klass_offset_in_bytes());
__ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), RklassOop);
__ load_klass(O0, RklassOop);
__ verify_oop(RklassOop);
// Special case of invokeinterface called for virtual method of
@ -3221,7 +3222,7 @@ void TemplateTable::_new() {
__ set((intptr_t)markOopDesc::prototype(), G4_scratch);
}
__ st_ptr(G4_scratch, RallocatedObject, oopDesc::mark_offset_in_bytes()); // mark
__ st_ptr(RinstanceKlass, RallocatedObject, oopDesc::klass_offset_in_bytes()); // klass
__ store_klass(RinstanceKlass, RallocatedObject); // klass
{
SkipIfEqual skip_if(
@ -3277,7 +3278,7 @@ void TemplateTable::checkcast() {
__ delayed()->nop();
// Get value klass in RobjKlass
__ ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), RobjKlass); // get value klass
__ load_klass(Otos_i, RobjKlass); // get value klass
// Get constant pool tag
__ get_2_byte_integer_at_bcp(1, Lscratch, Roffset, InterpreterMacroAssembler::Unsigned);
@ -3295,13 +3296,14 @@ void TemplateTable::checkcast() {
__ pop_ptr(Otos_i, G3_scratch); // restore receiver
__ br(Assembler::always, false, Assembler::pt, resolved);
__ delayed()->ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), RobjKlass); // get value klass
__ delayed()->nop();
// Extract target class from constant pool
__ bind(quicked);
__ add(Roffset, sizeof(constantPoolOopDesc), Roffset);
__ ld_ptr(Lscratch, Roffset, RspecifiedKlass);
__ bind(resolved);
__ load_klass(Otos_i, RobjKlass); // get value klass
// Generate a fast subtype check. Branch to cast_ok if no
// failure. Throw exception if failure.
@ -3334,7 +3336,7 @@ void TemplateTable::instanceof() {
__ delayed()->nop();
// Get value klass in RobjKlass
__ ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), RobjKlass); // get value klass
__ load_klass(Otos_i, RobjKlass); // get value klass
// Get constant pool tag
__ get_2_byte_integer_at_bcp(1, Lscratch, Roffset, InterpreterMacroAssembler::Unsigned);
@ -3352,7 +3354,7 @@ void TemplateTable::instanceof() {
__ pop_ptr(Otos_i, G3_scratch); // restore receiver
__ br(Assembler::always, false, Assembler::pt, resolved);
__ delayed()->ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), RobjKlass); // get value klass
__ delayed()->nop();
// Extract target class from constant pool
@ -3361,6 +3363,7 @@ void TemplateTable::instanceof() {
__ get_constant_pool(Lscratch);
__ ld_ptr(Lscratch, Roffset, RspecifiedKlass);
__ bind(resolved);
__ load_klass(Otos_i, RobjKlass); // get value klass
// Generate a fast subtype check. Branch to cast_ok if no
// failure. Return 0 if failure.

@ -64,6 +64,15 @@ void VM_Version::initialize() {
if (FLAG_IS_DEFAULT(UseInlineCaches)) {
UseInlineCaches = false;
}
#ifdef _LP64
// Single issue niagara1 is slower for CompressedOops
// but niagaras after that it's fine.
if (!is_niagara1_plus()) {
if (FLAG_IS_DEFAULT(UseCompressedOops)) {
FLAG_SET_ERGO(bool, UseCompressedOops, false);
}
}
#endif // _LP64
#ifdef COMPILER2
// Indirect branch is the same cost as direct
if (FLAG_IS_DEFAULT(UseJumpTables)) {

@ -60,7 +60,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
// get receiver klass
address npe_addr = __ pc();
__ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_scratch);
__ load_klass(O0, G3_scratch);
// set methodOop (in case of interpreted method), and destination address
int entry_offset = instanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
@ -131,7 +131,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
// get receiver klass (also an implicit null-check)
address npe_addr = __ pc();
__ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), G3_klassOop);
__ load_klass(O0, G3_klassOop);
__ verify_oop(G3_klassOop);
// Push a new window to get some temp registers. This chops the head of all
@ -237,11 +237,16 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
else {
const int slop = 2*BytesPerInstWord; // sethi;add (needed for long offsets)
if (is_vtable_stub) {
const int basic = 5*BytesPerInstWord; // ld;ld;ld,jmp,nop
// ld;ld;ld,jmp,nop
const int basic = 5*BytesPerInstWord +
// shift;add for load_klass
(UseCompressedOops ? 2*BytesPerInstWord : 0);
return basic + slop;
} else {
// save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore, sethi, jmpl, restore
const int basic = (20 LP64_ONLY(+ 6)) * BytesPerInstWord;
const int basic = (20 LP64_ONLY(+ 6)) * BytesPerInstWord +
// shift;add for load_klass
(UseCompressedOops ? 2*BytesPerInstWord : 0);
return (basic + slop);
}
}

@ -127,6 +127,7 @@ int AbstractAssembler::code_fill_byte() {
bool Assembler::reachable(AddressLiteral adr) {
int64_t disp;
// None will force a 64bit literal to the code stream. Likely a placeholder
// for something that will be patched later and we need to certain it will
// always be reachable.
@ -636,7 +637,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x8A: // movb r, a
case 0x8B: // movl r, a
case 0x8F: // popl a
debug_only(has_disp32 = true);
debug_only(has_disp32 = true;)
break;
case 0x68: // pushq #32
@ -2891,7 +2892,7 @@ void Assembler::rep_set() {
}
// scans rcx double words (m64) at [rdi] for occurance of rax
void Assembler::repne_scan() {
void Assembler::repne_scanq() {
// REPNE/REPNZ
emit_byte(0xF2);
// SCASQ
@ -2899,6 +2900,14 @@ void Assembler::repne_scan() {
emit_byte(0xAF);
}
void Assembler::repne_scanl() {
// REPNE/REPNZ
emit_byte(0xF2);
// SCASL
emit_byte(0xAF);
}
void Assembler::setb(Condition cc, Register dst) {
assert(0 <= cc && cc < 16, "illegal cc");
int encode = prefix_and_encode(dst->encoding(), true);
@ -4597,7 +4606,6 @@ void MacroAssembler::verify_oop(Register reg, const char* s) {
// pass args on stack, only touch rax
pushq(reg);
// avoid using pushptr, as it modifies scratch registers
// and our contract is not to modify anything
ExternalAddress buffer((address)b);
@ -4664,9 +4672,9 @@ void MacroAssembler::debug(char* msg, int64_t pc, int64_t regs[]) {
JavaThread* thread = JavaThread::current();
JavaThreadState saved_state = thread->thread_state();
thread->set_thread_state(_thread_in_vm);
ttyLocker ttyl;
#ifndef PRODUCT
if (CountBytecodes || TraceBytecodes || StopInterpreterAt) {
ttyLocker ttyl;
BytecodeCounter::print();
}
#endif
@ -4674,6 +4682,7 @@ void MacroAssembler::debug(char* msg, int64_t pc, int64_t regs[]) {
// XXX correct this offset for amd64
// This is the value of eip which points to where verify_oop will return.
if (os::message_box(msg, "Execution stopped, print registers?")) {
ttyLocker ttyl;
tty->print_cr("rip = 0x%016lx", pc);
tty->print_cr("rax = 0x%016lx", regs[15]);
tty->print_cr("rbx = 0x%016lx", regs[12]);
@ -4695,6 +4704,7 @@ void MacroAssembler::debug(char* msg, int64_t pc, int64_t regs[]) {
}
ThreadStateTransition::transition(thread, _thread_in_vm, saved_state);
} else {
ttyLocker ttyl;
::tty->print_cr("=============== DEBUG MESSAGE: %s ================\n",
msg);
}
@ -4891,7 +4901,7 @@ void MacroAssembler::tlab_refill(Label& retry,
movq(Address(top, arrayOopDesc::length_offset_in_bytes()), t1);
// set klass to intArrayKlass
movptr(t1, ExternalAddress((address) Universe::intArrayKlassObj_addr()));
movq(Address(top, oopDesc::klass_offset_in_bytes()), t1);
store_klass(top, t1);
// refill the tlab with an eden allocation
bind(do_refill);
@ -4938,7 +4948,6 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, Register obj_reg, Re
assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg);
assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout");
Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes());
Address klass_addr (obj_reg, oopDesc::klass_offset_in_bytes());
Address saved_mark_addr(lock_reg, 0);
if (PrintBiasedLockingStatistics && counters == NULL)
@ -4962,7 +4971,7 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, Register obj_reg, Re
jcc(Assembler::notEqual, cas_label);
// The bias pattern is present in the object's header. Need to check
// whether the bias owner and the epoch are both still current.
movq(tmp_reg, klass_addr);
load_klass(tmp_reg, obj_reg);
movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
orq(tmp_reg, r15_thread);
xorq(tmp_reg, swap_reg);
@ -5037,7 +5046,7 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, Register obj_reg, Re
//
// FIXME: due to a lack of registers we currently blow away the age
// bits in this situation. Should attempt to preserve them.
movq(tmp_reg, klass_addr);
load_klass(tmp_reg, obj_reg);
movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
orq(tmp_reg, r15_thread);
if (os::is_MP()) {
@ -5068,7 +5077,7 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, Register obj_reg, Re
//
// FIXME: due to a lack of registers we currently blow away the age
// bits in this situation. Should attempt to preserve them.
movq(tmp_reg, klass_addr);
load_klass(tmp_reg, obj_reg);
movq(tmp_reg, Address(tmp_reg, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
if (os::is_MP()) {
lock();
@ -5104,6 +5113,113 @@ void MacroAssembler::biased_locking_exit(Register obj_reg, Register temp_reg, La
}
void MacroAssembler::load_klass(Register dst, Register src) {
if (UseCompressedOops) {
movl(dst, Address(src, oopDesc::klass_offset_in_bytes()));
decode_heap_oop_not_null(dst);
} else {
movq(dst, Address(src, oopDesc::klass_offset_in_bytes()));
}
}
void MacroAssembler::store_klass(Register dst, Register src) {
if (UseCompressedOops) {
encode_heap_oop_not_null(src);
// zero the entire klass field first as the gap needs to be zeroed too.
movptr(Address(dst, oopDesc::klass_offset_in_bytes()), NULL_WORD);
movl(Address(dst, oopDesc::klass_offset_in_bytes()), src);
} else {
movq(Address(dst, oopDesc::klass_offset_in_bytes()), src);
}
}
void MacroAssembler::load_heap_oop(Register dst, Address src) {
if (UseCompressedOops) {
movl(dst, src);
decode_heap_oop(dst);
} else {
movq(dst, src);
}
}
void MacroAssembler::store_heap_oop(Address dst, Register src) {
if (UseCompressedOops) {
assert(!dst.uses(src), "not enough registers");
encode_heap_oop(src);
movl(dst, src);
} else {
movq(dst, src);
}
}
// Algorithm must match oop.inline.hpp encode_heap_oop.
void MacroAssembler::encode_heap_oop(Register r) {
assert (UseCompressedOops, "should be compressed");
#ifdef ASSERT
Label ok;
pushq(rscratch1); // cmpptr trashes rscratch1
cmpptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr()));
jcc(Assembler::equal, ok);
stop("MacroAssembler::encode_heap_oop: heap base corrupted?");
bind(ok);
popq(rscratch1);
#endif
verify_oop(r);
testq(r, r);
cmovq(Assembler::equal, r, r12_heapbase);
subq(r, r12_heapbase);
shrq(r, LogMinObjAlignmentInBytes);
}
void MacroAssembler::encode_heap_oop_not_null(Register r) {
assert (UseCompressedOops, "should be compressed");
#ifdef ASSERT
Label ok;
testq(r, r);
jcc(Assembler::notEqual, ok);
stop("null oop passed to encode_heap_oop_not_null");
bind(ok);
#endif
verify_oop(r);
subq(r, r12_heapbase);
shrq(r, LogMinObjAlignmentInBytes);
}
void MacroAssembler::decode_heap_oop(Register r) {
assert (UseCompressedOops, "should be compressed");
#ifdef ASSERT
Label ok;
pushq(rscratch1);
cmpptr(r12_heapbase,
ExternalAddress((address)Universe::heap_base_addr()));
jcc(Assembler::equal, ok);
stop("MacroAssembler::decode_heap_oop: heap base corrupted?");
bind(ok);
popq(rscratch1);
#endif
Label done;
shlq(r, LogMinObjAlignmentInBytes);
jccb(Assembler::equal, done);
addq(r, r12_heapbase);
#if 0
// alternate decoding probably a wash.
testq(r, r);
jccb(Assembler::equal, done);
leaq(r, Address(r12_heapbase, r, Address::times_8, 0));
#endif
bind(done);
verify_oop(r);
}
void MacroAssembler::decode_heap_oop_not_null(Register r) {
assert (UseCompressedOops, "should only be used for compressed headers");
// Cannot assert, unverified entry point counts instructions (see .ad file)
// vtableStubs also counts instructions in pd_code_size_limit.
assert(Address::times_8 == LogMinObjAlignmentInBytes, "decode alg wrong");
leaq(r, Address(r12_heapbase, r, Address::times_8, 0));
}
Assembler::Condition MacroAssembler::negate_condition(Assembler::Condition cond) {
switch (cond) {
// Note some conditions are synonyms for others
@ -5173,3 +5289,9 @@ void MacroAssembler::bang_stack_size(Register size, Register tmp) {
movq(Address(tmp, (-i*os::vm_page_size())), size );
}
}
void MacroAssembler::reinit_heapbase() {
if (UseCompressedOops) {
movptr(r12_heapbase, ExternalAddress((address)Universe::heap_base_addr()));
}
}

@ -37,7 +37,7 @@ class Argument VALUE_OBJ_CLASS_SPEC {
#else
n_int_register_parameters_c = 6, // rdi, rsi, rdx, rcx, r8, r9 (c_rarg0, c_rarg1, ...)
n_float_register_parameters_c = 8, // xmm0 - xmm7 (c_farg0, c_farg1, ... )
#endif
#endif // _WIN64
n_int_register_parameters_j = 6, // j_rarg0, j_rarg1, ...
n_float_register_parameters_j = 8 // j_farg0, j_farg1, ...
};
@ -77,7 +77,7 @@ REGISTER_DECLARATION(XMMRegister, c_farg5, xmm5);
REGISTER_DECLARATION(XMMRegister, c_farg6, xmm6);
REGISTER_DECLARATION(XMMRegister, c_farg7, xmm7);
#endif
#endif // _WIN64
// Symbolically name the register arguments used by the Java calling convention.
// We have control over the convention for java so we can do what we please.
@ -105,7 +105,7 @@ REGISTER_DECLARATION(Register, j_rarg4, rsi);
#else
REGISTER_DECLARATION(Register, j_rarg3, c_rarg4);
REGISTER_DECLARATION(Register, j_rarg4, c_rarg5);
#endif /* _WIN64 */
#endif // _WIN64
REGISTER_DECLARATION(Register, j_rarg5, c_rarg0);
REGISTER_DECLARATION(XMMRegister, j_farg0, xmm0);
@ -120,7 +120,8 @@ REGISTER_DECLARATION(XMMRegister, j_farg7, xmm7);
REGISTER_DECLARATION(Register, rscratch1, r10); // volatile
REGISTER_DECLARATION(Register, rscratch2, r11); // volatile
REGISTER_DECLARATION(Register, r15_thread, r15); // callee-saved
REGISTER_DECLARATION(Register, r12_heapbase, r12); // callee-saved
REGISTER_DECLARATION(Register, r15_thread, r15); // callee-saved
#endif // _LP64
@ -785,7 +786,8 @@ class Assembler : public AbstractAssembler {
void rep_movl();
void rep_movq();
void rep_set();
void repne_scan();
void repne_scanl();
void repne_scanq();
void setb(Condition cc, Register dst);
void clflush(Address adr);
@ -1099,6 +1101,17 @@ class MacroAssembler : public Assembler {
void movbool(Address dst, Register src);
void testbool(Register dst);
// oop manipulations
void load_klass(Register dst, Register src);
void store_klass(Register dst, Register src);
void load_heap_oop(Register dst, Address src);
void store_heap_oop(Address dst, Register src);
void encode_heap_oop(Register r);
void decode_heap_oop(Register r);
void encode_heap_oop_not_null(Register r);
void decode_heap_oop_not_null(Register r);
// Stack frame creation/removal
void enter();
void leave();
@ -1250,6 +1263,9 @@ class MacroAssembler : public Assembler {
void verify_oop(Register reg, const char* s = "broken oop");
void verify_oop_addr(Address addr, const char * s = "broken oop addr");
// if heap base register is used - reinit it with the correct value
void reinit_heapbase();
// only if +VerifyFPU
void verify_FPU(int stack_depth, const char* s = "illegal FPU state") {}

@ -218,7 +218,7 @@ void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2,
void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2) {
assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0,
"con_size_in_bytes is not multiple of alignment");
const int hdr_size_in_bytes = oopDesc::header_size_in_bytes();
const int hdr_size_in_bytes = instanceOopDesc::base_offset_in_bytes();
initialize_header(obj, klass, noreg, t1, t2);

@ -267,15 +267,29 @@ void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass,
addq(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
// Scan rcx words at [rdi] for occurance of rax
// Set NZ/Z based on last compare
repne_scan();
// Not equal?
jcc(Assembler::notEqual, not_subtype);
// this part is kind tricky, as values in supers array could be 32 or 64 bit wide
// and we store values in objArrays always encoded, thus we need to encode value
// before repne
if (UseCompressedOops) {
encode_heap_oop(rax);
repne_scanl();
// Not equal?
jcc(Assembler::notEqual, not_subtype);
// decode heap oop here for movq
decode_heap_oop(rax);
} else {
repne_scanq();
jcc(Assembler::notEqual, not_subtype);
}
// Must be equal but missed in cache. Update cache.
movq(Address(Rsub_klass, sizeof(oopDesc) +
Klass::secondary_super_cache_offset_in_bytes()), rax);
jmp(ok_is_subtype);
bind(not_subtype);
// decode heap oop here for miss
if (UseCompressedOops) decode_heap_oop(rax);
profile_typecheck_failed(rcx); // blows rcx
}

@ -375,7 +375,7 @@ address InterpreterGenerator::generate_accessor_entry(void) {
__ cmpl(rdx, atos);
__ jcc(Assembler::notEqual, notObj);
// atos
__ movq(rax, field_address);
__ load_heap_oop(rax, field_address);
__ jmp(xreturn_path);
__ bind(notObj);

@ -106,6 +106,7 @@ REGISTER_DEFINITION(XMMRegister, j_farg7);
REGISTER_DEFINITION(Register, rscratch1);
REGISTER_DEFINITION(Register, rscratch2);
REGISTER_DEFINITION(Register, r12_heapbase);
REGISTER_DEFINITION(Register, r15_thread);
#endif // AMD64

@ -789,7 +789,7 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm
{
__ verify_oop(holder);
__ movq(temp, Address(receiver, oopDesc::klass_offset_in_bytes()));
__ load_klass(temp, receiver);
__ verify_oop(temp);
__ cmpq(temp, Address(holder, compiledICHolderOopDesc::holder_klass_offset()));
@ -1297,21 +1297,26 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
const Register ic_reg = rax;
const Register receiver = j_rarg0;
const Register tmp = rdx;
Label ok;
Label exception_pending;
__ verify_oop(receiver);
__ cmpq(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes()));
__ pushq(tmp); // spill (any other registers free here???)
__ load_klass(tmp, receiver);
__ cmpq(ic_reg, tmp);
__ jcc(Assembler::equal, ok);
__ popq(tmp);
__ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
__ bind(ok);
__ popq(tmp);
// Verified entry point must be aligned
__ align(8);
__ bind(ok);
int vep_offset = ((intptr_t)__ pc()) - start;
// The instruction at the verified entry point must be 5 bytes or longer
@ -1663,6 +1668,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ andq(rsp, -16); // align stack as required by ABI
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)));
__ movq(rsp, r12); // restore sp
__ reinit_heapbase();
// Restore any method result value
restore_native_result(masm, ret_type, stack_slots);
__ bind(Continue);
@ -1725,7 +1731,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ bind(done);
}
{
SkipIfEqual skip(masm, &DTraceMethodProbes, false);
save_native_result(masm, ret_type, stack_slots);
@ -1829,6 +1834,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C)));
__ movq(rsp, r12); // restore sp
__ reinit_heapbase();
#ifdef ASSERT
{
Label L;
@ -1859,6 +1865,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ andq(rsp, -16); // align stack as required by ABI
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages)));
__ movq(rsp, r12); // restore sp
__ reinit_heapbase();
restore_native_result(masm, ret_type, stack_slots);
// and continue
__ jmp(reguard_done);
@ -1941,9 +1948,8 @@ void SharedRuntime::generate_deopt_blob() {
map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words);
// Normal deoptimization. Save exec mode for unpack_frames.
__ movl(r12, Deoptimization::Unpack_deopt); // callee-saved
__ movl(r14, Deoptimization::Unpack_deopt); // callee-saved
__ jmp(cont);
int exception_offset = __ pc() - start;
// Prolog for exception case
@ -1955,7 +1961,7 @@ void SharedRuntime::generate_deopt_blob() {
map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words);
// Deopt during an exception. Save exec mode for unpack_frames.
__ movl(r12, Deoptimization::Unpack_exception); // callee-saved
__ movl(r14, Deoptimization::Unpack_exception); // callee-saved
__ bind(cont);
@ -2088,7 +2094,7 @@ void SharedRuntime::generate_deopt_blob() {
__ set_last_Java_frame(noreg, rbp, NULL);
__ movq(c_rarg0, r15_thread);
__ movl(c_rarg1, r12); // second arg: exec_mode
__ movl(c_rarg1, r14); // second arg: exec_mode
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames)));
// Set an oopmap for the call site

@ -30,6 +30,7 @@
// see the comment in stubRoutines.hpp
#define __ _masm->
#define TIMES_OOP (UseCompressedOops ? Address::times_4 : Address::times_8)
#ifdef PRODUCT
#define BLOCK_COMMENT(str) /* nothing */
@ -252,6 +253,7 @@ class StubGenerator: public StubCodeGenerator {
// Load up thread register
__ movq(r15_thread, thread);
__ reinit_heapbase();
#ifdef ASSERT
// make sure we have no pending exceptions
@ -945,7 +947,7 @@ class StubGenerator: public StubCodeGenerator {
__ jcc(Assembler::notZero, error);
// make sure klass is 'reasonable'
__ movq(rax, Address(rax, oopDesc::klass_offset_in_bytes())); // get klass
__ load_klass(rax, rax); // get klass
__ testq(rax, rax);
__ jcc(Assembler::zero, error); // if klass is NULL it is broken
// Check if the klass is in the right area of memory
@ -957,7 +959,7 @@ class StubGenerator: public StubCodeGenerator {
__ jcc(Assembler::notZero, error);
// make sure klass' klass is 'reasonable'
__ movq(rax, Address(rax, oopDesc::klass_offset_in_bytes()));
__ load_klass(rax, rax);
__ testq(rax, rax);
__ jcc(Assembler::zero, error); // if klass' klass is NULL it is broken
// Check if the klass' klass is in the right area of memory
@ -1001,6 +1003,7 @@ class StubGenerator: public StubCodeGenerator {
BLOCK_COMMENT("call MacroAssembler::debug");
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug)));
__ movq(rsp, r12); // restore rsp
__ reinit_heapbase(); // r12 is heapbase
__ popaq(); // pop registers
__ ret(3 * wordSize); // pop caller saved stuff
@ -1652,6 +1655,7 @@ class StubGenerator: public StubCodeGenerator {
// Arguments:
// aligned - true => Input and output aligned on a HeapWord == 8-byte boundary
// ignored
// is_oop - true => oop array, so generate store check code
// name - stub name string
//
// Inputs:
@ -1665,9 +1669,9 @@ class StubGenerator: public StubCodeGenerator {
//
// Side Effects:
// disjoint_int_copy_entry is set to the no-overlap entry point
// used by generate_conjoint_int_copy().
// used by generate_conjoint_int_oop_copy().
//
address generate_disjoint_int_copy(bool aligned, const char *name) {
address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, const char *name) {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", name);
address start = __ pc();
@ -1680,19 +1684,30 @@ class StubGenerator: public StubCodeGenerator {
const Register qword_count = count;
const Register end_from = from; // source array end address
const Register end_to = to; // destination array end address
const Register saved_to = r11; // saved destination array address
// End pointers are inclusive, and if count is not zero they point
// to the last unit copied: end_to[0] := end_from[0]
__ enter(); // required for proper stackwalking of RuntimeStub frame
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
disjoint_int_copy_entry = __ pc();
(is_oop ? disjoint_oop_copy_entry : disjoint_int_copy_entry) = __ pc();
if (is_oop) {
// no registers are destroyed by this call
gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2);
}
BLOCK_COMMENT("Entry:");
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
// r9 and r10 may be used to save non-volatile registers
if (is_oop) {
__ movq(saved_to, to);
}
// 'from', 'to' and 'count' are now valid
__ movq(dword_count, count);
__ shrq(count, 1); // count => qword_count
@ -1718,6 +1733,10 @@ class StubGenerator: public StubCodeGenerator {
__ movl(Address(end_to, 8), rax);
__ BIND(L_exit);
if (is_oop) {
__ leaq(end_to, Address(saved_to, dword_count, Address::times_4, -4));
gen_write_ref_array_post_barrier(saved_to, end_to, rax);
}
inc_counter_np(SharedRuntime::_jint_array_copy_ctr);
restore_arg_regs();
__ xorq(rax, rax); // return 0
@ -1734,6 +1753,7 @@ class StubGenerator: public StubCodeGenerator {
// Arguments:
// aligned - true => Input and output aligned on a HeapWord == 8-byte boundary
// ignored
// is_oop - true => oop array, so generate store check code
// name - stub name string
//
// Inputs:
@ -1745,12 +1765,12 @@ class StubGenerator: public StubCodeGenerator {
// the hardware handle it. The two dwords within qwords that span
// cache line boundaries will still be loaded and stored atomicly.
//
address generate_conjoint_int_copy(bool aligned, const char *name) {
address generate_conjoint_int_oop_copy(bool aligned, bool is_oop, const char *name) {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", name);
address start = __ pc();
Label L_copy_32_bytes, L_copy_8_bytes, L_copy_2_bytes;
Label L_copy_32_bytes, L_copy_8_bytes, L_copy_2_bytes, L_exit;
const Register from = rdi; // source array address
const Register to = rsi; // destination array address
const Register count = rdx; // elements count
@ -1760,14 +1780,21 @@ class StubGenerator: public StubCodeGenerator {
__ enter(); // required for proper stackwalking of RuntimeStub frame
assert_clean_int(c_rarg2, rax); // Make sure 'count' is clean int.
int_copy_entry = __ pc();
if (is_oop) {
// no registers are destroyed by this call
gen_write_ref_array_pre_barrier(/* dest */ c_rarg1, /* count */ c_rarg2);
}
(is_oop ? oop_copy_entry : int_copy_entry) = __ pc();
BLOCK_COMMENT("Entry:");
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
array_overlap_test(disjoint_int_copy_entry, Address::times_4);
array_overlap_test(is_oop ? disjoint_oop_copy_entry : disjoint_int_copy_entry,
Address::times_4);
setup_arg_regs(); // from => rdi, to => rsi, count => rdx
// r9 and r10 may be used to save non-volatile registers
assert_clean_int(count, rax); // Make sure 'count' is clean int.
// 'from', 'to' and 'count' are now valid
__ movq(dword_count, count);
__ shrq(count, 1); // count => qword_count
@ -1789,6 +1816,9 @@ class StubGenerator: public StubCodeGenerator {
__ jcc(Assembler::notZero, L_copy_8_bytes);
inc_counter_np(SharedRuntime::_jint_array_copy_ctr);
if (is_oop) {
__ jmp(L_exit);
}
restore_arg_regs();
__ xorq(rax, rax); // return 0
__ leave(); // required for proper stackwalking of RuntimeStub frame
@ -1797,7 +1827,13 @@ class StubGenerator: public StubCodeGenerator {
// Copy in 32-bytes chunks
copy_32_bytes_backward(from, to, qword_count, rax, L_copy_32_bytes, L_copy_8_bytes);
inc_counter_np(SharedRuntime::_jint_array_copy_ctr);
inc_counter_np(SharedRuntime::_jint_array_copy_ctr);
__ bind(L_exit);
if (is_oop) {
Register end_to = rdx;
__ leaq(end_to, Address(to, dword_count, Address::times_4, -4));
gen_write_ref_array_post_barrier(to, end_to, rax);
}
restore_arg_regs();
__ xorq(rax, rax); // return 0
__ leave(); // required for proper stackwalking of RuntimeStub frame
@ -1817,7 +1853,7 @@ class StubGenerator: public StubCodeGenerator {
// c_rarg1 - destination array address
// c_rarg2 - element count, treated as ssize_t, can be zero
//
// Side Effects:
// Side Effects:
// disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the
// no-overlap entry point used by generate_conjoint_long_oop_copy().
//
@ -1857,7 +1893,7 @@ class StubGenerator: public StubCodeGenerator {
// Copy from low to high addresses. Use 'to' as scratch.
__ leaq(end_from, Address(from, qword_count, Address::times_8, -8));
__ leaq(end_to, Address(to, qword_count, Address::times_8, -8));
__ leaq(end_to, Address(to, qword_count, Address::times_8, -8));
__ negq(qword_count);
__ jmp(L_copy_32_bytes);
@ -1923,11 +1959,14 @@ class StubGenerator: public StubCodeGenerator {
address disjoint_copy_entry = NULL;
if (is_oop) {
assert(!UseCompressedOops, "shouldn't be called for compressed oops");
disjoint_copy_entry = disjoint_oop_copy_entry;
oop_copy_entry = __ pc();
array_overlap_test(disjoint_oop_copy_entry, Address::times_8);
} else {
disjoint_copy_entry = disjoint_long_copy_entry;
long_copy_entry = __ pc();
array_overlap_test(disjoint_long_copy_entry, Address::times_8);
}
BLOCK_COMMENT("Entry:");
// caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
@ -1945,8 +1984,6 @@ class StubGenerator: public StubCodeGenerator {
gen_write_ref_array_pre_barrier(to, saved_count);
}
// Copy from high to low addresses. Use rcx as scratch.
__ jmp(L_copy_32_bytes);
// Copy trailing qwords
@ -2038,7 +2075,14 @@ class StubGenerator: public StubCodeGenerator {
// Scan rcx words at [rdi] for occurance of rax
// Set NZ/Z based on last compare
__ movq(rax, super_klass);
__ repne_scan();
if (UseCompressedOops) {
// Compare against compressed form. Don't need to uncompress because
// looks like orig rax is restored in popq below.
__ encode_heap_oop(rax);
__ repne_scanl();
} else {
__ repne_scanq();
}
// Unspill the temp. registers:
__ popq(rdi);
@ -2115,7 +2159,7 @@ class StubGenerator: public StubCodeGenerator {
// caller guarantees that the arrays really are different
// otherwise, we would have to make conjoint checks
{ Label L;
array_overlap_test(L, Address::times_8);
array_overlap_test(L, TIMES_OOP);
__ stop("checkcast_copy within a single array");
__ bind(L);
}
@ -2160,12 +2204,11 @@ class StubGenerator: public StubCodeGenerator {
#endif //ASSERT
// Loop-invariant addresses. They are exclusive end pointers.
Address end_from_addr(from, length, Address::times_8, 0);
Address end_to_addr(to, length, Address::times_8, 0);
Address end_from_addr(from, length, TIMES_OOP, 0);
Address end_to_addr(to, length, TIMES_OOP, 0);
// Loop-variant addresses. They assume post-incremented count < 0.
Address from_element_addr(end_from, count, Address::times_8, 0);
Address to_element_addr(end_to, count, Address::times_8, 0);
Address oop_klass_addr(rax_oop, oopDesc::klass_offset_in_bytes());
Address from_element_addr(end_from, count, TIMES_OOP, 0);
Address to_element_addr(end_to, count, TIMES_OOP, 0);
gen_write_ref_array_pre_barrier(to, count);
@ -2189,17 +2232,17 @@ class StubGenerator: public StubCodeGenerator {
__ align(16);
__ BIND(L_store_element);
__ movq(to_element_addr, rax_oop); // store the oop
__ store_heap_oop(to_element_addr, rax_oop); // store the oop
__ incrementq(count); // increment the count toward zero
__ jcc(Assembler::zero, L_do_card_marks);
// ======== loop entry is here ========
__ BIND(L_load_element);
__ movq(rax_oop, from_element_addr); // load the oop
__ load_heap_oop(rax_oop, from_element_addr); // load the oop
__ testq(rax_oop, rax_oop);
__ jcc(Assembler::zero, L_store_element);
__ movq(r11_klass, oop_klass_addr); // query the object klass
__ load_klass(r11_klass, rax_oop);// query the object klass
generate_type_check(r11_klass, ckoff, ckval, L_store_element);
// ======== end loop ========
@ -2425,15 +2468,14 @@ class StubGenerator: public StubCodeGenerator {
// registers used as temp
const Register r11_length = r11; // elements count to copy
const Register r10_src_klass = r10; // array klass
const Register r9_dst_klass = r9; // dest array klass
// if (length < 0) return -1;
__ movl(r11_length, C_RARG4); // length (elements count, 32-bits value)
__ testl(r11_length, r11_length);
__ jccb(Assembler::negative, L_failed_0);
Address src_klass_addr(src, oopDesc::klass_offset_in_bytes());
Address dst_klass_addr(dst, oopDesc::klass_offset_in_bytes());
__ movq(r10_src_klass, src_klass_addr);
__ load_klass(r10_src_klass, src);
#ifdef ASSERT
// assert(src->klass() != NULL);
BLOCK_COMMENT("assert klasses not null");
@ -2443,7 +2485,8 @@ class StubGenerator: public StubCodeGenerator {
__ bind(L1);
__ stop("broken null klass");
__ bind(L2);
__ cmpq(dst_klass_addr, 0);
__ load_klass(r9_dst_klass, dst);
__ cmpq(r9_dst_klass, 0);
__ jcc(Assembler::equal, L1); // this would be broken also
BLOCK_COMMENT("assert done");
}
@ -2470,7 +2513,8 @@ class StubGenerator: public StubCodeGenerator {
__ jcc(Assembler::equal, L_objArray);
// if (src->klass() != dst->klass()) return -1;
__ cmpq(r10_src_klass, dst_klass_addr);
__ load_klass(r9_dst_klass, dst);
__ cmpq(r10_src_klass, r9_dst_klass);
__ jcc(Assembler::notEqual, L_failed);
// if (!src->is_Array()) return -1;
@ -2559,17 +2603,18 @@ class StubGenerator: public StubCodeGenerator {
Label L_plain_copy, L_checkcast_copy;
// test array classes for subtyping
__ cmpq(r10_src_klass, dst_klass_addr); // usual case is exact equality
__ load_klass(r9_dst_klass, dst);
__ cmpq(r10_src_klass, r9_dst_klass); // usual case is exact equality
__ jcc(Assembler::notEqual, L_checkcast_copy);
// Identically typed arrays can be copied without element-wise checks.
arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
r10, L_failed);
__ leaq(from, Address(src, src_pos, Address::times_8,
__ leaq(from, Address(src, src_pos, TIMES_OOP,
arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // src_addr
__ leaq(to, Address(dst, dst_pos, Address::times_8,
arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
__ leaq(to, Address(dst, dst_pos, TIMES_OOP,
arrayOopDesc::base_offset_in_bytes(T_OBJECT))); // dst_addr
__ movslq(count, r11_length); // length
__ BIND(L_plain_copy);
__ jump(RuntimeAddress(oop_copy_entry));
@ -2579,7 +2624,7 @@ class StubGenerator: public StubCodeGenerator {
{
// assert(r11_length == C_RARG4); // will reload from here
Register r11_dst_klass = r11;
__ movq(r11_dst_klass, dst_klass_addr);
__ load_klass(r11_dst_klass, dst);
// Before looking at dst.length, make sure dst is also an objArray.
__ cmpl(Address(r11_dst_klass, lh_offset), objArray_lh);
@ -2593,13 +2638,13 @@ class StubGenerator: public StubCodeGenerator {
__ movl(r11_length, C_RARG4); // reload
arraycopy_range_checks(src, src_pos, dst, dst_pos, r11_length,
rax, L_failed);
__ movl(r11_dst_klass, dst_klass_addr); // reload
__ load_klass(r11_dst_klass, dst); // reload
#endif
// Marshal the base address arguments now, freeing registers.
__ leaq(from, Address(src, src_pos, Address::times_8,
__ leaq(from, Address(src, src_pos, TIMES_OOP,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
__ leaq(to, Address(dst, dst_pos, Address::times_8,
__ leaq(to, Address(dst, dst_pos, TIMES_OOP,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
__ movl(count, C_RARG4); // length (reloaded)
Register sco_temp = c_rarg3; // this register is free now
@ -2648,14 +2693,20 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, "jshort_disjoint_arraycopy");
StubRoutines::_jshort_arraycopy = generate_conjoint_short_copy(false, "jshort_arraycopy");
StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, "jint_disjoint_arraycopy");
StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, "jint_arraycopy");
StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, false, "jint_disjoint_arraycopy");
StubRoutines::_jint_arraycopy = generate_conjoint_int_oop_copy(false, false, "jint_arraycopy");
StubRoutines::_jlong_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, false, "jlong_disjoint_arraycopy");
StubRoutines::_jlong_arraycopy = generate_conjoint_long_oop_copy(false, false, "jlong_arraycopy");
StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, true, "oop_disjoint_arraycopy");
StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(false, true, "oop_arraycopy");
if (UseCompressedOops) {
StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_int_oop_copy(false, true, "oop_disjoint_arraycopy");
StubRoutines::_oop_arraycopy = generate_conjoint_int_oop_copy(false, true, "oop_arraycopy");
} else {
StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, true, "oop_disjoint_arraycopy");
StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(false, true, "oop_arraycopy");
}
StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy");
StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy");

@ -664,7 +664,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
// work registers
const Register method = rbx;
const Register t = r12;
const Register t = r11;
// allocate space for parameters
__ get_method(method);
@ -844,6 +844,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
__ andq(rsp, -16); // align stack as required by ABI
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans)));
__ movq(rsp, r12); // restore sp
__ reinit_heapbase();
__ bind(Continue);
}
@ -891,6 +892,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages)));
__ movq(rsp, r12); // restore sp
__ popaq(); // XXX only restore smashed registers
__ reinit_heapbase();
__ bind(no_reguard);
}
@ -1360,6 +1362,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() {
// rdx: return address/pc that threw exception
__ restore_bcp(); // r13 points to call/send
__ restore_locals();
__ reinit_heapbase(); // restore r12 as heapbase.
// Entry point for exceptions thrown within interpreter code
Interpreter::_throw_exception_entry = __ pc();
// expression stack is undefined here
@ -1658,6 +1661,7 @@ void TemplateInterpreterGenerator::trace_bytecode(Template* t) {
__ andq(rsp, -16); // align stack as required by ABI
__ call(RuntimeAddress(Interpreter::trace_code(t->tos_in())));
__ movq(rsp, r12); // restore sp
__ reinit_heapbase();
}

@ -557,8 +557,8 @@ void TemplateTable::aaload() {
// eax: index
// rdx: array
index_check(rdx, rax); // kills rbx
__ movq(rax, Address(rdx, rax,
Address::times_8,
__ load_heap_oop(rax, Address(rdx, rax,
UseCompressedOops ? Address::times_4 : Address::times_8,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
}
@ -870,15 +870,15 @@ void TemplateTable::aastore() {
__ jcc(Assembler::zero, is_null);
// Move subklass into rbx
__ movq(rbx, Address(rax, oopDesc::klass_offset_in_bytes()));
__ load_klass(rbx, rax);
// Move superklass into rax
__ movq(rax, Address(rdx, oopDesc::klass_offset_in_bytes()));
__ load_klass(rax, rdx);
__ movq(rax, Address(rax,
sizeof(oopDesc) +
objArrayKlass::element_klass_offset_in_bytes()));
// Compress array + index*8 + 12 into a single register. Frees rcx.
// Compress array + index*oopSize + 12 into a single register. Frees rcx.
__ leaq(rdx, Address(rdx, rcx,
Address::times_8,
UseCompressedOops ? Address::times_4 : Address::times_8,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
// Generate subtype check. Blows rcx, rdi
@ -892,17 +892,17 @@ void TemplateTable::aastore() {
// Come here on success
__ bind(ok_is_subtype);
__ movq(rax, at_tos()); // Value
__ movq(Address(rdx, 0), rax);
__ store_heap_oop(Address(rdx, 0), rax);
__ store_check(rdx);
__ jmp(done);
// Have a NULL in rax, rdx=array, ecx=index. Store NULL at ary[idx]
__ bind(is_null);
__ profile_null_seen(rbx);
__ movq(Address(rdx, rcx,
Address::times_8,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)),
rax);
__ store_heap_oop(Address(rdx, rcx,
UseCompressedOops ? Address::times_4 : Address::times_8,
arrayOopDesc::base_offset_in_bytes(T_OBJECT)),
rax);
// Pop stack arguments
__ bind(done);
@ -1934,7 +1934,7 @@ void TemplateTable::_return(TosState state) {
if (_desc->bytecode() == Bytecodes::_return_register_finalizer) {
assert(state == vtos, "only valid state");
__ movq(c_rarg1, aaddress(0));
__ movq(rdi, Address(c_rarg1, oopDesc::klass_offset_in_bytes()));
__ load_klass(rdi, c_rarg1);
__ movl(rdi, Address(rdi, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc)));
__ testl(rdi, JVM_ACC_HAS_FINALIZER);
Label skip_register_finalizer;
@ -2184,7 +2184,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
__ cmpl(flags, atos);
__ jcc(Assembler::notEqual, notObj);
// atos
__ movq(rax, field);
__ load_heap_oop(rax, field);
__ push(atos);
if (!is_static) {
patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx);
@ -2394,7 +2394,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
// atos
__ pop(atos);
if (!is_static) pop_and_check_object(obj);
__ movq(field, rax);
__ store_heap_oop(field, rax);
__ store_check(obj, field); // Need to mark card
if (!is_static) {
patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx);
@ -2515,7 +2515,7 @@ void TemplateTable::jvmti_post_fast_field_mod() {
const Address field(c_rarg3, 0);
switch (bytecode()) { // load values into the jvalue object
case Bytecodes::_fast_aputfield: // fall through
case Bytecodes::_fast_aputfield: __ movq(field, rax); break;
case Bytecodes::_fast_lputfield: __ movq(field, rax); break;
case Bytecodes::_fast_iputfield: __ movl(field, rax); break;
case Bytecodes::_fast_bputfield: __ movb(field, rax); break;
@ -2582,7 +2582,7 @@ void TemplateTable::fast_storefield(TosState state) {
// access field
switch (bytecode()) {
case Bytecodes::_fast_aputfield:
__ movq(field, rax);
__ store_heap_oop(field, rax);
__ store_check(rcx, field);
break;
case Bytecodes::_fast_lputfield:
@ -2631,8 +2631,8 @@ void TemplateTable::fast_accessfield(TosState state) {
__ jcc(Assembler::zero, L1);
// access constant pool cache entry
__ get_cache_entry_pointer_at_bcp(c_rarg2, rcx, 1);
__ movq(r12, rax); // save object pointer before call_VM() clobbers it
__ verify_oop(rax);
__ movq(r12, rax); // save object pointer before call_VM() clobbers it
__ movq(c_rarg1, rax);
// c_rarg1: object pointer copied above
// c_rarg2: cache entry pointer
@ -2641,6 +2641,7 @@ void TemplateTable::fast_accessfield(TosState state) {
InterpreterRuntime::post_field_access),
c_rarg1, c_rarg2);
__ movq(rax, r12); // restore object pointer
__ reinit_heapbase();
__ bind(L1);
}
@ -2667,7 +2668,7 @@ void TemplateTable::fast_accessfield(TosState state) {
// access field
switch (bytecode()) {
case Bytecodes::_fast_agetfield:
__ movq(rax, field);
__ load_heap_oop(rax, field);
__ verify_oop(rax);
break;
case Bytecodes::_fast_lgetfield:
@ -2725,7 +2726,7 @@ void TemplateTable::fast_xaccess(TosState state) {
__ movl(rax, Address(rax, rbx, Address::times_1));
break;
case atos:
__ movq(rax, Address(rax, rbx, Address::times_1));
__ load_heap_oop(rax, Address(rax, rbx, Address::times_1));
__ verify_oop(rax);
break;
case ftos:
@ -2787,7 +2788,8 @@ void TemplateTable::prepare_invoke(Register method,
__ movl(recv, flags);
__ andl(recv, 0xFF);
if (TaggedStackInterpreter) __ shll(recv, 1); // index*2
__ movq(recv, Address(rsp, recv, Address::times_8, -Interpreter::expr_offset_in_bytes(1)));
__ movq(recv, Address(rsp, recv, Address::times_8,
-Interpreter::expr_offset_in_bytes(1)));
__ verify_oop(recv);
}
@ -2854,7 +2856,7 @@ void TemplateTable::invokevirtual_helper(Register index,
// get receiver klass
__ null_check(recv, oopDesc::klass_offset_in_bytes());
__ movq(rax, Address(recv, oopDesc::klass_offset_in_bytes()));
__ load_klass(rax, recv);
__ verify_oop(rax);
@ -2866,8 +2868,8 @@ void TemplateTable::invokevirtual_helper(Register index,
assert(vtableEntry::size() * wordSize == 8,
"adjust the scaling in the code below");
__ movq(method, Address(rax, index,
Address::times_8,
base + vtableEntry::method_offset_in_bytes()));
Address::times_8,
base + vtableEntry::method_offset_in_bytes()));
__ movq(rdx, Address(method, methodOopDesc::interpreter_entry_offset()));
__ jump_from_interpreted(method, rdx);
}
@ -2932,7 +2934,7 @@ void TemplateTable::invokeinterface(int byte_no) {
// Get receiver klass into rdx - also a null check
__ restore_locals(); // restore r14
__ movq(rdx, Address(rcx, oopDesc::klass_offset_in_bytes()));
__ load_klass(rdx, rcx);
__ verify_oop(rdx);
// profile this call
@ -3161,7 +3163,7 @@ void TemplateTable::_new() {
__ movptr(Address(rax, oopDesc::mark_offset_in_bytes()),
(intptr_t) markOopDesc::prototype()); // header (address 0x1)
}
__ movq(Address(rax, oopDesc::klass_offset_in_bytes()), rsi); // klass
__ store_klass(rax, rsi); // klass
__ jmp(done);
}
@ -3223,12 +3225,12 @@ void TemplateTable::checkcast() {
typeArrayOopDesc::header_size(T_BYTE) * wordSize),
JVM_CONSTANT_Class);
__ jcc(Assembler::equal, quicked);
__ movq(r12, rcx); // save rcx XXX
__ push(atos); // save receiver for result, and for GC
__ movq(r12, rcx); // save rcx XXX
call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
__ pop_ptr(rdx); // restore receiver
__ movq(rcx, r12); // restore rcx XXX
__ reinit_heapbase();
__ pop_ptr(rdx); // restore receiver
__ jmpb(resolved);
// Get superklass in rax and subklass in rbx
@ -3238,7 +3240,7 @@ void TemplateTable::checkcast() {
Address::times_8, sizeof(constantPoolOopDesc)));
__ bind(resolved);
__ movq(rbx, Address(rdx, oopDesc::klass_offset_in_bytes()));
__ load_klass(rbx, rdx);
// Generate subtype check. Blows rcx, rdi. Object in rdx.
// Superklass in rax. Subklass in rbx.
@ -3280,19 +3282,20 @@ void TemplateTable::instanceof() {
JVM_CONSTANT_Class);
__ jcc(Assembler::equal, quicked);
__ movq(r12, rcx); // save rcx
__ push(atos); // save receiver for result, and for GC
__ movq(r12, rcx); // save rcx
call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
__ pop_ptr(rdx); // restore receiver
__ movq(rdx, Address(rdx, oopDesc::klass_offset_in_bytes()));
__ movq(rcx, r12); // restore rcx
__ reinit_heapbase();
__ pop_ptr(rdx); // restore receiver
__ load_klass(rdx, rdx);
__ jmpb(resolved);
// Get superklass in rax and subklass in rdx
__ bind(quicked);
__ movq(rdx, Address(rax, oopDesc::klass_offset_in_bytes()));
__ load_klass(rdx, rax);
__ movq(rax, Address(rcx, rbx,
Address::times_8, sizeof(constantPoolOopDesc)));
Address::times_8, sizeof(constantPoolOopDesc)));
__ bind(resolved);

@ -56,7 +56,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
// get receiver klass
address npe_addr = __ pc();
__ movq(rax, Address(j_rarg0, oopDesc::klass_offset_in_bytes()));
__ load_klass(rax, j_rarg0);
// compute entry offset (in words)
int entry_offset =
@ -131,7 +131,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
// get receiver klass (also an implicit null-check)
address npe_addr = __ pc();
__ movq(rbx, Address(j_rarg0, oopDesc::klass_offset_in_bytes()));
__ load_klass(rbx, j_rarg0);
// If we take a trap while this arg is on the stack we will not
// be able to walk the stack properly. This is not an issue except
@ -181,7 +181,7 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
// Get methodOop and entrypoint for compiler
// Get klass pointer again
__ movq(rax, Address(j_rarg0, oopDesc::klass_offset_in_bytes()));
__ load_klass(rax, j_rarg0);
const Register method = rbx;
__ movq(method, Address(rax, j_rarg1, Address::times_1, method_offset));
@ -226,10 +226,12 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
if (is_vtable_stub) {
// Vtable stub size
return (DebugVtables ? 512 : 24) + (CountCompiledCalls ? 13 : 0);
return (DebugVtables ? 512 : 24) + (CountCompiledCalls ? 13 : 0) +
(UseCompressedOops ? 16 : 0); // 1 leaq can be 3 bytes + 1 long
} else {
// Itable stub size
return (DebugVtables ? 636 : 72) + (CountCompiledCalls ? 13 : 0);
return (DebugVtables ? 636 : 72) + (CountCompiledCalls ? 13 : 0) +
(UseCompressedOops ? 32 : 0); // 2 leaqs
}
}

@ -4538,8 +4538,8 @@ frame %{
// Location of C & interpreter return values
c_return_value %{
assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" );
static int lo[Op_RegL+1] = { 0, 0, EAX_num, EAX_num, FPR1L_num, FPR1L_num, EAX_num };
static int hi[Op_RegL+1] = { 0, 0, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, FPR1H_num, EDX_num };
static int lo[Op_RegL+1] = { 0, 0, OptoReg::Bad, EAX_num, EAX_num, FPR1L_num, FPR1L_num, EAX_num };
static int hi[Op_RegL+1] = { 0, 0, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, FPR1H_num, EDX_num };
// in SSE2+ mode we want to keep the FPU stack clean so pretend
// that C functions return float and double results in XMM0.
@ -4554,8 +4554,8 @@ frame %{
// Location of return values
return_value %{
assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" );
static int lo[Op_RegL+1] = { 0, 0, EAX_num, EAX_num, FPR1L_num, FPR1L_num, EAX_num };
static int hi[Op_RegL+1] = { 0, 0, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, FPR1H_num, EDX_num };
static int lo[Op_RegL+1] = { 0, 0, OptoReg::Bad, EAX_num, EAX_num, FPR1L_num, FPR1L_num, EAX_num };
static int hi[Op_RegL+1] = { 0, 0, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, FPR1H_num, EDX_num };
if( ideal_reg == Op_RegD && UseSSE>=2 )
return OptoRegPair(XMM0b_num,XMM0a_num);
if( ideal_reg == Op_RegF && UseSSE>=1 )

Some files were not shown because too many files have changed in this diff Show More