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:
parent
680ecf1611
commit
4a831d45f0
hotspot
agent/src/share/classes/sun/jvm/hotspot
CommandProcessor.javaHSDB.javaHotSpotTypeDataBase.java
compiler
debugger
Address.javaDebugger.javaDebuggerBase.javaJVMDebugger.javaMachineDescription.javaMachineDescriptionAMD64.javaMachineDescriptionIA64.javaMachineDescriptionIntelX86.javaMachineDescriptionSPARC32Bit.javaMachineDescriptionSPARC64Bit.java
dbx
dummy
linux
proc
remote
win32
windbg
memory
oops
Array.javaConstantPool.javaConstantPoolCache.javaConstantPoolCacheKlass.javaConstantPoolKlass.javaDefaultOopVisitor.javaInstance.javaInstanceKlass.javaKlass.javaNarrowOopField.javaObjArray.javaObjectHeap.javaObjectHistogram.javaObjectHistogramElement.javaOop.javaOopPrinter.javaOopUtilities.javaOopVisitor.java
runtime
types
ui
utilities
make
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
Loading…
x
Reference in New Issue
Block a user