This commit is contained in:
Vladimir Kozlov 2012-10-12 09:22:52 -07:00
commit 5f132a5ec3
135 changed files with 2294 additions and 1132 deletions

View file

@ -89,6 +89,7 @@ public interface Address {
public Address getAddressAt (long offset) throws UnmappedAddressException, UnalignedAddressException; public Address getAddressAt (long offset) throws UnmappedAddressException, UnalignedAddressException;
/** Returns the decoded address at the given offset */ /** Returns the decoded address at the given offset */
public Address getCompOopAddressAt (long offset) throws UnmappedAddressException, UnalignedAddressException; public Address getCompOopAddressAt (long offset) throws UnmappedAddressException, UnalignedAddressException;
public Address getCompKlassAddressAt (long offset) throws UnmappedAddressException, UnalignedAddressException;
// //
// Java-related routines // Java-related routines

View file

@ -121,6 +121,9 @@ public interface Debugger extends SymbolLookup, ThreadAccess {
public long getHeapOopSize(); public long getHeapOopSize();
public long getNarrowOopBase(); public long getNarrowOopBase();
public int getNarrowOopShift(); public int getNarrowOopShift();
public long getKlassPtrSize();
public long getNarrowKlassBase();
public int getNarrowKlassShift();
public ReadResult readBytesFromProcess(long address, long numBytes) public ReadResult readBytesFromProcess(long address, long numBytes)
throws DebuggerException; throws DebuggerException;

View file

@ -58,6 +58,10 @@ public abstract class DebuggerBase implements Debugger {
protected long heapOopSize; protected long heapOopSize;
protected long narrowOopBase; // heap base for compressed oops. protected long narrowOopBase; // heap base for compressed oops.
protected int narrowOopShift; // shift to decode compressed oops. protected int narrowOopShift; // shift to decode compressed oops.
// class metadata space
protected long klassPtrSize;
protected long narrowKlassBase; // heap base for compressed klass ptrs.
protected int narrowKlassShift; // shift to decode compressed klass ptrs.
// Should be initialized if desired by calling initCache() // Should be initialized if desired by calling initCache()
private PageCache cache; private PageCache cache;
@ -159,10 +163,14 @@ public abstract class DebuggerBase implements Debugger {
javaPrimitiveTypesConfigured = true; javaPrimitiveTypesConfigured = true;
} }
public void putHeapConst(long heapOopSize, long narrowOopBase, int narrowOopShift) { public void putHeapConst(long heapOopSize, long klassPtrSize, long narrowOopBase, int narrowOopShift,
long narrowKlassBase, int narrowKlassShift) {
this.heapOopSize = heapOopSize; this.heapOopSize = heapOopSize;
this.klassPtrSize = klassPtrSize;
this.narrowOopBase = narrowOopBase; this.narrowOopBase = narrowOopBase;
this.narrowOopShift = narrowOopShift; this.narrowOopShift = narrowOopShift;
this.narrowKlassBase = narrowKlassBase;
this.narrowKlassShift = narrowKlassShift;
} }
/** May be called by subclasses if desired to initialize the page /** May be called by subclasses if desired to initialize the page
@ -464,6 +472,15 @@ public abstract class DebuggerBase implements Debugger {
return value; return value;
} }
protected long readCompKlassAddressValue(long address)
throws UnmappedAddressException, UnalignedAddressException {
long value = readCInteger(address, getKlassPtrSize(), true);
if (value != 0) {
value = (long)(narrowKlassBase + (long)(value << narrowKlassShift));
}
return value;
}
protected void writeAddressValue(long address, long value) protected void writeAddressValue(long address, long value)
throws UnmappedAddressException, UnalignedAddressException { throws UnmappedAddressException, UnalignedAddressException {
writeCInteger(address, machDesc.getAddressSize(), value); writeCInteger(address, machDesc.getAddressSize(), value);
@ -551,4 +568,15 @@ public abstract class DebuggerBase implements Debugger {
public int getNarrowOopShift() { public int getNarrowOopShift() {
return narrowOopShift; return narrowOopShift;
} }
public long getKlassPtrSize() {
return klassPtrSize;
}
public long getNarrowKlassBase() {
return narrowKlassBase;
}
public int getNarrowKlassShift() {
return narrowKlassShift;
}
} }

View file

@ -42,5 +42,7 @@ public interface JVMDebugger extends Debugger {
long jintSize, long jintSize,
long jlongSize, long jlongSize,
long jshortSize); long jshortSize);
public void putHeapConst(long heapOopSize, long narrowOopBase, int narrowOopShift); public void putHeapConst(long heapOopSize, long klassPtrSize,
long narrowKlassBase, int narrowKlassShift,
long narrowOopBase, int narrowOopShift);
} }

View file

@ -79,6 +79,11 @@ class BsdAddress implements Address {
return debugger.readCompOopAddress(addr + offset); return debugger.readCompOopAddress(addr + offset);
} }
public Address getCompKlassAddressAt(long offset)
throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompOopAddress(addr + offset);
}
// //
// Java-related routines // Java-related routines
// //

View file

@ -46,6 +46,7 @@ public interface BsdDebugger extends JVMDebugger {
throws DebuggerException; throws DebuggerException;
public BsdAddress readAddress(long address) throws DebuggerException; public BsdAddress readAddress(long address) throws DebuggerException;
public BsdAddress readCompOopAddress(long address) throws DebuggerException; public BsdAddress readCompOopAddress(long address) throws DebuggerException;
public BsdAddress readCompKlassAddress(long address) throws DebuggerException;
public BsdOopHandle readOopHandle(long address) throws DebuggerException; public BsdOopHandle readOopHandle(long address) throws DebuggerException;
public BsdOopHandle readCompOopHandle(long address) throws DebuggerException; public BsdOopHandle readCompOopHandle(long address) throws DebuggerException;
public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException; public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException;

View file

@ -431,6 +431,12 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
return (value == 0 ? null : new BsdAddress(this, value)); return (value == 0 ? null : new BsdAddress(this, value));
} }
public BsdAddress readCompKlassAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
long value = readCompKlassAddressValue(address);
return (value == 0 ? null : new BsdAddress(this, value));
}
/** From the BsdDebugger interface */ /** From the BsdDebugger interface */
public BsdOopHandle readOopHandle(long address) public BsdOopHandle readOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, throws UnmappedAddressException, UnalignedAddressException,

View file

@ -80,6 +80,10 @@ class DummyAddress implements Address {
return new DummyAddress(debugger, badLong); return new DummyAddress(debugger, badLong);
} }
public Address getCompKlassAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return new DummyAddress(debugger, badLong);
}
// //
// Java-related routines // Java-related routines
// //

View file

@ -79,6 +79,11 @@ class LinuxAddress implements Address {
return debugger.readCompOopAddress(addr + offset); return debugger.readCompOopAddress(addr + offset);
} }
public Address getCompKlassAddressAt(long offset)
throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompKlassAddress(addr + offset);
}
// //
// Java-related routines // Java-related routines
// //

View file

@ -46,6 +46,7 @@ public interface LinuxDebugger extends JVMDebugger {
throws DebuggerException; throws DebuggerException;
public LinuxAddress readAddress(long address) throws DebuggerException; public LinuxAddress readAddress(long address) throws DebuggerException;
public LinuxAddress readCompOopAddress(long address) throws DebuggerException; public LinuxAddress readCompOopAddress(long address) throws DebuggerException;
public LinuxAddress readCompKlassAddress(long address) throws DebuggerException;
public LinuxOopHandle readOopHandle(long address) throws DebuggerException; public LinuxOopHandle readOopHandle(long address) throws DebuggerException;
public LinuxOopHandle readCompOopHandle(long address) throws DebuggerException; public LinuxOopHandle readCompOopHandle(long address) throws DebuggerException;
public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException; public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException;

View file

@ -429,6 +429,12 @@ public class LinuxDebuggerLocal extends DebuggerBase implements LinuxDebugger {
return (value == 0 ? null : new LinuxAddress(this, value)); return (value == 0 ? null : new LinuxAddress(this, value));
} }
public LinuxAddress readCompKlassAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
long value = readCompKlassAddressValue(address);
return (value == 0 ? null : new LinuxAddress(this, value));
}
/** From the LinuxDebugger interface */ /** From the LinuxDebugger interface */
public LinuxOopHandle readOopHandle(long address) public LinuxOopHandle readOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, throws UnmappedAddressException, UnalignedAddressException,

View file

@ -76,6 +76,10 @@ class ProcAddress implements Address {
return debugger.readCompOopAddress(addr + offset); return debugger.readCompOopAddress(addr + offset);
} }
public Address getCompKlassAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompKlassAddress(addr + offset);
}
// //
// Java-related routines // Java-related routines
// //

View file

@ -47,6 +47,7 @@ public interface ProcDebugger extends JVMDebugger {
throws DebuggerException; throws DebuggerException;
public ProcAddress readAddress(long address) throws DebuggerException; public ProcAddress readAddress(long address) throws DebuggerException;
public ProcAddress readCompOopAddress(long address) throws DebuggerException; public ProcAddress readCompOopAddress(long address) throws DebuggerException;
public ProcAddress readCompKlassAddress(long address) throws DebuggerException;
public ProcOopHandle readOopHandle(long address) throws DebuggerException; public ProcOopHandle readOopHandle(long address) throws DebuggerException;
public ProcOopHandle readCompOopHandle(long address) throws DebuggerException; public ProcOopHandle readCompOopHandle(long address) throws DebuggerException;
public long[] getThreadIntegerRegisterSet(int tid) throws DebuggerException; public long[] getThreadIntegerRegisterSet(int tid) throws DebuggerException;

View file

@ -351,6 +351,12 @@ public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger {
return (value == 0 ? null : new ProcAddress(this, value)); return (value == 0 ? null : new ProcAddress(this, value));
} }
public ProcAddress readCompKlassAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
long value = readCompKlassAddressValue(address);
return (value == 0 ? null : new ProcAddress(this, value));
}
/** From the ProcDebugger interface */ /** From the ProcDebugger interface */
public ProcOopHandle readOopHandle(long address) public ProcOopHandle readOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {

View file

@ -74,6 +74,9 @@ class RemoteAddress implements Address {
public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompOopAddress(addr + offset); return debugger.readCompOopAddress(addr + offset);
} }
public Address getCompKlassAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompKlassAddress(addr + offset);
}
// //
// Java-related routines // Java-related routines

View file

@ -68,6 +68,9 @@ public interface RemoteDebugger extends Remote {
public long getHeapOopSize() throws RemoteException; public long getHeapOopSize() throws RemoteException;
public long getNarrowOopBase() throws RemoteException; public long getNarrowOopBase() throws RemoteException;
public int getNarrowOopShift() throws RemoteException; public int getNarrowOopShift() throws RemoteException;
public long getKlassPtrSize() throws RemoteException;
public long getNarrowKlassBase() throws RemoteException;
public int getNarrowKlassShift() throws RemoteException;
public boolean areThreadsEqual(long addrOrId1, boolean isAddress1, public boolean areThreadsEqual(long addrOrId1, boolean isAddress1,
long addrOrId2, boolean isAddress2) throws RemoteException; long addrOrId2, boolean isAddress2) throws RemoteException;

View file

@ -99,7 +99,10 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger {
javaPrimitiveTypesConfigured = true; javaPrimitiveTypesConfigured = true;
narrowOopBase = remoteDebugger.getNarrowOopBase(); narrowOopBase = remoteDebugger.getNarrowOopBase();
narrowOopShift = remoteDebugger.getNarrowOopShift(); narrowOopShift = remoteDebugger.getNarrowOopShift();
narrowKlassBase = remoteDebugger.getNarrowKlassBase();
narrowKlassShift = remoteDebugger.getNarrowKlassShift();
heapOopSize = remoteDebugger.getHeapOopSize(); heapOopSize = remoteDebugger.getHeapOopSize();
klassPtrSize = remoteDebugger.getKlassPtrSize();
} }
catch (RemoteException e) { catch (RemoteException e) {
throw new DebuggerException(e); throw new DebuggerException(e);
@ -319,6 +322,12 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger {
return (value == 0 ? null : new RemoteAddress(this, value)); return (value == 0 ? null : new RemoteAddress(this, value));
} }
RemoteAddress readCompKlassAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
long value = readCompKlassAddressValue(address);
return (value == 0 ? null : new RemoteAddress(this, value));
}
RemoteOopHandle readOopHandle(long address) RemoteOopHandle readOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
long value = readAddressValue(address); long value = readAddressValue(address);

View file

@ -126,6 +126,18 @@ public class RemoteDebuggerServer extends UnicastRemoteObject
return debugger.getNarrowOopShift(); return debugger.getNarrowOopShift();
} }
public long getKlassPtrSize() throws RemoteException {
return debugger.getHeapOopSize();
}
public long getNarrowKlassBase() throws RemoteException {
return debugger.getNarrowKlassBase();
}
public int getNarrowKlassShift() throws RemoteException {
return debugger.getNarrowKlassShift();
}
public boolean areThreadsEqual(long addrOrId1, boolean isAddress1, public boolean areThreadsEqual(long addrOrId1, boolean isAddress1,
long addrOrId2, boolean isAddress2) throws RemoteException { long addrOrId2, boolean isAddress2) throws RemoteException {
ThreadProxy t1 = getThreadProxy(addrOrId1, isAddress1); ThreadProxy t1 = getThreadProxy(addrOrId1, isAddress1);

View file

@ -76,6 +76,10 @@ class WindbgAddress implements Address {
return debugger.readCompOopAddress(addr + offset); return debugger.readCompOopAddress(addr + offset);
} }
public Address getCompKlassAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
return debugger.readCompKlassAddress(addr + offset);
}
// //
// Java-related routines // Java-related routines
// //

View file

@ -46,6 +46,7 @@ public interface WindbgDebugger extends JVMDebugger {
throws DebuggerException; throws DebuggerException;
public WindbgAddress readAddress(long address) throws DebuggerException; public WindbgAddress readAddress(long address) throws DebuggerException;
public WindbgAddress readCompOopAddress(long address) throws DebuggerException; public WindbgAddress readCompOopAddress(long address) throws DebuggerException;
public WindbgAddress readCompKlassAddress(long address) throws DebuggerException;
public WindbgOopHandle readOopHandle(long address) throws DebuggerException; public WindbgOopHandle readOopHandle(long address) throws DebuggerException;
public WindbgOopHandle readCompOopHandle(long address) throws DebuggerException; public WindbgOopHandle readCompOopHandle(long address) throws DebuggerException;

View file

@ -321,6 +321,11 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger
return (WindbgAddress) newAddress(readCompOopAddressValue(address)); return (WindbgAddress) newAddress(readCompOopAddressValue(address));
} }
public WindbgAddress readCompKlassAddress(long address)
throws UnmappedAddressException, UnalignedAddressException {
return (WindbgAddress) newAddress(readCompKlassAddressValue(address));
}
/** From the WindbgDebugger interface */ /** From the WindbgDebugger interface */
public WindbgOopHandle readOopHandle(long address) public WindbgOopHandle readOopHandle(long address)
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException { throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {

View file

@ -53,6 +53,8 @@ public class Universe {
private static AddressField narrowOopBaseField; private static AddressField narrowOopBaseField;
private static CIntegerField narrowOopShiftField; private static CIntegerField narrowOopShiftField;
private static AddressField narrowKlassBaseField;
private static CIntegerField narrowKlassShiftField;
static { static {
VM.registerVMInitializedObserver(new Observer() { VM.registerVMInitializedObserver(new Observer() {
@ -86,6 +88,8 @@ public class Universe {
narrowOopBaseField = type.getAddressField("_narrow_oop._base"); narrowOopBaseField = type.getAddressField("_narrow_oop._base");
narrowOopShiftField = type.getCIntegerField("_narrow_oop._shift"); narrowOopShiftField = type.getCIntegerField("_narrow_oop._shift");
narrowKlassBaseField = type.getAddressField("_narrow_klass._base");
narrowKlassShiftField = type.getCIntegerField("_narrow_klass._shift");
} }
public Universe() { public Universe() {
@ -111,6 +115,19 @@ public class Universe {
return (int)narrowOopShiftField.getValue(); return (int)narrowOopShiftField.getValue();
} }
public static long getNarrowKlassBase() {
if (narrowKlassBaseField.getValue() == null) {
return 0;
} else {
return narrowKlassBaseField.getValue().minus(null);
}
}
public static int getNarrowKlassShift() {
return (int)narrowKlassShiftField.getValue();
}
/** Returns "TRUE" iff "p" points into the allocated area of the heap. */ /** Returns "TRUE" iff "p" points into the allocated area of the heap. */
public boolean isIn(Address p) { public boolean isIn(Address p) {
return heap().isIn(p); return heap().isIn(p);

View file

@ -59,7 +59,7 @@ public class Array extends Oop {
if (headerSize != 0) { if (headerSize != 0) {
return headerSize; return headerSize;
} }
if (VM.getVM().isCompressedHeadersEnabled()) { if (VM.getVM().isCompressedKlassPointersEnabled()) {
headerSize = typeSize; headerSize = typeSize;
} else { } else {
headerSize = VM.getVM().alignUp(typeSize + VM.getVM().getIntSize(), headerSize = VM.getVM().alignUp(typeSize + VM.getVM().getIntSize(),
@ -80,7 +80,7 @@ public class Array extends Oop {
if (lengthOffsetInBytes != 0) { if (lengthOffsetInBytes != 0) {
return lengthOffsetInBytes; return lengthOffsetInBytes;
} }
if (VM.getVM().isCompressedHeadersEnabled()) { if (VM.getVM().isCompressedKlassPointersEnabled()) {
lengthOffsetInBytes = typeSize - VM.getVM().getIntSize(); lengthOffsetInBytes = typeSize - VM.getVM().getIntSize();
} else { } else {
lengthOffsetInBytes = typeSize; lengthOffsetInBytes = typeSize;

View file

@ -53,7 +53,7 @@ public class Instance extends Oop {
// Returns header size in bytes. // Returns header size in bytes.
public static long getHeaderSize() { public static long getHeaderSize() {
if (VM.getVM().isCompressedHeadersEnabled()) { if (VM.getVM().isCompressedKlassPointersEnabled()) {
return typeSize - VM.getVM().getIntSize(); return typeSize - VM.getVM().getIntSize();
} else { } else {
return typeSize; return typeSize;

View file

@ -27,7 +27,6 @@ package sun.jvm.hotspot.oops;
import sun.jvm.hotspot.runtime.VMObject; import sun.jvm.hotspot.runtime.VMObject;
import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.*;
// The class for an C int field simply provides access to the value.
public class MetadataField extends Field { public class MetadataField extends Field {
public MetadataField(sun.jvm.hotspot.types.AddressField vmField, long startOffset) { public MetadataField(sun.jvm.hotspot.types.AddressField vmField, long startOffset) {

View file

@ -0,0 +1,41 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.oops;
import sun.jvm.hotspot.debugger.*;
public class NarrowKlassField extends MetadataField {
public NarrowKlassField(sun.jvm.hotspot.types.AddressField vmField, long startOffset) {
super(vmField, startOffset);
}
public Metadata getValue(Address addr) {
return Metadata.instantiateWrapperFor(addr.getCompKlassAddressAt(getOffset()));
}
public void setValue(Oop obj, long value) throws MutationException {
// Fix this: set* missing in Address
}
}

View file

@ -47,10 +47,7 @@ public class Oop {
Type type = db.lookupType("oopDesc"); Type type = db.lookupType("oopDesc");
mark = new CIntField(type.getCIntegerField("_mark"), 0); mark = new CIntField(type.getCIntegerField("_mark"), 0);
klass = new MetadataField(type.getAddressField("_metadata._klass"), 0); klass = new MetadataField(type.getAddressField("_metadata._klass"), 0);
if (VM.getVM().isCompressedHeadersEnabled()) { compressedKlass = new NarrowKlassField(type.getAddressField("_metadata._compressed_klass"), 0);
// compressedKlass = new CIntField(type.getCIntegerField("_metadata._compressed_klass"), 0);
throw new InternalError("unimplemented");
}
headerSize = type.getSize(); headerSize = type.getSize();
} }
@ -74,13 +71,13 @@ public class Oop {
private static CIntField mark; private static CIntField mark;
private static MetadataField klass; private static MetadataField klass;
private static CIntField compressedKlass; private static NarrowKlassField compressedKlass;
// Accessors for declared fields // Accessors for declared fields
public Mark getMark() { return new Mark(getHandle()); } public Mark getMark() { return new Mark(getHandle()); }
public Klass getKlass() { public Klass getKlass() {
if (VM.getVM().isCompressedHeadersEnabled()) { if (VM.getVM().isCompressedKlassPointersEnabled()) {
throw new InternalError("unimplemented"); return (Klass)compressedKlass.getValue(getHandle());
} else { } else {
return (Klass)klass.getValue(getHandle()); return (Klass)klass.getValue(getHandle());
} }
@ -150,7 +147,7 @@ public class Oop {
void iterateFields(OopVisitor visitor, boolean doVMFields) { void iterateFields(OopVisitor visitor, boolean doVMFields) {
if (doVMFields) { if (doVMFields) {
visitor.doCInt(mark, true); visitor.doCInt(mark, true);
if (VM.getVM().isCompressedHeadersEnabled()) { if (VM.getVM().isCompressedKlassPointersEnabled()) {
throw new InternalError("unimplemented"); throw new InternalError("unimplemented");
} else { } else {
visitor.doMetadata(klass, true); visitor.doMetadata(klass, true);
@ -210,8 +207,8 @@ public class Oop {
if (handle == null) { if (handle == null) {
return null; return null;
} }
if (VM.getVM().isCompressedHeadersEnabled()) { if (VM.getVM().isCompressedKlassPointersEnabled()) {
throw new InternalError("Unimplemented"); return (Klass)Metadata.instantiateWrapperFor(handle.getCompKlassAddressAt(compressedKlass.getOffset()));
} else { } else {
return (Klass)Metadata.instantiateWrapperFor(handle.getAddressAt(klass.getOffset())); return (Klass)Metadata.instantiateWrapperFor(handle.getAddressAt(klass.getOffset()));
} }

View file

@ -63,12 +63,8 @@ public class java_lang_Class {
/** get Klass* field at offset hc_klass_offset from a java.lang.Class object */ /** get Klass* field at offset hc_klass_offset from a java.lang.Class object */
public static Klass asKlass(Oop aClass) { public static Klass asKlass(Oop aClass) {
if (VM.getVM().isCompressedHeadersEnabled()) {
throw new InternalError("unimplemented");
} else {
return (Klass)Metadata.instantiateWrapperFor(aClass.getHandle().getAddressAt(klassOffset)); return (Klass)Metadata.instantiateWrapperFor(aClass.getHandle().getAddressAt(klassOffset));
} }
}
/** get oop_size field at offset oop_size_offset from a java.lang.Class object */ /** get oop_size field at offset oop_size_offset from a java.lang.Class object */
public static long getOopSize(Oop aClass) { public static long getOopSize(Oop aClass) {

View file

@ -103,6 +103,7 @@ public class VM {
private int logMinObjAlignmentInBytes; private int logMinObjAlignmentInBytes;
private int heapWordSize; private int heapWordSize;
private int heapOopSize; private int heapOopSize;
private int klassPtrSize;
private int oopSize; private int oopSize;
/** This is only present in a non-core build */ /** This is only present in a non-core build */
private CodeCache codeCache; private CodeCache codeCache;
@ -129,7 +130,7 @@ public class VM {
private static CIntegerType boolType; private static CIntegerType boolType;
private Boolean sharingEnabled; private Boolean sharingEnabled;
private Boolean compressedOopsEnabled; private Boolean compressedOopsEnabled;
private Boolean compressedHeadersEnabled; private Boolean compressedKlassPointersEnabled;
// command line flags supplied to VM - see struct Flag in globals.hpp // command line flags supplied to VM - see struct Flag in globals.hpp
public static final class Flag { public static final class Flag {
@ -350,6 +351,12 @@ public class VM {
} else { } else {
heapOopSize = (int)getOopSize(); heapOopSize = (int)getOopSize();
} }
if (isCompressedKlassPointersEnabled()) {
klassPtrSize = (int)getIntSize();
} else {
klassPtrSize = (int)getOopSize(); // same as an oop
}
} }
/** This could be used by a reflective runtime system */ /** This could be used by a reflective runtime system */
@ -374,8 +381,9 @@ public class VM {
((Observer) iter.next()).update(null, null); ((Observer) iter.next()).update(null, null);
} }
debugger.putHeapConst(soleInstance.getHeapOopSize(), Universe.getNarrowOopBase(), debugger.putHeapConst(soleInstance.getHeapOopSize(), soleInstance.getKlassPtrSize(),
Universe.getNarrowOopShift()); Universe.getNarrowOopBase(), Universe.getNarrowOopShift(),
Universe.getNarrowKlassBase(), Universe.getNarrowKlassShift());
} }
/** This is used by the debugging system */ /** This is used by the debugging system */
@ -536,6 +544,10 @@ public class VM {
public int getHeapOopSize() { public int getHeapOopSize() {
return heapOopSize; return heapOopSize;
} }
public int getKlassPtrSize() {
return klassPtrSize;
}
/** Utility routine for getting data structure alignment correct */ /** Utility routine for getting data structure alignment correct */
public long alignUp(long size, long alignment) { public long alignUp(long size, long alignment) {
return (size + alignment - 1) & ~(alignment - 1); return (size + alignment - 1) & ~(alignment - 1);
@ -784,13 +796,13 @@ public class VM {
return compressedOopsEnabled.booleanValue(); return compressedOopsEnabled.booleanValue();
} }
public boolean isCompressedHeadersEnabled() { public boolean isCompressedKlassPointersEnabled() {
if (compressedHeadersEnabled == null) { if (compressedKlassPointersEnabled == null) {
Flag flag = getCommandLineFlag("UseCompressedHeaders"); Flag flag = getCommandLineFlag("UseCompressedKlassPointers");
compressedHeadersEnabled = (flag == null) ? Boolean.FALSE: compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE:
(flag.getBool()? Boolean.TRUE: Boolean.FALSE); (flag.getBool()? Boolean.TRUE: Boolean.FALSE);
} }
return compressedHeadersEnabled.booleanValue(); return compressedKlassPointersEnabled.booleanValue();
} }
public int getObjectAlignmentInBytes() { public int getObjectAlignmentInBytes() {

View file

@ -53,9 +53,8 @@ public class RobustOopDeterminator {
private static void initialize(TypeDataBase db) { private static void initialize(TypeDataBase db) {
Type type = db.lookupType("oopDesc"); Type type = db.lookupType("oopDesc");
if (VM.getVM().isCompressedHeadersEnabled()) { if (VM.getVM().isCompressedKlassPointersEnabled()) {
// klassField = type.getNarrowOopField("_metadata._compressed_klass"); klassField = type.getAddressField("_metadata._compressed_klass");
throw new InternalError("unimplemented");
} else { } else {
klassField = type.getAddressField("_metadata._klass"); klassField = type.getAddressField("_metadata._klass");
} }
@ -70,7 +69,11 @@ public class RobustOopDeterminator {
} }
try { try {
// Try to instantiate the Klass // Try to instantiate the Klass
if (VM.getVM().isCompressedKlassPointersEnabled()) {
Metadata.instantiateWrapperFor(oop.getCompKlassAddressAt(klassField.getOffset()));
} else {
Metadata.instantiateWrapperFor(klassField.getValue(oop)); Metadata.instantiateWrapperFor(klassField.getValue(oop));
}
return true; return true;
} }
catch (AddressException e) { catch (AddressException e) {

View file

@ -114,21 +114,21 @@ $(GENOFFS): $(DTRACE_SRCDIR)/$(GENOFFS)Main.c lib$(GENOFFS).dylib
# $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs. # $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
$(JVMOFFS).h: $(GENOFFS) $(JVMOFFS).h: $(GENOFFS)
$(QUIETLY) DYLD_LIBRARY_PATH=. ./$(GENOFFS) -header > $@.tmp; touch $@; \ $(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -header > $@.tmp; touch $@; \
if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \ if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
then rm -f $@; mv $@.tmp $@; \ then rm -f $@; mv $@.tmp $@; \
else rm -f $@.tmp; \ else rm -f $@.tmp; \
fi fi
$(JVMOFFS)Index.h: $(GENOFFS) $(JVMOFFS)Index.h: $(GENOFFS)
$(QUIETLY) DYLD_LIBRARY_PATH=. ./$(GENOFFS) -index > $@.tmp; touch $@; \ $(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -index > $@.tmp; touch $@; \
if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \ if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
then rm -f $@; mv $@.tmp $@; \ then rm -f $@; mv $@.tmp $@; \
else rm -f $@.tmp; \ else rm -f $@.tmp; \
fi fi
$(JVMOFFS).cpp: $(GENOFFS) $(JVMOFFS).h $(JVMOFFS)Index.h $(JVMOFFS).cpp: $(GENOFFS) $(JVMOFFS).h $(JVMOFFS)Index.h
$(QUIETLY) DYLD_LIBRARY_PATH=. ./$(GENOFFS) -table > $@.tmp; touch $@; \ $(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -table > $@.tmp; touch $@; \
if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \ if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
then rm -f $@; mv $@.tmp $@; \ then rm -f $@; mv $@.tmp $@; \
else rm -f $@.tmp; \ else rm -f $@.tmp; \

View file

@ -206,15 +206,15 @@ CONDITIONALLY_UPDATE_JVMOFFS_TARGET = \
# $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs. # $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
$(JVMOFFS).h: $(GENOFFS) $(JVMOFFS).h: $(GENOFFS)
$(QUIETLY) LD_LIBRARY_PATH=. ./$(GENOFFS) -header > $@.tmp $(QUIETLY) LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ./$(GENOFFS) -header > $@.tmp
$(QUIETLY) $(CONDITIONALLY_UPDATE_JVMOFFS_TARGET) $(QUIETLY) $(CONDITIONALLY_UPDATE_JVMOFFS_TARGET)
$(JVMOFFS)Index.h: $(GENOFFS) $(JVMOFFS)Index.h: $(GENOFFS)
$(QUIETLY) LD_LIBRARY_PATH=. ./$(GENOFFS) -index > $@.tmp $(QUIETLY) LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ./$(GENOFFS) -index > $@.tmp
$(QUIETLY) $(CONDITIONALLY_UPDATE_JVMOFFS_TARGET) $(QUIETLY) $(CONDITIONALLY_UPDATE_JVMOFFS_TARGET)
$(JVMOFFS).cpp: $(GENOFFS) $(JVMOFFS).h $(JVMOFFS)Index.h $(JVMOFFS).cpp: $(GENOFFS) $(JVMOFFS).h $(JVMOFFS)Index.h
$(QUIETLY) LD_LIBRARY_PATH=. ./$(GENOFFS) -table > $@.tmp $(QUIETLY) LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ./$(GENOFFS) -table > $@.tmp
$(QUIETLY) $(CONDITIONALLY_UPDATE_JVMOFFS_TARGET) $(QUIETLY) $(CONDITIONALLY_UPDATE_JVMOFFS_TARGET)
$(JVMOFFS.o): $(JVMOFFS).h $(JVMOFFS).cpp $(JVMOFFS.o): $(JVMOFFS).h $(JVMOFFS).cpp

View file

@ -1641,6 +1641,21 @@ void MacroAssembler::set_narrow_oop(jobject obj, Register d) {
} }
void MacroAssembler::set_narrow_klass(Klass* k, Register d) {
assert(oop_recorder() != NULL, "this assembler needs an OopRecorder");
int klass_index = oop_recorder()->find_index(k);
RelocationHolder rspec = metadata_Relocation::spec(klass_index);
narrowOop encoded_k = oopDesc::encode_klass(k);
assert_not_delayed();
// Relocation with special format (see relocInfo_sparc.hpp).
relocate(rspec, 1);
// Assembler::sethi(encoded_k, d);
emit_long( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(encoded_k) );
// Don't add relocation for 'add'. Do patching during 'sethi' processing.
add(d, low10(encoded_k), d);
}
void MacroAssembler::align(int modulus) { void MacroAssembler::align(int modulus) {
while (offset() % modulus != 0) nop(); while (offset() % modulus != 0) nop();
@ -4660,7 +4675,7 @@ void MacroAssembler::load_klass(Register src_oop, Register klass) {
// if this changes, change that. // if this changes, change that.
if (UseCompressedKlassPointers) { if (UseCompressedKlassPointers) {
lduw(src_oop, oopDesc::klass_offset_in_bytes(), klass); lduw(src_oop, oopDesc::klass_offset_in_bytes(), klass);
decode_heap_oop_not_null(klass); decode_klass_not_null(klass);
} else { } else {
ld_ptr(src_oop, oopDesc::klass_offset_in_bytes(), klass); ld_ptr(src_oop, oopDesc::klass_offset_in_bytes(), klass);
} }
@ -4669,7 +4684,7 @@ void MacroAssembler::load_klass(Register src_oop, Register klass) {
void MacroAssembler::store_klass(Register klass, Register dst_oop) { void MacroAssembler::store_klass(Register klass, Register dst_oop) {
if (UseCompressedKlassPointers) { if (UseCompressedKlassPointers) {
assert(dst_oop != klass, "not enough registers"); assert(dst_oop != klass, "not enough registers");
encode_heap_oop_not_null(klass); encode_klass_not_null(klass);
st(klass, dst_oop, oopDesc::klass_offset_in_bytes()); st(klass, dst_oop, oopDesc::klass_offset_in_bytes());
} else { } else {
st_ptr(klass, dst_oop, oopDesc::klass_offset_in_bytes()); st_ptr(klass, dst_oop, oopDesc::klass_offset_in_bytes());
@ -4829,17 +4844,58 @@ void MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) {
// pd_code_size_limit. // pd_code_size_limit.
// Also do not verify_oop as this is called by verify_oop. // Also do not verify_oop as this is called by verify_oop.
assert (UseCompressedOops, "must be compressed"); assert (UseCompressedOops, "must be compressed");
assert (Universe::heap() != NULL, "java heap should be initialized");
assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
sllx(src, LogMinObjAlignmentInBytes, dst); sllx(src, LogMinObjAlignmentInBytes, dst);
if (Universe::narrow_oop_base() != NULL) if (Universe::narrow_oop_base() != NULL)
add(dst, G6_heapbase, dst); add(dst, G6_heapbase, dst);
} }
void MacroAssembler::encode_klass_not_null(Register r) {
assert(Metaspace::is_initialized(), "metaspace should be initialized");
assert (UseCompressedKlassPointers, "must be compressed");
assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
if (Universe::narrow_klass_base() != NULL)
sub(r, G6_heapbase, r);
srlx(r, LogKlassAlignmentInBytes, r);
}
void MacroAssembler::encode_klass_not_null(Register src, Register dst) {
assert(Metaspace::is_initialized(), "metaspace should be initialized");
assert (UseCompressedKlassPointers, "must be compressed");
assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
if (Universe::narrow_klass_base() == NULL) {
srlx(src, LogKlassAlignmentInBytes, dst);
} else {
sub(src, G6_heapbase, dst);
srlx(dst, LogKlassAlignmentInBytes, dst);
}
}
void MacroAssembler::decode_klass_not_null(Register r) {
assert(Metaspace::is_initialized(), "metaspace should be initialized");
// Do not add assert code to this unless you change vtableStubs_sparc.cpp
// pd_code_size_limit.
assert (UseCompressedKlassPointers, "must be compressed");
assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
sllx(r, LogKlassAlignmentInBytes, r);
if (Universe::narrow_klass_base() != NULL)
add(r, G6_heapbase, r);
}
void MacroAssembler::decode_klass_not_null(Register src, Register dst) {
assert(Metaspace::is_initialized(), "metaspace should be initialized");
// Do not add assert code to this unless you change vtableStubs_sparc.cpp
// pd_code_size_limit.
assert (UseCompressedKlassPointers, "must be compressed");
assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
sllx(src, LogKlassAlignmentInBytes, dst);
if (Universe::narrow_klass_base() != NULL)
add(dst, G6_heapbase, dst);
}
void MacroAssembler::reinit_heapbase() { void MacroAssembler::reinit_heapbase() {
if (UseCompressedOops) { if (UseCompressedOops || UseCompressedKlassPointers) {
// call indirectly to solve generation ordering problem AddressLiteral base(Universe::narrow_ptrs_base_addr());
AddressLiteral base(Universe::narrow_oop_base_addr());
load_ptr_contents(base, G6_heapbase); load_ptr_contents(base, G6_heapbase);
} }
} }

View file

@ -2280,6 +2280,11 @@ public:
void encode_heap_oop_not_null(Register src, Register dst); void encode_heap_oop_not_null(Register src, Register dst);
void decode_heap_oop_not_null(Register src, Register dst); void decode_heap_oop_not_null(Register src, Register dst);
void encode_klass_not_null(Register r);
void decode_klass_not_null(Register r);
void encode_klass_not_null(Register src, Register dst);
void decode_klass_not_null(Register src, Register dst);
// Support for managing the JavaThread pointer (i.e.; the reference to // Support for managing the JavaThread pointer (i.e.; the reference to
// thread-local information). // thread-local information).
void get_thread(); // load G2_thread void get_thread(); // load G2_thread
@ -2409,6 +2414,7 @@ public:
inline void set_metadata (const AddressLiteral& obj_addr, Register d); // same as load_address inline void set_metadata (const AddressLiteral& obj_addr, Register d); // same as load_address
void set_narrow_oop( jobject obj, Register d ); void set_narrow_oop( jobject obj, Register d );
void set_narrow_klass( Klass* k, Register d );
// nop padding // nop padding
void align(int modulus); void align(int modulus);

View file

@ -105,6 +105,11 @@ bool LIR_Assembler::is_single_instruction(LIR_Op* op) {
if (src->is_address() && !src->is_stack() && (src->type() == T_OBJECT || src->type() == T_ARRAY)) return false; if (src->is_address() && !src->is_stack() && (src->type() == T_OBJECT || src->type() == T_ARRAY)) return false;
} }
if (UseCompressedKlassPointers) {
if (src->is_address() && !src->is_stack() && src->type() == T_ADDRESS &&
src->as_address_ptr()->disp() == oopDesc::klass_offset_in_bytes()) return false;
}
if (dst->is_register()) { if (dst->is_register()) {
if (src->is_address() && Assembler::is_simm13(src->as_address_ptr()->disp())) { if (src->is_address() && Assembler::is_simm13(src->as_address_ptr()->disp())) {
return !PatchALot; return !PatchALot;
@ -969,8 +974,18 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ
#endif #endif
} }
break; break;
case T_METADATA: case T_METADATA: __ ld_ptr(base, offset, to_reg->as_register()); break;
case T_ADDRESS: __ ld_ptr(base, offset, to_reg->as_register()); break; case T_ADDRESS:
#ifdef _LP64
if (offset == oopDesc::klass_offset_in_bytes() && UseCompressedKlassPointers) {
__ lduw(base, offset, to_reg->as_register());
__ decode_klass_not_null(to_reg->as_register());
} else
#endif
{
__ ld_ptr(base, offset, to_reg->as_register());
}
break;
case T_ARRAY : // fall through case T_ARRAY : // fall through
case T_OBJECT: case T_OBJECT:
{ {
@ -2344,7 +2359,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
if (UseCompressedKlassPointers) { if (UseCompressedKlassPointers) {
// tmp holds the default type. It currently comes uncompressed after the // tmp holds the default type. It currently comes uncompressed after the
// load of a constant, so encode it. // load of a constant, so encode it.
__ encode_heap_oop(tmp); __ encode_klass_not_null(tmp);
// load the raw value of the dst klass, since we will be comparing // load the raw value of the dst klass, since we will be comparing
// uncompressed values directly. // uncompressed values directly.
__ lduw(dst, oopDesc::klass_offset_in_bytes(), tmp2); __ lduw(dst, oopDesc::klass_offset_in_bytes(), tmp2);

View file

@ -189,7 +189,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
if (UseCompressedKlassPointers) { if (UseCompressedKlassPointers) {
// Save klass // Save klass
mov(klass, t1); mov(klass, t1);
encode_heap_oop_not_null(t1); encode_klass_not_null(t1);
stw(t1, obj, oopDesc::klass_offset_in_bytes()); stw(t1, obj, oopDesc::klass_offset_in_bytes());
} else { } else {
st_ptr(klass, obj, oopDesc::klass_offset_in_bytes()); st_ptr(klass, obj, oopDesc::klass_offset_in_bytes());

View file

@ -208,8 +208,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
Register O1_scratch = O1; Register O1_scratch = O1;
Register O4_param_size = O4; // size of parameters Register O4_param_size = O4; // size of parameters
address code_start = __ pc();
// here's where control starts out: // here's where control starts out:
__ align(CodeEntryAlignment); __ align(CodeEntryAlignment);
address entry_point = __ pc(); address entry_point = __ pc();
@ -252,22 +250,9 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
// O4_first_arg_addr is live! // O4_first_arg_addr is live!
if (TraceMethodHandles) { if (TraceMethodHandles) {
const char* name = vmIntrinsics::name_at(iid);
if (*name == '_') name += 1;
const size_t len = strlen(name) + 50;
char* qname = NEW_C_HEAP_ARRAY(char, len, mtInternal);
const char* suffix = "";
if (vmIntrinsics::method_for(iid) == NULL ||
!vmIntrinsics::method_for(iid)->access_flags().is_public()) {
if (is_signature_polymorphic_static(iid))
suffix = "/static";
else
suffix = "/private";
}
jio_snprintf(qname, len, "MethodHandle::interpreter_entry::%s%s", name, suffix);
if (O0_mh != noreg) if (O0_mh != noreg)
__ mov(O0_mh, G3_method_handle); // make stub happy __ mov(O0_mh, G3_method_handle); // make stub happy
trace_method_handle(_masm, qname); trace_method_handle_interpreter_entry(_masm, iid);
} }
if (iid == vmIntrinsics::_invokeBasic) { if (iid == vmIntrinsics::_invokeBasic) {
@ -287,14 +272,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
generate_method_handle_dispatch(_masm, iid, O0_recv, G5_member, not_for_compiler_entry); generate_method_handle_dispatch(_masm, iid, O0_recv, G5_member, not_for_compiler_entry);
} }
if (PrintMethodHandleStubs) {
address code_end = __ pc();
tty->print_cr("--------");
tty->print_cr("method handle interpreter entry for %s", vmIntrinsics::name_at(iid));
Disassembler::decode(code_start, code_end);
tty->cr();
}
return entry_point; return entry_point;
} }

View file

@ -58,5 +58,3 @@ public:
Register recv, Register method_temp, Register recv, Register method_temp,
Register temp2, Register temp3, Register temp2, Register temp3,
bool for_compiler_entry); bool for_compiler_entry);
static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;

View file

@ -97,8 +97,8 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
jint inst2; jint inst2;
guarantee(Assembler::inv_op2(inst)==Assembler::sethi_op2, "must be sethi"); guarantee(Assembler::inv_op2(inst)==Assembler::sethi_op2, "must be sethi");
if (format() != 0) { if (format() != 0) {
assert(type() == relocInfo::oop_type, "only narrow oops case"); assert(type() == relocInfo::oop_type || type() == relocInfo::metadata_type, "only narrow oops or klasses case");
jint np = oopDesc::encode_heap_oop((oop)x); jint np = type() == relocInfo::oop_type ? oopDesc::encode_heap_oop((oop)x) : oopDesc::encode_klass((Klass*)x);
inst &= ~Assembler::hi22(-1); inst &= ~Assembler::hi22(-1);
inst |= Assembler::hi22((intptr_t)np); inst |= Assembler::hi22((intptr_t)np);
if (verify_only) { if (verify_only) {

View file

@ -557,9 +557,9 @@ int MachCallDynamicJavaNode::ret_addr_offset() {
int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
int klass_load_size; int klass_load_size;
if (UseCompressedOops && UseCompressedKlassPointers) { if (UseCompressedKlassPointers) {
assert(Universe::heap() != NULL, "java heap should be initialized"); assert(Universe::heap() != NULL, "java heap should be initialized");
if (Universe::narrow_oop_base() == NULL) if (Universe::narrow_klass_base() == NULL)
klass_load_size = 2*BytesPerInstWord; // see MacroAssembler::load_klass() klass_load_size = 2*BytesPerInstWord; // see MacroAssembler::load_klass()
else else
klass_load_size = 3*BytesPerInstWord; klass_load_size = 3*BytesPerInstWord;
@ -1707,11 +1707,11 @@ uint reloc_java_to_interp() {
void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
st->print_cr("\nUEP:"); st->print_cr("\nUEP:");
#ifdef _LP64 #ifdef _LP64
if (UseCompressedOops) { if (UseCompressedKlassPointers) {
assert(Universe::heap() != NULL, "java heap should be initialized"); assert(Universe::heap() != NULL, "java heap should be initialized");
st->print_cr("\tLDUW [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check - compressed klass"); 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("\tSLL R_G5,3,R_G5");
if (Universe::narrow_oop_base() != NULL) if (Universe::narrow_klass_base() != NULL)
st->print_cr("\tADD R_G5,R_G6_heap_base,R_G5"); st->print_cr("\tADD R_G5,R_G6_heap_base,R_G5");
} else { } else {
st->print_cr("\tLDX [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check"); st->print_cr("\tLDX [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check");
@ -1942,6 +1942,12 @@ bool Matcher::narrow_oop_use_complex_address() {
return false; return false;
} }
bool Matcher::narrow_klass_use_complex_address() {
NOT_LP64(ShouldNotCallThis());
assert(UseCompressedKlassPointers, "only for compressed klass code");
return false;
}
// Is it better to copy float constants, or load them directly from memory? // Is it better to copy float constants, or load them directly from memory?
// Intel can load a float constant from a direct address, requiring no // Intel can load a float constant from a direct address, requiring no
// extra registers. Most RISCs will have to materialize an address into a // extra registers. Most RISCs will have to materialize an address into a
@ -2602,9 +2608,9 @@ encode %{
int off = __ offset(); int off = __ offset();
__ load_klass(O0, G3_scratch); __ load_klass(O0, G3_scratch);
int klass_load_size; int klass_load_size;
if (UseCompressedOops && UseCompressedKlassPointers) { if (UseCompressedKlassPointers) {
assert(Universe::heap() != NULL, "java heap should be initialized"); assert(Universe::heap() != NULL, "java heap should be initialized");
if (Universe::narrow_oop_base() == NULL) if (Universe::narrow_klass_base() == NULL)
klass_load_size = 2*BytesPerInstWord; klass_load_size = 2*BytesPerInstWord;
else else
klass_load_size = 3*BytesPerInstWord; klass_load_size = 3*BytesPerInstWord;
@ -3610,6 +3616,15 @@ operand immN()
interface(CONST_INTER); interface(CONST_INTER);
%} %}
operand immNKlass()
%{
match(ConNKlass);
op_cost(10);
format %{ %}
interface(CONST_INTER);
%}
// NULL Pointer Immediate // NULL Pointer Immediate
operand immN0() operand immN0()
%{ %{
@ -5870,8 +5885,8 @@ instruct loadI2L_immI(iRegL dst, memory mem, immI mask, iRegL tmp) %{
%} %}
// Load Unsigned Integer into a Long Register // Load Unsigned Integer into a Long Register
instruct loadUI2L(iRegL dst, memory mem) %{ instruct loadUI2L(iRegL dst, memory mem, immL_32bits mask) %{
match(Set dst (LoadUI2L mem)); match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
ins_cost(MEMORY_REF_COST); ins_cost(MEMORY_REF_COST);
size(4); size(4);
@ -6159,6 +6174,17 @@ instruct loadConN(iRegN dst, immN src) %{
ins_pipe(ialu_hi_lo_reg); ins_pipe(ialu_hi_lo_reg);
%} %}
instruct loadConNKlass(iRegN dst, immNKlass src) %{
match(Set dst src);
ins_cost(DEFAULT_COST * 3/2);
format %{ "SET $src,$dst\t! compressed klass ptr" %}
ins_encode %{
Register dst = $dst$$Register;
__ set_narrow_klass((Klass*)$src$$constant, dst);
%}
ins_pipe(ialu_hi_lo_reg);
%}
// Materialize long value (predicated by immL_cheap). // Materialize long value (predicated by immL_cheap).
instruct loadConL_set64(iRegL dst, immL_cheap con, o7RegL tmp) %{ instruct loadConL_set64(iRegL dst, immL_cheap con, o7RegL tmp) %{
match(Set dst con); match(Set dst con);
@ -6475,6 +6501,25 @@ instruct storeN(memory dst, iRegN src) %{
ins_pipe(istore_mem_spORreg); ins_pipe(istore_mem_spORreg);
%} %}
instruct storeNKlass(memory dst, iRegN src) %{
match(Set dst (StoreNKlass dst src));
ins_cost(MEMORY_REF_COST);
size(4);
format %{ "STW $src,$dst\t! compressed klass 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) %{ instruct storeN0(memory dst, immN0 src) %{
match(Set dst (StoreN dst src)); match(Set dst (StoreN dst src));
ins_cost(MEMORY_REF_COST); ins_cost(MEMORY_REF_COST);
@ -6582,6 +6627,23 @@ instruct decodeHeapOop_not_null(iRegP dst, iRegN src) %{
ins_pipe(ialu_reg); ins_pipe(ialu_reg);
%} %}
instruct encodeKlass_not_null(iRegN dst, iRegP src) %{
match(Set dst (EncodePKlass src));
format %{ "encode_klass_not_null $src, $dst" %}
ins_encode %{
__ encode_klass_not_null($src$$Register, $dst$$Register);
%}
ins_pipe(ialu_reg);
%}
instruct decodeKlass_not_null(iRegP dst, iRegN src) %{
match(Set dst (DecodeNKlass src));
format %{ "decode_klass_not_null $src, $dst" %}
ins_encode %{
__ decode_klass_not_null($src$$Register, $dst$$Register);
%}
ins_pipe(ialu_reg);
%}
//----------MemBar Instructions----------------------------------------------- //----------MemBar Instructions-----------------------------------------------
// Memory barrier flavors // Memory barrier flavors

View file

@ -117,6 +117,7 @@ void VM_Version::initialize() {
// 32-bit oops don't make sense for the 64-bit VM on sparc // 32-bit oops don't make sense for the 64-bit VM on sparc
// since the 32-bit VM has the same registers and smaller objects. // since the 32-bit VM has the same registers and smaller objects.
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
#endif // _LP64 #endif // _LP64
#ifdef COMPILER2 #ifdef COMPILER2
// Indirect branch is the same cost as direct // Indirect branch is the same cost as direct

View file

@ -220,13 +220,13 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
const int basic = 5*BytesPerInstWord + const int basic = 5*BytesPerInstWord +
// shift;add for load_klass (only shift with zero heap based) // shift;add for load_klass (only shift with zero heap based)
(UseCompressedKlassPointers ? (UseCompressedKlassPointers ?
((Universe::narrow_oop_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0); ((Universe::narrow_klass_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0);
return basic + slop; return basic + slop;
} else { } else {
const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord + const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord +
// shift;add for load_klass (only shift with zero heap based) // shift;add for load_klass (only shift with zero heap based)
(UseCompressedKlassPointers ? (UseCompressedKlassPointers ?
((Universe::narrow_oop_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0); ((Universe::narrow_klass_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0);
return (basic + slop); return (basic + slop);
} }
} }

View file

@ -6916,7 +6916,7 @@ void MacroAssembler::call_VM_base(Register oop_result,
#ifdef ASSERT #ifdef ASSERT
// TraceBytecodes does not use r12 but saves it over the call, so don't verify // TraceBytecodes does not use r12 but saves it over the call, so don't verify
// r12 is the heapbase. // r12 is the heapbase.
LP64_ONLY(if (UseCompressedOops && !TraceBytecodes) verify_heapbase("call_VM_base");) LP64_ONLY(if ((UseCompressedOops || UseCompressedKlassPointers) && !TraceBytecodes) verify_heapbase("call_VM_base: heap base corrupted?");)
#endif // ASSERT #endif // ASSERT
assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result"); assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result");
@ -10016,7 +10016,7 @@ void MacroAssembler::load_klass(Register dst, Register src) {
#ifdef _LP64 #ifdef _LP64
if (UseCompressedKlassPointers) { if (UseCompressedKlassPointers) {
movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); movl(dst, Address(src, oopDesc::klass_offset_in_bytes()));
decode_heap_oop_not_null(dst); decode_klass_not_null(dst);
} else } else
#endif #endif
movptr(dst, Address(src, oopDesc::klass_offset_in_bytes())); movptr(dst, Address(src, oopDesc::klass_offset_in_bytes()));
@ -10027,15 +10027,10 @@ void MacroAssembler::load_prototype_header(Register dst, Register src) {
if (UseCompressedKlassPointers) { if (UseCompressedKlassPointers) {
assert (Universe::heap() != NULL, "java heap should be initialized"); assert (Universe::heap() != NULL, "java heap should be initialized");
movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); movl(dst, Address(src, oopDesc::klass_offset_in_bytes()));
if (Universe::narrow_oop_shift() != 0) { if (Universe::narrow_klass_shift() != 0) {
assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
if (LogMinObjAlignmentInBytes == Address::times_8) { assert(LogKlassAlignmentInBytes == Address::times_8, "klass not aligned on 64bits?");
movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset())); movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset()));
} else {
// OK to use shift since we don't need to preserve flags.
shlq(dst, LogMinObjAlignmentInBytes);
movq(dst, Address(r12_heapbase, dst, Address::times_1, Klass::prototype_header_offset()));
}
} else { } else {
movq(dst, Address(dst, Klass::prototype_header_offset())); movq(dst, Address(dst, Klass::prototype_header_offset()));
} }
@ -10050,7 +10045,7 @@ void MacroAssembler::load_prototype_header(Register dst, Register src) {
void MacroAssembler::store_klass(Register dst, Register src) { void MacroAssembler::store_klass(Register dst, Register src) {
#ifdef _LP64 #ifdef _LP64
if (UseCompressedKlassPointers) { if (UseCompressedKlassPointers) {
encode_heap_oop_not_null(src); encode_klass_not_null(src);
movl(Address(dst, oopDesc::klass_offset_in_bytes()), src); movl(Address(dst, oopDesc::klass_offset_in_bytes()), src);
} else } else
#endif #endif
@ -10132,12 +10127,12 @@ void MacroAssembler::store_klass_gap(Register dst, Register src) {
#ifdef ASSERT #ifdef ASSERT
void MacroAssembler::verify_heapbase(const char* msg) { void MacroAssembler::verify_heapbase(const char* msg) {
assert (UseCompressedOops, "should be compressed"); assert (UseCompressedOops || UseCompressedKlassPointers, "should be compressed");
assert (Universe::heap() != NULL, "java heap should be initialized"); assert (Universe::heap() != NULL, "java heap should be initialized");
if (CheckCompressedOops) { if (CheckCompressedOops) {
Label ok; Label ok;
push(rscratch1); // cmpptr trashes rscratch1 push(rscratch1); // cmpptr trashes rscratch1
cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); cmpptr(r12_heapbase, ExternalAddress((address)Universe::narrow_ptrs_base_addr()));
jcc(Assembler::equal, ok); jcc(Assembler::equal, ok);
STOP(msg); STOP(msg);
bind(ok); bind(ok);
@ -10275,6 +10270,74 @@ void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) {
} }
} }
void MacroAssembler::encode_klass_not_null(Register r) {
assert(Metaspace::is_initialized(), "metaspace should be initialized");
#ifdef ASSERT
verify_heapbase("MacroAssembler::encode_klass_not_null: heap base corrupted?");
#endif
if (Universe::narrow_klass_base() != NULL) {
subq(r, r12_heapbase);
}
if (Universe::narrow_klass_shift() != 0) {
assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
shrq(r, LogKlassAlignmentInBytes);
}
}
void MacroAssembler::encode_klass_not_null(Register dst, Register src) {
assert(Metaspace::is_initialized(), "metaspace should be initialized");
#ifdef ASSERT
verify_heapbase("MacroAssembler::encode_klass_not_null2: heap base corrupted?");
#endif
if (dst != src) {
movq(dst, src);
}
if (Universe::narrow_klass_base() != NULL) {
subq(dst, r12_heapbase);
}
if (Universe::narrow_klass_shift() != 0) {
assert (LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
shrq(dst, LogKlassAlignmentInBytes);
}
}
void MacroAssembler::decode_klass_not_null(Register r) {
assert(Metaspace::is_initialized(), "metaspace should be initialized");
// Note: it will change flags
assert (UseCompressedKlassPointers, "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.
// Also do not verify_oop as this is called by verify_oop.
if (Universe::narrow_klass_shift() != 0) {
assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
shlq(r, LogKlassAlignmentInBytes);
if (Universe::narrow_klass_base() != NULL) {
addq(r, r12_heapbase);
}
} else {
assert (Universe::narrow_klass_base() == NULL, "sanity");
}
}
void MacroAssembler::decode_klass_not_null(Register dst, Register src) {
assert(Metaspace::is_initialized(), "metaspace should be initialized");
// Note: it will change flags
assert (UseCompressedKlassPointers, "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.
// Also do not verify_oop as this is called by verify_oop.
if (Universe::narrow_klass_shift() != 0) {
assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong");
assert(LogKlassAlignmentInBytes == Address::times_8, "klass not aligned on 64bits?");
leaq(dst, Address(r12_heapbase, src, Address::times_8, 0));
} else {
assert (Universe::narrow_klass_base() == NULL, "sanity");
if (dst != src) {
movq(dst, src);
}
}
}
void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { void MacroAssembler::set_narrow_oop(Register dst, jobject obj) {
assert (UseCompressedOops, "should only be used for compressed headers"); assert (UseCompressedOops, "should only be used for compressed headers");
assert (Universe::heap() != NULL, "java heap should be initialized"); assert (Universe::heap() != NULL, "java heap should be initialized");
@ -10293,6 +10356,22 @@ void MacroAssembler::set_narrow_oop(Address dst, jobject obj) {
mov_narrow_oop(dst, oop_index, rspec); mov_narrow_oop(dst, oop_index, rspec);
} }
void MacroAssembler::set_narrow_klass(Register dst, Klass* k) {
assert (UseCompressedKlassPointers, "should only be used for compressed headers");
assert (oop_recorder() != NULL, "this assembler needs an OopRecorder");
int klass_index = oop_recorder()->find_index(k);
RelocationHolder rspec = metadata_Relocation::spec(klass_index);
mov_narrow_oop(dst, oopDesc::encode_klass(k), rspec);
}
void MacroAssembler::set_narrow_klass(Address dst, Klass* k) {
assert (UseCompressedKlassPointers, "should only be used for compressed headers");
assert (oop_recorder() != NULL, "this assembler needs an OopRecorder");
int klass_index = oop_recorder()->find_index(k);
RelocationHolder rspec = metadata_Relocation::spec(klass_index);
mov_narrow_oop(dst, oopDesc::encode_klass(k), rspec);
}
void MacroAssembler::cmp_narrow_oop(Register dst, jobject obj) { void MacroAssembler::cmp_narrow_oop(Register dst, jobject obj) {
assert (UseCompressedOops, "should only be used for compressed headers"); assert (UseCompressedOops, "should only be used for compressed headers");
assert (Universe::heap() != NULL, "java heap should be initialized"); assert (Universe::heap() != NULL, "java heap should be initialized");
@ -10311,9 +10390,25 @@ void MacroAssembler::cmp_narrow_oop(Address dst, jobject obj) {
Assembler::cmp_narrow_oop(dst, oop_index, rspec); Assembler::cmp_narrow_oop(dst, oop_index, rspec);
} }
void MacroAssembler::cmp_narrow_klass(Register dst, Klass* k) {
assert (UseCompressedKlassPointers, "should only be used for compressed headers");
assert (oop_recorder() != NULL, "this assembler needs an OopRecorder");
int klass_index = oop_recorder()->find_index(k);
RelocationHolder rspec = metadata_Relocation::spec(klass_index);
Assembler::cmp_narrow_oop(dst, oopDesc::encode_klass(k), rspec);
}
void MacroAssembler::cmp_narrow_klass(Address dst, Klass* k) {
assert (UseCompressedKlassPointers, "should only be used for compressed headers");
assert (oop_recorder() != NULL, "this assembler needs an OopRecorder");
int klass_index = oop_recorder()->find_index(k);
RelocationHolder rspec = metadata_Relocation::spec(klass_index);
Assembler::cmp_narrow_oop(dst, oopDesc::encode_klass(k), rspec);
}
void MacroAssembler::reinit_heapbase() { void MacroAssembler::reinit_heapbase() {
if (UseCompressedOops) { if (UseCompressedOops || UseCompressedKlassPointers) {
movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr())); movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_ptrs_base_addr()));
} }
} }
#endif // _LP64 #endif // _LP64

View file

@ -2083,6 +2083,15 @@ class MacroAssembler: public Assembler {
void cmp_narrow_oop(Register dst, jobject obj); void cmp_narrow_oop(Register dst, jobject obj);
void cmp_narrow_oop(Address dst, jobject obj); void cmp_narrow_oop(Address dst, jobject obj);
void encode_klass_not_null(Register r);
void decode_klass_not_null(Register r);
void encode_klass_not_null(Register dst, Register src);
void decode_klass_not_null(Register dst, Register src);
void set_narrow_klass(Register dst, Klass* k);
void set_narrow_klass(Address dst, Klass* k);
void cmp_narrow_klass(Register dst, Klass* k);
void cmp_narrow_klass(Address dst, Klass* k);
// if heap base register is used - reinit it with the correct value // if heap base register is used - reinit it with the correct value
void reinit_heapbase(); void reinit_heapbase();

View file

@ -148,7 +148,7 @@
static int adjust_reg_range(int range) { static int adjust_reg_range(int range) {
// Reduce the number of available regs (to free r12) in case of compressed oops // Reduce the number of available regs (to free r12) in case of compressed oops
if (UseCompressedOops) return range - 1; if (UseCompressedOops || UseCompressedKlassPointers) return range - 1;
return range; return range;
} }

View file

@ -340,7 +340,7 @@ int LIR_Assembler::check_icache() {
Register receiver = FrameMap::receiver_opr->as_register(); Register receiver = FrameMap::receiver_opr->as_register();
Register ic_klass = IC_Klass; Register ic_klass = IC_Klass;
const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9); const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9);
const bool do_post_padding = VerifyOops || UseCompressedOops; const bool do_post_padding = VerifyOops || UseCompressedKlassPointers;
if (!do_post_padding) { if (!do_post_padding) {
// insert some nops so that the verified entry point is aligned on CodeEntryAlignment // insert some nops so that the verified entry point is aligned on CodeEntryAlignment
while ((__ offset() + ic_cmp_size) % CodeEntryAlignment != 0) { while ((__ offset() + ic_cmp_size) % CodeEntryAlignment != 0) {
@ -1262,7 +1262,11 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch
break; break;
case T_ADDRESS: case T_ADDRESS:
if (UseCompressedKlassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) {
__ movl(dest->as_register(), from_addr);
} else {
__ movptr(dest->as_register(), from_addr); __ movptr(dest->as_register(), from_addr);
}
break; break;
case T_INT: case T_INT:
__ movl(dest->as_register(), from_addr); __ movl(dest->as_register(), from_addr);
@ -1364,6 +1368,12 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch
} }
#endif #endif
__ verify_oop(dest->as_register()); __ verify_oop(dest->as_register());
} else if (type == T_ADDRESS && addr->disp() == oopDesc::klass_offset_in_bytes()) {
#ifdef _LP64
if (UseCompressedKlassPointers) {
__ decode_klass_not_null(dest->as_register());
}
#endif
} }
} }
@ -1705,7 +1715,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
} else if (obj == klass_RInfo) { } else if (obj == klass_RInfo) {
klass_RInfo = dst; klass_RInfo = dst;
} }
if (k->is_loaded() && !UseCompressedOops) { if (k->is_loaded() && !UseCompressedKlassPointers) {
select_different_registers(obj, dst, k_RInfo, klass_RInfo); select_different_registers(obj, dst, k_RInfo, klass_RInfo);
} else { } else {
Rtmp1 = op->tmp3()->as_register(); Rtmp1 = op->tmp3()->as_register();
@ -3446,7 +3456,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
__ mov_metadata(tmp, default_type->constant_encoding()); __ mov_metadata(tmp, default_type->constant_encoding());
#ifdef _LP64 #ifdef _LP64
if (UseCompressedKlassPointers) { if (UseCompressedKlassPointers) {
__ encode_heap_oop(tmp); __ encode_klass_not_null(tmp);
} }
#endif #endif

View file

@ -1166,7 +1166,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) {
} }
LIR_Opr reg = rlock_result(x); LIR_Opr reg = rlock_result(x);
LIR_Opr tmp3 = LIR_OprFact::illegalOpr; LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
if (!x->klass()->is_loaded() || UseCompressedOops) { if (!x->klass()->is_loaded() || UseCompressedKlassPointers) {
tmp3 = new_register(objectType); tmp3 = new_register(objectType);
} }
__ checkcast(reg, obj.result(), x->klass(), __ checkcast(reg, obj.result(), x->klass(),
@ -1188,7 +1188,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) {
} }
obj.load_item(); obj.load_item();
LIR_Opr tmp3 = LIR_OprFact::illegalOpr; LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
if (!x->klass()->is_loaded() || UseCompressedOops) { if (!x->klass()->is_loaded() || UseCompressedKlassPointers) {
tmp3 = new_register(objectType); tmp3 = new_register(objectType);
} }
__ instanceof(reg, obj.result(), x->klass(), __ instanceof(reg, obj.result(), x->klass(),

View file

@ -159,7 +159,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
#ifdef _LP64 #ifdef _LP64
if (UseCompressedKlassPointers) { // Take care not to kill klass if (UseCompressedKlassPointers) { // Take care not to kill klass
movptr(t1, klass); movptr(t1, klass);
encode_heap_oop_not_null(t1); encode_klass_not_null(t1);
movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1); movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1);
} else } else
#endif #endif

View file

@ -209,8 +209,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
Register rcx_mh = rcx; // MH receiver; dies quickly and is recycled Register rcx_mh = rcx; // MH receiver; dies quickly and is recycled
Register rbx_method = rbx; // eventual target of this invocation Register rbx_method = rbx; // eventual target of this invocation
address code_start = __ pc();
// here's where control starts out: // here's where control starts out:
__ align(CodeEntryAlignment); __ align(CodeEntryAlignment);
address entry_point = __ pc(); address entry_point = __ pc();
@ -251,23 +249,7 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
// rdx_first_arg_addr is live! // rdx_first_arg_addr is live!
if (TraceMethodHandles) { trace_method_handle_interpreter_entry(_masm, iid);
const char* name = vmIntrinsics::name_at(iid);
if (*name == '_') name += 1;
const size_t len = strlen(name) + 50;
char* qname = NEW_C_HEAP_ARRAY(char, len, mtInternal);
const char* suffix = "";
if (vmIntrinsics::method_for(iid) == NULL ||
!vmIntrinsics::method_for(iid)->access_flags().is_public()) {
if (is_signature_polymorphic_static(iid))
suffix = "/static";
else
suffix = "/private";
}
jio_snprintf(qname, len, "MethodHandle::interpreter_entry::%s%s", name, suffix);
// note: stub look for mh in rcx
trace_method_handle(_masm, qname);
}
if (iid == vmIntrinsics::_invokeBasic) { if (iid == vmIntrinsics::_invokeBasic) {
generate_method_handle_dispatch(_masm, iid, rcx_mh, noreg, not_for_compiler_entry); generate_method_handle_dispatch(_masm, iid, rcx_mh, noreg, not_for_compiler_entry);
@ -287,14 +269,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
generate_method_handle_dispatch(_masm, iid, rcx_recv, rbx_member, not_for_compiler_entry); generate_method_handle_dispatch(_masm, iid, rcx_recv, rbx_member, not_for_compiler_entry);
} }
if (PrintMethodHandleStubs) {
address code_end = __ pc();
tty->print_cr("--------");
tty->print_cr("method handle interpreter entry for %s", vmIntrinsics::name_at(iid));
Disassembler::decode(code_start, code_end);
tty->cr();
}
return entry_point; return entry_point;
} }

View file

@ -55,8 +55,6 @@ public:
Register temp2, Register temp2,
bool for_compiler_entry); bool for_compiler_entry);
static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
static Register saved_last_sp_register() { static Register saved_last_sp_register() {
// Should be in sharedRuntime, not here. // Should be in sharedRuntime, not here.
return LP64_ONLY(r13) NOT_LP64(rsi); return LP64_ONLY(r13) NOT_LP64(rsi);

View file

@ -212,11 +212,11 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
if (is_vtable_stub) { if (is_vtable_stub) {
// Vtable stub size // 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 (UseCompressedKlassPointers ? 16 : 0); // 1 leaq can be 3 bytes + 1 long
} else { } else {
// Itable stub size // Itable stub size
return (DebugVtables ? 512 : 74) + (CountCompiledCalls ? 13 : 0) + return (DebugVtables ? 512 : 74) + (CountCompiledCalls ? 13 : 0) +
(UseCompressedOops ? 32 : 0); // 2 leaqs (UseCompressedKlassPointers ? 32 : 0); // 2 leaqs
} }
// In order to tune these parameters, run the JVM with VM options // In order to tune these parameters, run the JVM with VM options
// +PrintMiscellaneous and +WizardMode to see information about // +PrintMiscellaneous and +WizardMode to see information about

View file

@ -1424,6 +1424,11 @@ bool Matcher::narrow_oop_use_complex_address() {
return true; return true;
} }
bool Matcher::narrow_klass_use_complex_address() {
ShouldNotCallThis();
return true;
}
// Is it better to copy float constants, or load them directly from memory? // Is it better to copy float constants, or load them directly from memory?
// Intel can load a float constant from a direct address, requiring no // Intel can load a float constant from a direct address, requiring no
@ -1553,9 +1558,6 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() {
// Returns true if the high 32 bits of the value is known to be zero. // Returns true if the high 32 bits of the value is known to be zero.
bool is_operand_hi32_zero(Node* n) { bool is_operand_hi32_zero(Node* n) {
int opc = n->Opcode(); int opc = n->Opcode();
if (opc == Op_LoadUI2L) {
return true;
}
if (opc == Op_AndL) { if (opc == Op_AndL) {
Node* o2 = n->in(2); Node* o2 = n->in(2);
if (o2->is_Con() && (o2->get_long() & 0xFFFFFFFF00000000LL) == 0LL) { if (o2->is_Con() && (o2->get_long() & 0xFFFFFFFF00000000LL) == 0LL) {
@ -6147,8 +6149,8 @@ instruct loadI2L_immI(eRegL dst, memory mem, immI mask, eFlagsReg cr) %{
%} %}
// Load Unsigned Integer into Long Register // Load Unsigned Integer into Long Register
instruct loadUI2L(eRegL dst, memory mem, eFlagsReg cr) %{ instruct loadUI2L(eRegL dst, memory mem, immL_32bits mask, eFlagsReg cr) %{
match(Set dst (LoadUI2L mem)); match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
effect(KILL cr); effect(KILL cr);
ins_cost(250); ins_cost(250);

View file

@ -1409,10 +1409,10 @@ uint reloc_java_to_interp()
#ifndef PRODUCT #ifndef PRODUCT
void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const
{ {
if (UseCompressedOops) { if (UseCompressedKlassPointers) {
st->print_cr("movl rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); st->print_cr("movl rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass");
if (Universe::narrow_oop_shift() != 0) { if (Universe::narrow_klass_shift() != 0) {
st->print_cr("\tdecode_heap_oop_not_null rscratch1, rscratch1"); st->print_cr("\tdecode_klass_not_null rscratch1, rscratch1");
} }
st->print_cr("\tcmpq rax, rscratch1\t # Inline cache check"); st->print_cr("\tcmpq rax, rscratch1\t # Inline cache check");
} else { } else {
@ -1428,7 +1428,7 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
{ {
MacroAssembler masm(&cbuf); MacroAssembler masm(&cbuf);
uint insts_size = cbuf.insts_size(); uint insts_size = cbuf.insts_size();
if (UseCompressedOops) { if (UseCompressedKlassPointers) {
masm.load_klass(rscratch1, j_rarg0); masm.load_klass(rscratch1, j_rarg0);
masm.cmpptr(rax, rscratch1); masm.cmpptr(rax, rscratch1);
} else { } else {
@ -1576,6 +1576,11 @@ bool Matcher::narrow_oop_use_complex_address() {
return (LogMinObjAlignmentInBytes <= 3); return (LogMinObjAlignmentInBytes <= 3);
} }
bool Matcher::narrow_klass_use_complex_address() {
assert(UseCompressedKlassPointers, "only for compressed klass code");
return (LogKlassAlignmentInBytes <= 3);
}
// Is it better to copy float constants, or load them directly from // Is it better to copy float constants, or load them directly from
// memory? Intel can load a float constant from a direct address, // memory? Intel can load a float constant from a direct address,
// requiring no extra registers. Most RISCs will have to materialize // requiring no extra registers. Most RISCs will have to materialize
@ -3139,6 +3144,14 @@ operand immN() %{
interface(CONST_INTER); interface(CONST_INTER);
%} %}
operand immNKlass() %{
match(ConNKlass);
op_cost(10);
format %{ %}
interface(CONST_INTER);
%}
// NULL Pointer Immediate // NULL Pointer Immediate
operand immN0() %{ operand immN0() %{
predicate(n->get_narrowcon() == 0); predicate(n->get_narrowcon() == 0);
@ -4038,6 +4051,145 @@ operand indPosIndexScaleOffsetNarrow(rRegN reg, immL32 off, rRegI idx, immI2 sca
%} %}
%} %}
operand indirectNarrowKlass(rRegN reg)
%{
predicate(Universe::narrow_klass_shift() == 0);
constraint(ALLOC_IN_RC(ptr_reg));
match(DecodeNKlass reg);
format %{ "[$reg]" %}
interface(MEMORY_INTER) %{
base($reg);
index(0x4);
scale(0x0);
disp(0x0);
%}
%}
operand indOffset8NarrowKlass(rRegN reg, immL8 off)
%{
predicate(Universe::narrow_klass_shift() == 0);
constraint(ALLOC_IN_RC(ptr_reg));
match(AddP (DecodeNKlass reg) off);
format %{ "[$reg + $off (8-bit)]" %}
interface(MEMORY_INTER) %{
base($reg);
index(0x4);
scale(0x0);
disp($off);
%}
%}
operand indOffset32NarrowKlass(rRegN reg, immL32 off)
%{
predicate(Universe::narrow_klass_shift() == 0);
constraint(ALLOC_IN_RC(ptr_reg));
match(AddP (DecodeNKlass reg) off);
format %{ "[$reg + $off (32-bit)]" %}
interface(MEMORY_INTER) %{
base($reg);
index(0x4);
scale(0x0);
disp($off);
%}
%}
operand indIndexOffsetNarrowKlass(rRegN reg, rRegL lreg, immL32 off)
%{
predicate(Universe::narrow_klass_shift() == 0);
constraint(ALLOC_IN_RC(ptr_reg));
match(AddP (AddP (DecodeNKlass reg) lreg) off);
op_cost(10);
format %{"[$reg + $off + $lreg]" %}
interface(MEMORY_INTER) %{
base($reg);
index($lreg);
scale(0x0);
disp($off);
%}
%}
operand indIndexNarrowKlass(rRegN reg, rRegL lreg)
%{
predicate(Universe::narrow_klass_shift() == 0);
constraint(ALLOC_IN_RC(ptr_reg));
match(AddP (DecodeNKlass reg) lreg);
op_cost(10);
format %{"[$reg + $lreg]" %}
interface(MEMORY_INTER) %{
base($reg);
index($lreg);
scale(0x0);
disp(0x0);
%}
%}
operand indIndexScaleNarrowKlass(rRegN reg, rRegL lreg, immI2 scale)
%{
predicate(Universe::narrow_klass_shift() == 0);
constraint(ALLOC_IN_RC(ptr_reg));
match(AddP (DecodeNKlass reg) (LShiftL lreg scale));
op_cost(10);
format %{"[$reg + $lreg << $scale]" %}
interface(MEMORY_INTER) %{
base($reg);
index($lreg);
scale($scale);
disp(0x0);
%}
%}
operand indIndexScaleOffsetNarrowKlass(rRegN reg, immL32 off, rRegL lreg, immI2 scale)
%{
predicate(Universe::narrow_klass_shift() == 0);
constraint(ALLOC_IN_RC(ptr_reg));
match(AddP (AddP (DecodeNKlass reg) (LShiftL lreg scale)) off);
op_cost(10);
format %{"[$reg + $off + $lreg << $scale]" %}
interface(MEMORY_INTER) %{
base($reg);
index($lreg);
scale($scale);
disp($off);
%}
%}
operand indCompressedKlassOffset(rRegN reg, immL32 off) %{
predicate(UseCompressedKlassPointers && (Universe::narrow_klass_shift() == Address::times_8));
constraint(ALLOC_IN_RC(ptr_reg));
match(AddP (DecodeNKlass reg) off);
op_cost(10);
format %{"[R12 + $reg << 3 + $off] (compressed klass addressing)" %}
interface(MEMORY_INTER) %{
base(0xc); // R12
index($reg);
scale(0x3);
disp($off);
%}
%}
operand indPosIndexScaleOffsetNarrowKlass(rRegN reg, immL32 off, rRegI idx, immI2 scale)
%{
constraint(ALLOC_IN_RC(ptr_reg));
predicate(Universe::narrow_klass_shift() == 0 && n->in(2)->in(3)->in(1)->as_Type()->type()->is_long()->_lo >= 0);
match(AddP (AddP (DecodeNKlass reg) (LShiftL (ConvI2L idx) scale)) off);
op_cost(10);
format %{"[$reg + $off + $idx << $scale]" %}
interface(MEMORY_INTER) %{
base($reg);
index($idx);
scale($scale);
disp($off);
%}
%}
//----------Special Memory Operands-------------------------------------------- //----------Special Memory Operands--------------------------------------------
// Stack Slot Operand - This operand is used for loading and storing temporary // Stack Slot Operand - This operand is used for loading and storing temporary
@ -4209,7 +4361,11 @@ opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex,
indCompressedOopOffset, indCompressedOopOffset,
indirectNarrow, indOffset8Narrow, indOffset32Narrow, indirectNarrow, indOffset8Narrow, indOffset32Narrow,
indIndexOffsetNarrow, indIndexNarrow, indIndexScaleNarrow, indIndexOffsetNarrow, indIndexNarrow, indIndexScaleNarrow,
indIndexScaleOffsetNarrow, indPosIndexScaleOffsetNarrow); indIndexScaleOffsetNarrow, indPosIndexScaleOffsetNarrow,
indCompressedKlassOffset,
indirectNarrowKlass, indOffset8NarrowKlass, indOffset32NarrowKlass,
indIndexOffsetNarrowKlass, indIndexNarrowKlass, indIndexScaleNarrowKlass,
indIndexScaleOffsetNarrowKlass, indPosIndexScaleOffsetNarrowKlass);
//----------PIPELINE----------------------------------------------------------- //----------PIPELINE-----------------------------------------------------------
// Rules which define the behavior of the target architectures pipeline. // Rules which define the behavior of the target architectures pipeline.
@ -5044,9 +5200,9 @@ instruct loadI2L_immI(rRegL dst, memory mem, immI mask, rFlagsReg cr) %{
%} %}
// Load Unsigned Integer into Long Register // Load Unsigned Integer into Long Register
instruct loadUI2L(rRegL dst, memory mem) instruct loadUI2L(rRegL dst, memory mem, immL_32bits mask)
%{ %{
match(Set dst (LoadUI2L mem)); match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
ins_cost(125); ins_cost(125);
format %{ "movl $dst, $mem\t# uint -> long" %} format %{ "movl $dst, $mem\t# uint -> long" %}
@ -5469,6 +5625,22 @@ instruct loadConN(rRegN dst, immN src) %{
ins_pipe(ialu_reg_fat); // XXX ins_pipe(ialu_reg_fat); // XXX
%} %}
instruct loadConNKlass(rRegN dst, immNKlass src) %{
match(Set dst src);
ins_cost(125);
format %{ "movl $dst, $src\t# compressed klass ptr" %}
ins_encode %{
address con = (address)$src$$constant;
if (con == NULL) {
ShouldNotReachHere();
} else {
__ set_narrow_klass($dst$$Register, (Klass*)$src$$constant);
}
%}
ins_pipe(ialu_reg_fat); // XXX
%}
instruct loadConF0(regF dst, immF0 src) instruct loadConF0(regF dst, immF0 src)
%{ %{
match(Set dst src); match(Set dst src);
@ -5738,7 +5910,7 @@ instruct storeP(memory mem, any_RegP src)
instruct storeImmP0(memory mem, immP0 zero) instruct storeImmP0(memory mem, immP0 zero)
%{ %{
predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL) && (Universe::narrow_klass_base() == NULL));
match(Set mem (StoreP mem zero)); match(Set mem (StoreP mem zero));
ins_cost(125); // XXX ins_cost(125); // XXX
@ -5774,9 +5946,21 @@ instruct storeN(memory mem, rRegN src)
ins_pipe(ialu_mem_reg); ins_pipe(ialu_mem_reg);
%} %}
instruct storeNKlass(memory mem, rRegN src)
%{
match(Set mem (StoreNKlass mem src));
ins_cost(125); // XXX
format %{ "movl $mem, $src\t# compressed klass ptr" %}
ins_encode %{
__ movl($mem$$Address, $src$$Register);
%}
ins_pipe(ialu_mem_reg);
%}
instruct storeImmN0(memory mem, immN0 zero) instruct storeImmN0(memory mem, immN0 zero)
%{ %{
predicate(Universe::narrow_oop_base() == NULL); predicate(Universe::narrow_oop_base() == NULL && Universe::narrow_klass_base() == NULL);
match(Set mem (StoreN mem zero)); match(Set mem (StoreN mem zero));
ins_cost(125); // XXX ins_cost(125); // XXX
@ -5804,10 +5988,22 @@ instruct storeImmN(memory mem, immN src)
ins_pipe(ialu_mem_imm); ins_pipe(ialu_mem_imm);
%} %}
instruct storeImmNKlass(memory mem, immNKlass src)
%{
match(Set mem (StoreNKlass mem src));
ins_cost(150); // XXX
format %{ "movl $mem, $src\t# compressed klass ptr" %}
ins_encode %{
__ set_narrow_klass($mem$$Address, (Klass*)$src$$constant);
%}
ins_pipe(ialu_mem_imm);
%}
// Store Integer Immediate // Store Integer Immediate
instruct storeImmI0(memory mem, immI0 zero) instruct storeImmI0(memory mem, immI0 zero)
%{ %{
predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL) && (Universe::narrow_klass_base() == NULL));
match(Set mem (StoreI mem zero)); match(Set mem (StoreI mem zero));
ins_cost(125); // XXX ins_cost(125); // XXX
@ -5832,7 +6028,7 @@ instruct storeImmI(memory mem, immI src)
// Store Long Immediate // Store Long Immediate
instruct storeImmL0(memory mem, immL0 zero) instruct storeImmL0(memory mem, immL0 zero)
%{ %{
predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL) && (Universe::narrow_klass_base() == NULL));
match(Set mem (StoreL mem zero)); match(Set mem (StoreL mem zero));
ins_cost(125); // XXX ins_cost(125); // XXX
@ -5857,7 +6053,7 @@ instruct storeImmL(memory mem, immL32 src)
// Store Short/Char Immediate // Store Short/Char Immediate
instruct storeImmC0(memory mem, immI0 zero) instruct storeImmC0(memory mem, immI0 zero)
%{ %{
predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL) && (Universe::narrow_klass_base() == NULL));
match(Set mem (StoreC mem zero)); match(Set mem (StoreC mem zero));
ins_cost(125); // XXX ins_cost(125); // XXX
@ -5883,7 +6079,7 @@ instruct storeImmI16(memory mem, immI16 src)
// Store Byte Immediate // Store Byte Immediate
instruct storeImmB0(memory mem, immI0 zero) instruct storeImmB0(memory mem, immI0 zero)
%{ %{
predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL) && (Universe::narrow_klass_base() == NULL));
match(Set mem (StoreB mem zero)); match(Set mem (StoreB mem zero));
ins_cost(125); // XXX ins_cost(125); // XXX
@ -5908,7 +6104,7 @@ instruct storeImmB(memory mem, immI8 src)
// Store CMS card-mark Immediate // Store CMS card-mark Immediate
instruct storeImmCM0_reg(memory mem, immI0 zero) instruct storeImmCM0_reg(memory mem, immI0 zero)
%{ %{
predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL) && (Universe::narrow_klass_base() == NULL));
match(Set mem (StoreCM mem zero)); match(Set mem (StoreCM mem zero));
ins_cost(125); // XXX ins_cost(125); // XXX
@ -5946,7 +6142,7 @@ instruct storeF(memory mem, regF src)
// Store immediate Float value (it is faster than store from XMM register) // Store immediate Float value (it is faster than store from XMM register)
instruct storeF0(memory mem, immF0 zero) instruct storeF0(memory mem, immF0 zero)
%{ %{
predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL) && (Universe::narrow_klass_base() == NULL));
match(Set mem (StoreF mem zero)); match(Set mem (StoreF mem zero));
ins_cost(25); // XXX ins_cost(25); // XXX
@ -5996,7 +6192,7 @@ instruct storeD0_imm(memory mem, immD0 src)
instruct storeD0(memory mem, immD0 zero) instruct storeD0(memory mem, immD0 zero)
%{ %{
predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL) && (Universe::narrow_klass_base() == NULL));
match(Set mem (StoreD mem zero)); match(Set mem (StoreD mem zero));
ins_cost(25); // XXX ins_cost(25); // XXX
@ -6482,6 +6678,32 @@ instruct decodeHeapOop_not_null(rRegP dst, rRegN src, rFlagsReg cr) %{
ins_pipe(ialu_reg_long); ins_pipe(ialu_reg_long);
%} %}
instruct encodeKlass_not_null(rRegN dst, rRegP src, rFlagsReg cr) %{
match(Set dst (EncodePKlass src));
effect(KILL cr);
format %{ "encode_heap_oop_not_null $dst,$src" %}
ins_encode %{
__ encode_klass_not_null($dst$$Register, $src$$Register);
%}
ins_pipe(ialu_reg_long);
%}
instruct decodeKlass_not_null(rRegP dst, rRegN src, rFlagsReg cr) %{
match(Set dst (DecodeNKlass src));
effect(KILL cr);
format %{ "decode_heap_oop_not_null $dst,$src" %}
ins_encode %{
Register s = $src$$Register;
Register d = $dst$$Register;
if (s != d) {
__ decode_klass_not_null(d, s);
} else {
__ decode_klass_not_null(d);
}
%}
ins_pipe(ialu_reg_long);
%}
//----------Conditional Move--------------------------------------------------- //----------Conditional Move---------------------------------------------------
// Jump // Jump
@ -10452,7 +10674,7 @@ instruct testP_mem(rFlagsReg cr, memory op, immP0 zero)
instruct testP_mem_reg0(rFlagsReg cr, memory mem, immP0 zero) instruct testP_mem_reg0(rFlagsReg cr, memory mem, immP0 zero)
%{ %{
predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL)); predicate(UseCompressedOops && (Universe::narrow_oop_base() == NULL) && (Universe::narrow_klass_base() == NULL));
match(Set cr (CmpP (LoadP mem) zero)); match(Set cr (CmpP (LoadP mem) zero));
format %{ "cmpq R12, $mem\t# ptr (R12_heapbase==0)" %} format %{ "cmpq R12, $mem\t# ptr (R12_heapbase==0)" %}
@ -10503,6 +10725,27 @@ instruct compN_mem_imm(rFlagsRegU cr, memory mem, immN src)
ins_pipe(ialu_cr_reg_mem); ins_pipe(ialu_cr_reg_mem);
%} %}
instruct compN_rReg_imm_klass(rFlagsRegU cr, rRegN op1, immNKlass op2) %{
match(Set cr (CmpN op1 op2));
format %{ "cmpl $op1, $op2\t# compressed klass ptr" %}
ins_encode %{
__ cmp_narrow_klass($op1$$Register, (Klass*)$op2$$constant);
%}
ins_pipe(ialu_cr_reg_imm);
%}
instruct compN_mem_imm_klass(rFlagsRegU cr, memory mem, immNKlass src)
%{
match(Set cr (CmpN src (LoadNKlass mem)));
format %{ "cmpl $mem, $src\t# compressed klass ptr" %}
ins_encode %{
__ cmp_narrow_klass($mem$$Address, (Klass*)$src$$constant);
%}
ins_pipe(ialu_cr_reg_mem);
%}
instruct testN_reg(rFlagsReg cr, rRegN src, immN0 zero) %{ instruct testN_reg(rFlagsReg cr, rRegN src, immN0 zero) %{
match(Set cr (CmpN src zero)); match(Set cr (CmpN src zero));
@ -10526,7 +10769,7 @@ instruct testN_mem(rFlagsReg cr, memory mem, immN0 zero)
instruct testN_mem_reg0(rFlagsReg cr, memory mem, immN0 zero) instruct testN_mem_reg0(rFlagsReg cr, memory mem, immN0 zero)
%{ %{
predicate(Universe::narrow_oop_base() == NULL); predicate(Universe::narrow_oop_base() == NULL && (Universe::narrow_klass_base() == NULL));
match(Set cr (CmpN (LoadN mem) zero)); match(Set cr (CmpN (LoadN mem) zero));
format %{ "cmpl R12, $mem\t# compressed ptr (R12_heapbase==0)" %} format %{ "cmpl R12, $mem\t# compressed ptr (R12_heapbase==0)" %}

View file

@ -267,8 +267,8 @@ int generateJvmOffsets(GEN_variant gen_variant) {
printf("\n"); printf("\n");
GEN_OFFS(NarrowOopStruct, _base); GEN_OFFS(NarrowPtrStruct, _base);
GEN_OFFS(NarrowOopStruct, _shift); GEN_OFFS(NarrowPtrStruct, _shift);
printf("\n"); printf("\n");
GEN_VALUE(SIZE_HeapBlockHeader, (int) sizeof(HeapBlock::Header)); GEN_VALUE(SIZE_HeapBlockHeader, (int) sizeof(HeapBlock::Header));

View file

@ -45,10 +45,6 @@ extern pointer __JvmOffsets;
extern pointer __1cJCodeCacheF_heap_; extern pointer __1cJCodeCacheF_heap_;
extern pointer __1cIUniverseO_collectedHeap_; extern pointer __1cIUniverseO_collectedHeap_;
extern pointer __1cIUniverseL_narrow_oop_;
#ifdef _LP64
extern pointer UseCompressedOops;
#endif
extern pointer __1cHnmethodG__vtbl_; extern pointer __1cHnmethodG__vtbl_;
extern pointer __1cNMethodG__vtbl_; extern pointer __1cNMethodG__vtbl_;
@ -136,8 +132,8 @@ dtrace:helper:ustack:
copyin_offset(SIZE_oopDesc); copyin_offset(SIZE_oopDesc);
copyin_offset(SIZE_ConstantPool); copyin_offset(SIZE_ConstantPool);
copyin_offset(OFFSET_NarrowOopStruct_base); copyin_offset(OFFSET_NarrowPtrStruct_base);
copyin_offset(OFFSET_NarrowOopStruct_shift); copyin_offset(OFFSET_NarrowPtrStruct_shift);
/* /*
* The PC to translate is in arg0. * The PC to translate is in arg0.
@ -159,17 +155,6 @@ dtrace:helper:ustack:
this->CodeCache_heap_address = copyin_ptr(&``__1cJCodeCacheF_heap_); this->CodeCache_heap_address = copyin_ptr(&``__1cJCodeCacheF_heap_);
/* Reading volatile values */ /* Reading volatile values */
#ifdef _LP64
this->Use_Compressed_Oops = copyin_uint8(&``UseCompressedOops);
#else
this->Use_Compressed_Oops = 0;
#endif
this->Universe_narrow_oop_base = copyin_ptr(&``__1cIUniverseL_narrow_oop_ +
OFFSET_NarrowOopStruct_base);
this->Universe_narrow_oop_shift = copyin_int32(&``__1cIUniverseL_narrow_oop_ +
OFFSET_NarrowOopStruct_shift);
this->CodeCache_low = copyin_ptr(this->CodeCache_heap_address + this->CodeCache_low = copyin_ptr(this->CodeCache_heap_address +
OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low); OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);

View file

@ -44,7 +44,7 @@ void VMError::show_message_box(char *buf, int buflen) {
jio_snprintf(p, buflen - len, jio_snprintf(p, buflen - len,
"\n\n" "\n\n"
"Do you want to debug the problem?\n\n" "Do you want to debug the problem?\n\n"
"To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " INTX_FORMAT " (" INTPTR_FORMAT ")\n" "To debug, run 'gdb /proc/%d/exe %d'; then switch to thread " UINTX_FORMAT " (" INTPTR_FORMAT ")\n"
"Enter 'yes' to launch gdb automatically (PATH must include gdb)\n" "Enter 'yes' to launch gdb automatically (PATH must include gdb)\n"
"Otherwise, press RETURN to abort...", "Otherwise, press RETURN to abort...",
os::current_process_id(), os::current_process_id(), os::current_process_id(), os::current_process_id(),

View file

@ -262,8 +262,8 @@ int generateJvmOffsets(GEN_variant gen_variant) {
printf("\n"); printf("\n");
GEN_OFFS(NarrowOopStruct, _base); GEN_OFFS(NarrowPtrStruct, _base);
GEN_OFFS(NarrowOopStruct, _shift); GEN_OFFS(NarrowPtrStruct, _shift);
printf("\n"); printf("\n");
GEN_VALUE(SIZE_HeapBlockHeader, sizeof(HeapBlock::Header)); GEN_VALUE(SIZE_HeapBlockHeader, sizeof(HeapBlock::Header));

View file

@ -45,10 +45,6 @@ extern pointer __JvmOffsets;
extern pointer __1cJCodeCacheF_heap_; extern pointer __1cJCodeCacheF_heap_;
extern pointer __1cIUniverseO_collectedHeap_; extern pointer __1cIUniverseO_collectedHeap_;
extern pointer __1cIUniverseL_narrow_oop_;
#ifdef _LP64
extern pointer UseCompressedOops;
#endif
extern pointer __1cHnmethodG__vtbl_; extern pointer __1cHnmethodG__vtbl_;
extern pointer __1cGMethodG__vtbl_; extern pointer __1cGMethodG__vtbl_;
@ -136,8 +132,8 @@ dtrace:helper:ustack:
copyin_offset(SIZE_oopDesc); copyin_offset(SIZE_oopDesc);
copyin_offset(SIZE_ConstantPool); copyin_offset(SIZE_ConstantPool);
copyin_offset(OFFSET_NarrowOopStruct_base); copyin_offset(OFFSET_NarrowPtrStruct_base);
copyin_offset(OFFSET_NarrowOopStruct_shift); copyin_offset(OFFSET_NarrowPtrStruct_shift);
/* /*
* The PC to translate is in arg0. * The PC to translate is in arg0.
@ -158,18 +154,6 @@ dtrace:helper:ustack:
this->CodeCache_heap_address = copyin_ptr(&``__1cJCodeCacheF_heap_); this->CodeCache_heap_address = copyin_ptr(&``__1cJCodeCacheF_heap_);
/* Reading volatile values */
#ifdef _LP64
this->Use_Compressed_Oops = copyin_uint8(&``UseCompressedOops);
#else
this->Use_Compressed_Oops = 0;
#endif
this->Universe_narrow_oop_base = copyin_ptr(&``__1cIUniverseL_narrow_oop_ +
OFFSET_NarrowOopStruct_base);
this->Universe_narrow_oop_shift = copyin_int32(&``__1cIUniverseL_narrow_oop_ +
OFFSET_NarrowOopStruct_shift);
this->CodeCache_low = copyin_ptr(this->CodeCache_heap_address + this->CodeCache_low = copyin_ptr(this->CodeCache_heap_address +
OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low); OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);

View file

@ -1392,7 +1392,7 @@ void ADLParser::pipe_parse(void) {
_AD.addForm(machnode); _AD.addForm(machnode);
} }
else if (!strcmp(ident, "attributes")) { else if (!strcmp(ident, "attributes")) {
bool vsi_seen = false, bhds_seen = false; bool vsi_seen = false;
skipws(); skipws();
if ( (_curchar != '%') if ( (_curchar != '%')
@ -1436,7 +1436,6 @@ void ADLParser::pipe_parse(void) {
} }
pipeline->_branchHasDelaySlot = true; pipeline->_branchHasDelaySlot = true;
bhds_seen = true;
continue; continue;
} }
@ -1639,6 +1638,12 @@ void ADLParser::resource_parse(PipelineForm &pipeline) {
next_char(); // Skip "(" or "," next_char(); // Skip "(" or ","
ident = get_ident(); // Grab next identifier ident = get_ident(); // Grab next identifier
if (_AD._adl_debug > 1) {
if (ident != NULL) {
fprintf(stderr, "resource_parse: identifier: %s\n", ident);
}
}
if (ident == NULL) { if (ident == NULL) {
parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar); parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
return; return;
@ -2427,7 +2432,6 @@ InstructForm *ADLParser::peep_match_child_parse(PeepMatch &match, int parent, in
int lparen = 0; // keep track of parenthesis nesting depth int lparen = 0; // keep track of parenthesis nesting depth
int rparen = 0; // position of instruction at this depth int rparen = 0; // position of instruction at this depth
InstructForm *inst_seen = NULL; InstructForm *inst_seen = NULL;
InstructForm *child_seen = NULL;
// Walk the match tree, // Walk the match tree,
// Record <parent, position, instruction name, input position> // Record <parent, position, instruction name, input position>
@ -2437,7 +2441,7 @@ InstructForm *ADLParser::peep_match_child_parse(PeepMatch &match, int parent, in
if (_curchar == '(') { if (_curchar == '(') {
++lparen; ++lparen;
next_char(); next_char();
child_seen = peep_match_child_parse(match, parent, position, rparen); ( void ) peep_match_child_parse(match, parent, position, rparen);
} }
// Right paren signals end of an input, may be more // Right paren signals end of an input, may be more
else if (_curchar == ')') { else if (_curchar == ')') {
@ -3154,6 +3158,9 @@ void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) {
//------------------------------size_parse----------------------------------- //------------------------------size_parse-----------------------------------
// Parse a 'size(<expr>)' attribute which specifies the size of the
// emitted instructions in bytes. <expr> can be a C++ expression,
// e.g. a constant.
char* ADLParser::size_parse(InstructForm *instr) { char* ADLParser::size_parse(InstructForm *instr) {
char* sizeOfInstr = NULL; char* sizeOfInstr = NULL;
@ -4274,7 +4281,17 @@ char *ADLParser::get_ident_common(bool do_preproc) {
|| ((c >= '0') && (c <= '9')) || ((c >= '0') && (c <= '9'))
|| ((c == '_')) || ((c == ':')) || ((c == '#')) ); || ((c == '_')) || ((c == ':')) || ((c == '#')) );
if (start == end) { // We popped out on the first try if (start == end) { // We popped out on the first try
parse_err(SYNERR, "identifier expected at %c\n", c); // It can occur that `start' contains the rest of the input file.
// In this case the output should be truncated.
if (strlen(start) > 24) {
char buf[32];
strncpy(buf, start, 20);
buf[20] = '\0';
strcat(buf, "[...]");
parse_err(SYNERR, "Identifier expected, but found '%s'.", buf);
} else {
parse_err(SYNERR, "Identifier expected, but found '%s'.", start);
}
start = NULL; start = NULL;
} }
else { else {

View file

@ -221,6 +221,7 @@ ArchDesc::ArchDesc()
_register = NULL; _register = NULL;
_encode = NULL; _encode = NULL;
_pipeline = NULL; _pipeline = NULL;
_frame = NULL;
} }
ArchDesc::~ArchDesc() { ArchDesc::~ArchDesc() {
@ -648,7 +649,10 @@ int ArchDesc::instructFormCount() {
// Return the textual binding for a given CPP flag name. // Return the textual binding for a given CPP flag name.
// Return NULL if there is no binding, or it has been #undef-ed. // Return NULL if there is no binding, or it has been #undef-ed.
char* ArchDesc::get_preproc_def(const char* flag) { char* ArchDesc::get_preproc_def(const char* flag) {
SourceForm* deff = (SourceForm*) _preproc_table[flag]; // In case of syntax errors, flag may take the value NULL.
SourceForm* deff = NULL;
if (flag != NULL)
deff = (SourceForm*) _preproc_table[flag];
return (deff == NULL) ? NULL : deff->_code; return (deff == NULL) ? NULL : deff->_code;
} }
@ -803,7 +807,9 @@ int ArchDesc::emit_msg(int quiet, int flag, int line, const char *fmt,
while (i++ <= 15) fputc(' ', errfile); while (i++ <= 15) fputc(' ', errfile);
fprintf(errfile, "%-8s:", pref); fprintf(errfile, "%-8s:", pref);
vfprintf(errfile, fmt, args); vfprintf(errfile, fmt, args);
fprintf(errfile, "\n"); } fprintf(errfile, "\n");
fflush(errfile);
}
return 1; return 1;
} }
@ -855,8 +861,14 @@ const char *ArchDesc::reg_mask(OperandForm &opForm) {
// Check constraints on result's register class // Check constraints on result's register class
const char *result_class = opForm.constrained_reg_class(); const char *result_class = opForm.constrained_reg_class();
if (!result_class) opForm.dump(); if (result_class == NULL) {
assert( result_class, "Resulting register class was not defined for operand"); opForm.dump();
syntax_err(opForm._linenum,
"Use of an undefined result class for operand: %s",
opForm._ident);
abort();
}
regMask = reg_class_to_reg_mask( result_class ); regMask = reg_class_to_reg_mask( result_class );
return regMask; return regMask;
@ -865,8 +877,14 @@ const char *ArchDesc::reg_mask(OperandForm &opForm) {
// Obtain the name of the RegMask for an InstructForm // Obtain the name of the RegMask for an InstructForm
const char *ArchDesc::reg_mask(InstructForm &inForm) { const char *ArchDesc::reg_mask(InstructForm &inForm) {
const char *result = inForm.reduce_result(); const char *result = inForm.reduce_result();
assert( result,
"Did not find result operand or RegMask for this instruction"); if (result == NULL) {
syntax_err(inForm._linenum,
"Did not find result operand or RegMask"
" for this instruction: %s",
inForm._ident);
abort();
}
// Instructions producing 'Universe' use RegMask::Empty // Instructions producing 'Universe' use RegMask::Empty
if( strcmp(result,"Universe")==0 ) { if( strcmp(result,"Universe")==0 ) {
@ -875,10 +893,17 @@ const char *ArchDesc::reg_mask(InstructForm &inForm) {
// Lookup this result operand and get its register class // Lookup this result operand and get its register class
Form *form = (Form*)_globalNames[result]; Form *form = (Form*)_globalNames[result];
assert( form, "Result operand must be defined"); if (form == NULL) {
syntax_err(inForm._linenum,
"Did not find result operand for result: %s", result);
abort();
}
OperandForm *oper = form->is_operand(); OperandForm *oper = form->is_operand();
if (oper == NULL) form->dump(); if (oper == NULL) {
assert( oper, "Result must be an OperandForm"); syntax_err(inForm._linenum, "Form is not an OperandForm:");
form->dump();
abort();
}
return reg_mask( *oper ); return reg_mask( *oper );
} }
@ -887,7 +912,13 @@ const char *ArchDesc::reg_mask(InstructForm &inForm) {
char *ArchDesc::stack_or_reg_mask(OperandForm &opForm) { char *ArchDesc::stack_or_reg_mask(OperandForm &opForm) {
// name of cisc_spillable version // name of cisc_spillable version
const char *reg_mask_name = reg_mask(opForm); const char *reg_mask_name = reg_mask(opForm);
assert( reg_mask_name != NULL, "called with incorrect opForm");
if (reg_mask_name == NULL) {
syntax_err(opForm._linenum,
"Did not find reg_mask for opForm: %s",
opForm._ident);
abort();
}
const char *stack_or = "STACK_OR_"; const char *stack_or = "STACK_OR_";
int length = (int)strlen(stack_or) + (int)strlen(reg_mask_name) + 1; int length = (int)strlen(stack_or) + (int)strlen(reg_mask_name) + 1;
@ -968,7 +999,8 @@ void ArchDesc::initBaseOpTypes() {
// Create InstructForm and assign type for each ideal instruction. // Create InstructForm and assign type for each ideal instruction.
for ( int j = _last_machine_leaf+1; j < _last_opcode; ++j) { for ( int j = _last_machine_leaf+1; j < _last_opcode; ++j) {
char *ident = (char *)NodeClassNames[j]; char *ident = (char *)NodeClassNames[j];
if(!strcmp(ident, "ConI") || !strcmp(ident, "ConP") || !strcmp(ident, "ConN") || if(!strcmp(ident, "ConI") || !strcmp(ident, "ConP") ||
!strcmp(ident, "ConN") || !strcmp(ident, "ConNKlass") ||
!strcmp(ident, "ConF") || !strcmp(ident, "ConD") || !strcmp(ident, "ConF") || !strcmp(ident, "ConD") ||
!strcmp(ident, "ConL") || !strcmp(ident, "Con" ) || !strcmp(ident, "ConL") || !strcmp(ident, "Con" ) ||
!strcmp(ident, "Bool") ) { !strcmp(ident, "Bool") ) {

View file

@ -369,9 +369,10 @@ protected:
FILE *_cpp; FILE *_cpp;
FormDict &_globals; FormDict &_globals;
ArchDesc &_AD; ArchDesc &_AD;
const char *_name;
public: public:
OutputMap (FILE *decl_file, FILE *def_file, FormDict &globals, ArchDesc &AD) OutputMap (FILE *decl_file, FILE *def_file, FormDict &globals, ArchDesc &AD, const char *name)
: _hpp(decl_file), _cpp(def_file), _globals(globals), _AD(AD) {}; : _hpp(decl_file), _cpp(def_file), _globals(globals), _AD(AD), _name(name) {};
// Access files used by this routine // Access files used by this routine
FILE *decl_file() { return _hpp; } FILE *decl_file() { return _hpp; }
FILE *def_file() { return _cpp; } FILE *def_file() { return _cpp; }

View file

@ -33,7 +33,7 @@
// String hash tables // String hash tables
#define MAXID 20 #define MAXID 20
static char initflag = 0; // True after 1st initialization static char initflag = 0; // True after 1st initialization
static char shft[MAXID] = {1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6}; static char shft[MAXID + 1] = {1,2,3,4,5,6,7,1,2,3,4,5,6,7,1,2,3,4,5,6,7};
static short xsum[MAXID]; static short xsum[MAXID];
//------------------------------bucket--------------------------------------- //------------------------------bucket---------------------------------------

View file

@ -31,10 +31,14 @@
using namespace std; using namespace std;
// STRUCTURE FOR HANDLING INPUT AND OUTPUT FILES // STRUCTURE FOR HANDLING INPUT AND OUTPUT FILES
typedef struct {
class BufferedFile {
public:
const char *_name; const char *_name;
FILE *_fp; FILE *_fp;
} BufferedFile; inline BufferedFile() { _name = NULL; _fp = NULL; };
inline ~BufferedFile() {};
};
class ArchDesc; class ArchDesc;

View file

@ -215,6 +215,7 @@ Form::DataType Form::ideal_to_const_type(const char *name) const {
if (strcmp(name,"ConI")==0) return Form::idealI; if (strcmp(name,"ConI")==0) return Form::idealI;
if (strcmp(name,"ConP")==0) return Form::idealP; if (strcmp(name,"ConP")==0) return Form::idealP;
if (strcmp(name,"ConN")==0) return Form::idealN; if (strcmp(name,"ConN")==0) return Form::idealN;
if (strcmp(name,"ConNKlass")==0) return Form::idealNKlass;
if (strcmp(name,"ConL")==0) return Form::idealL; if (strcmp(name,"ConL")==0) return Form::idealL;
if (strcmp(name,"ConF")==0) return Form::idealF; if (strcmp(name,"ConF")==0) return Form::idealF;
if (strcmp(name,"ConD")==0) return Form::idealD; if (strcmp(name,"ConD")==0) return Form::idealD;
@ -255,9 +256,8 @@ Form::DataType Form::is_load_from_memory(const char *opType) const {
if( strcmp(opType,"LoadD_unaligned")==0 ) return Form::idealD; if( strcmp(opType,"LoadD_unaligned")==0 ) return Form::idealD;
if( strcmp(opType,"LoadF")==0 ) return Form::idealF; if( strcmp(opType,"LoadF")==0 ) return Form::idealF;
if( strcmp(opType,"LoadI")==0 ) return Form::idealI; if( strcmp(opType,"LoadI")==0 ) return Form::idealI;
if( strcmp(opType,"LoadUI2L")==0 ) return Form::idealI;
if( strcmp(opType,"LoadKlass")==0 ) return Form::idealP; if( strcmp(opType,"LoadKlass")==0 ) return Form::idealP;
if( strcmp(opType,"LoadNKlass")==0 ) return Form::idealN; if( strcmp(opType,"LoadNKlass")==0 ) return Form::idealNKlass;
if( strcmp(opType,"LoadL")==0 ) return Form::idealL; if( strcmp(opType,"LoadL")==0 ) return Form::idealL;
if( strcmp(opType,"LoadL_unaligned")==0 ) return Form::idealL; if( strcmp(opType,"LoadL_unaligned")==0 ) return Form::idealL;
if( strcmp(opType,"LoadPLocked")==0 ) return Form::idealP; if( strcmp(opType,"LoadPLocked")==0 ) return Form::idealP;
@ -280,6 +280,7 @@ Form::DataType Form::is_store_to_memory(const char *opType) const {
if( strcmp(opType,"StoreL")==0) return Form::idealL; if( strcmp(opType,"StoreL")==0) return Form::idealL;
if( strcmp(opType,"StoreP")==0) return Form::idealP; if( strcmp(opType,"StoreP")==0) return Form::idealP;
if( strcmp(opType,"StoreN")==0) return Form::idealN; if( strcmp(opType,"StoreN")==0) return Form::idealN;
if( strcmp(opType,"StoreNKlass")==0) return Form::idealNKlass;
if( strcmp(opType,"StoreVector")==0 ) return Form::idealV; if( strcmp(opType,"StoreVector")==0 ) return Form::idealV;
assert( strcmp(opType,"Store") != 0, "Must type Stores" ); assert( strcmp(opType,"Store") != 0, "Must type Stores" );
return Form::none; return Form::none;

View file

@ -173,7 +173,8 @@ public:
idealC = 7, // Char type idealC = 7, // Char type
idealS = 8, // String type idealS = 8, // String type
idealN = 9, // Narrow oop types idealN = 9, // Narrow oop types
idealV = 10 // Vector type idealNKlass = 10, // Narrow klass types
idealV = 11 // Vector type
}; };
// Convert ideal name to a DataType, return DataType::none if not a 'ConX' // Convert ideal name to a DataType, return DataType::none if not a 'ConX'
Form::DataType ideal_to_const_type(const char *ideal_type_name) const; Form::DataType ideal_to_const_type(const char *ideal_type_name) const;
@ -448,11 +449,11 @@ public:
// Return number of USEs + number of DEFs // Return number of USEs + number of DEFs
int num_operands(); int num_operands();
// Return zero-based position in list; -1 if not in list. // Return zero-based position in list; -1 if not in list.
int operand_position(const char *name, int usedef); int operand_position(const char *name, int usedef, Form *fm);
// Find position for this name, regardless of use/def information // Find position for this name, regardless of use/def information
int operand_position(const char *name); int operand_position(const char *name);
// Find position for this name when looked up for output via "format" // Find position for this name when looked up for output via "format"
int operand_position_format(const char *name); int operand_position_format(const char *name, Form *fm);
// Find position for the Label when looked up for output via "format" // Find position for the Label when looked up for output via "format"
int label_position(); int label_position();
// Find position for the Method when looked up for output via "format" // Find position for the Method when looked up for output via "format"

View file

@ -567,7 +567,7 @@ bool InstructForm::rematerialize(FormDict &globals, RegisterForm *registers ) {
if( strcmp(rc_name,"stack_slots") ) { if( strcmp(rc_name,"stack_slots") ) {
// Check for ideal_type of RegFlags // Check for ideal_type of RegFlags
const char *type = opform->ideal_type( globals, registers ); const char *type = opform->ideal_type( globals, registers );
if( !strcmp(type,"RegFlags") ) if( (type != NULL) && !strcmp(type, "RegFlags") )
rematerialize = true; rematerialize = true;
} else } else
rematerialize = false; // Do not rematerialize things target stk rematerialize = false; // Do not rematerialize things target stk
@ -750,6 +750,8 @@ bool InstructForm::captures_bottom_type(FormDict &globals) const {
!strcmp(_matrule->_rChild->_opType,"CastX2P") || // new result type !strcmp(_matrule->_rChild->_opType,"CastX2P") || // new result type
!strcmp(_matrule->_rChild->_opType,"DecodeN") || !strcmp(_matrule->_rChild->_opType,"DecodeN") ||
!strcmp(_matrule->_rChild->_opType,"EncodeP") || !strcmp(_matrule->_rChild->_opType,"EncodeP") ||
!strcmp(_matrule->_rChild->_opType,"DecodeNKlass") ||
!strcmp(_matrule->_rChild->_opType,"EncodePKlass") ||
!strcmp(_matrule->_rChild->_opType,"LoadN") || !strcmp(_matrule->_rChild->_opType,"LoadN") ||
!strcmp(_matrule->_rChild->_opType,"GetAndSetN") || !strcmp(_matrule->_rChild->_opType,"GetAndSetN") ||
!strcmp(_matrule->_rChild->_opType,"LoadNKlass") || !strcmp(_matrule->_rChild->_opType,"LoadNKlass") ||
@ -793,6 +795,20 @@ uint InstructForm::num_opnds() {
return num_opnds; return num_opnds;
} }
const char *InstructForm::opnd_ident(int idx) {
return _components.at(idx)->_name;
}
const char *InstructForm::unique_opnd_ident(int idx) {
uint i;
for (i = 1; i < num_opnds(); ++i) {
if (unique_opnds_idx(i) == idx) {
break;
}
}
return (_components.at(i) != NULL) ? _components.at(i)->_name : "";
}
// Return count of unmatched operands. // Return count of unmatched operands.
uint InstructForm::num_post_match_opnds() { uint InstructForm::num_post_match_opnds() {
uint num_post_match_opnds = _components.count(); uint num_post_match_opnds = _components.count();
@ -864,6 +880,9 @@ uint InstructForm::oper_input_base(FormDict &globals) {
return base; return base;
} }
// This function determines the order of the MachOper in _opnds[]
// by writing the operand names into the _components list.
//
// Implementation does not modify state of internal structures // Implementation does not modify state of internal structures
void InstructForm::build_components() { void InstructForm::build_components() {
// Add top-level operands to the components // Add top-level operands to the components
@ -959,11 +978,11 @@ void InstructForm::build_components() {
// Return zero-based position in component list; -1 if not in list. // Return zero-based position in component list; -1 if not in list.
int InstructForm::operand_position(const char *name, int usedef) { int InstructForm::operand_position(const char *name, int usedef) {
return unique_opnds_idx(_components.operand_position(name, usedef)); return unique_opnds_idx(_components.operand_position(name, usedef, this));
} }
int InstructForm::operand_position_format(const char *name) { int InstructForm::operand_position_format(const char *name) {
return unique_opnds_idx(_components.operand_position_format(name)); return unique_opnds_idx(_components.operand_position_format(name, this));
} }
// Return zero-based position in component list; -1 if not in list. // Return zero-based position in component list; -1 if not in list.
@ -1223,7 +1242,7 @@ bool InstructForm::check_branch_variant(ArchDesc &AD, InstructForm *short_branch
if (different) { if (different) {
globalAD->syntax_err(short_branch->_linenum, "Instruction %s and its short form %s have different parameters\n", _ident, short_branch->_ident); globalAD->syntax_err(short_branch->_linenum, "Instruction %s and its short form %s have different parameters\n", _ident, short_branch->_ident);
} }
if (AD._short_branch_debug) { if (AD._adl_debug > 1 || AD._short_branch_debug) {
fprintf(stderr, "Instruction %s has short form %s\n", _ident, short_branch->_ident); fprintf(stderr, "Instruction %s has short form %s\n", _ident, short_branch->_ident);
} }
_short_branch_form = short_branch; _short_branch_form = short_branch;
@ -1255,16 +1274,19 @@ void InstructForm::rep_var_format(FILE *fp, const char *rep_var) {
// Find replacement variable's type // Find replacement variable's type
const Form *form = _localNames[rep_var]; const Form *form = _localNames[rep_var];
if (form == NULL) { if (form == NULL) {
fprintf(stderr, "unknown replacement variable in format statement: '%s'\n", rep_var); globalAD->syntax_err(_linenum, "Unknown replacement variable %s in format statement of %s.",
assert(false, "ShouldNotReachHere()"); rep_var, _ident);
return;
} }
OpClassForm *opc = form->is_opclass(); OpClassForm *opc = form->is_opclass();
assert( opc, "replacement variable was not found in local names"); assert( opc, "replacement variable was not found in local names");
// Lookup the index position of the replacement variable // Lookup the index position of the replacement variable
int idx = operand_position_format(rep_var); int idx = operand_position_format(rep_var);
if ( idx == -1 ) { if ( idx == -1 ) {
assert( strcmp(opc->_ident,"label")==0, "Unimplemented"); globalAD->syntax_err(_linenum, "Could not find replacement variable %s in format statement of %s.\n",
assert( false, "ShouldNotReachHere()"); rep_var, _ident);
assert(strcmp(opc->_ident, "label") == 0, "Unimplemented");
return;
} }
if (is_noninput_operand(idx)) { if (is_noninput_operand(idx)) {
@ -1273,7 +1295,7 @@ void InstructForm::rep_var_format(FILE *fp, const char *rep_var) {
OperandForm* oper = form->is_operand(); OperandForm* oper = form->is_operand();
if (oper != NULL && oper->is_bound_register()) { if (oper != NULL && oper->is_bound_register()) {
const RegDef* first = oper->get_RegClass()->find_first_elem(); const RegDef* first = oper->get_RegClass()->find_first_elem();
fprintf(fp, " tty->print(\"%s\");\n", first->_regname); fprintf(fp, " st->print(\"%s\");\n", first->_regname);
} else { } else {
globalAD->syntax_err(_linenum, "In %s can't find format for %s %s", _ident, opc->_ident, rep_var); globalAD->syntax_err(_linenum, "In %s can't find format for %s %s", _ident, opc->_ident, rep_var);
} }
@ -1373,17 +1395,19 @@ void InstructForm::index_temps(FILE *fp, FormDict &globals, const char *prefix,
if ( cur_num_opnds >= 1 ) { if ( cur_num_opnds >= 1 ) {
fprintf(fp," // Start at oper_input_base() and count operands\n"); fprintf(fp," // Start at oper_input_base() and count operands\n");
fprintf(fp," unsigned %sidx0 = %d;\n", prefix, oper_input_base(globals)); fprintf(fp," unsigned %sidx0 = %d;\n", prefix, oper_input_base(globals));
fprintf(fp," unsigned %sidx1 = %d;\n", prefix, oper_input_base(globals)); fprintf(fp," unsigned %sidx1 = %d;", prefix, oper_input_base(globals));
fprintf(fp," \t// %s\n", unique_opnd_ident(1));
// Generate starting points for other unique operands if they exist // Generate starting points for other unique operands if they exist
for ( idx = 2; idx < num_unique_opnds(); ++idx ) { for ( idx = 2; idx < num_unique_opnds(); ++idx ) {
if( *receiver == 0 ) { if( *receiver == 0 ) {
fprintf(fp," unsigned %sidx%d = %sidx%d + opnd_array(%d)->num_edges();\n", fprintf(fp," unsigned %sidx%d = %sidx%d + opnd_array(%d)->num_edges();",
prefix, idx, prefix, idx-1, idx-1 ); prefix, idx, prefix, idx-1, idx-1 );
} else { } else {
fprintf(fp," unsigned %sidx%d = %sidx%d + %s_opnds[%d]->num_edges();\n", fprintf(fp," unsigned %sidx%d = %sidx%d + %s_opnds[%d]->num_edges();",
prefix, idx, prefix, idx-1, receiver, idx-1 ); prefix, idx, prefix, idx-1, receiver, idx-1 );
} }
fprintf(fp," \t// %s\n", unique_opnd_ident(idx));
} }
} }
if( *receiver != 0 ) { if( *receiver != 0 ) {
@ -1774,9 +1798,25 @@ static int effect_lookup(const char *name) {
return Component::INVALID; return Component::INVALID;
} }
const char *Component::getUsedefName() {
switch (_usedef) {
case Component::INVALID: return "INVALID"; break;
case Component::USE: return "USE"; break;
case Component::USE_DEF: return "USE_DEF"; break;
case Component::USE_KILL: return "USE_KILL"; break;
case Component::KILL: return "KILL"; break;
case Component::TEMP: return "TEMP"; break;
case Component::DEF: return "DEF"; break;
case Component::CALL: return "CALL"; break;
default: assert(false, "unknown effect");
}
return "Undefined Use/Def info";
}
Effect::Effect(const char *name) : _name(name), _use_def(effect_lookup(name)) { Effect::Effect(const char *name) : _name(name), _use_def(effect_lookup(name)) {
_ftype = Form::EFF; _ftype = Form::EFF;
} }
Effect::~Effect() { Effect::~Effect() {
} }
@ -2273,7 +2313,7 @@ void OperandForm::build_components() {
} }
int OperandForm::operand_position(const char *name, int usedef) { int OperandForm::operand_position(const char *name, int usedef) {
return _components.operand_position(name, usedef); return _components.operand_position(name, usedef, this);
} }
@ -2399,20 +2439,20 @@ void OperandForm::int_format(FILE *fp, FormDict &globals, uint index) {
if (_matrule && (_matrule->is_base_register(globals) || if (_matrule && (_matrule->is_base_register(globals) ||
strcmp(ideal_type(globalAD->globalNames()), "RegFlags") == 0)) { strcmp(ideal_type(globalAD->globalNames()), "RegFlags") == 0)) {
// !!!!! !!!!! // !!!!! !!!!!
fprintf(fp, "{ char reg_str[128];\n"); fprintf(fp," { char reg_str[128];\n");
fprintf(fp," ra->dump_register(node,reg_str);\n"); fprintf(fp," ra->dump_register(node,reg_str);\n");
fprintf(fp," tty->print(\"%cs\",reg_str);\n",'%'); fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');
fprintf(fp," }\n"); fprintf(fp," }\n");
} else if (_matrule && (dtype = _matrule->is_base_constant(globals)) != Form::none) { } else if (_matrule && (dtype = _matrule->is_base_constant(globals)) != Form::none) {
format_constant( fp, index, dtype ); format_constant( fp, index, dtype );
} else if (ideal_to_sReg_type(_ident) != Form::none) { } else if (ideal_to_sReg_type(_ident) != Form::none) {
// Special format for Stack Slot Register // Special format for Stack Slot Register
fprintf(fp, "{ char reg_str[128];\n"); fprintf(fp," { char reg_str[128];\n");
fprintf(fp," ra->dump_register(node,reg_str);\n"); fprintf(fp," ra->dump_register(node,reg_str);\n");
fprintf(fp," tty->print(\"%cs\",reg_str);\n",'%'); fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');
fprintf(fp," }\n"); fprintf(fp," }\n");
} else { } else {
fprintf(fp,"tty->print(\"No format defined for %s\n\");\n", _ident); fprintf(fp," st->print(\"No format defined for %s\n\");\n", _ident);
fflush(fp); fflush(fp);
fprintf(stderr,"No format defined for %s\n", _ident); fprintf(stderr,"No format defined for %s\n", _ident);
dump(); dump();
@ -2426,36 +2466,37 @@ void OperandForm::ext_format(FILE *fp, FormDict &globals, uint index) {
Form::DataType dtype; Form::DataType dtype;
if (_matrule && (_matrule->is_base_register(globals) || if (_matrule && (_matrule->is_base_register(globals) ||
strcmp(ideal_type(globalAD->globalNames()), "RegFlags") == 0)) { strcmp(ideal_type(globalAD->globalNames()), "RegFlags") == 0)) {
fprintf(fp, "{ char reg_str[128];\n"); fprintf(fp," { char reg_str[128];\n");
fprintf(fp," ra->dump_register(node->in(idx"); fprintf(fp," ra->dump_register(node->in(idx");
if ( index != 0 ) fprintf(fp, "+%d",index); if ( index != 0 ) fprintf(fp, "+%d",index);
fprintf(fp, "),reg_str);\n"); fprintf(fp, "),reg_str);\n");
fprintf(fp," tty->print(\"%cs\",reg_str);\n",'%'); fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');
fprintf(fp," }\n"); fprintf(fp," }\n");
} else if (_matrule && (dtype = _matrule->is_base_constant(globals)) != Form::none) { } else if (_matrule && (dtype = _matrule->is_base_constant(globals)) != Form::none) {
format_constant( fp, index, dtype ); format_constant( fp, index, dtype );
} else if (ideal_to_sReg_type(_ident) != Form::none) { } else if (ideal_to_sReg_type(_ident) != Form::none) {
// Special format for Stack Slot Register // Special format for Stack Slot Register
fprintf(fp, "{ char reg_str[128];\n"); fprintf(fp," { char reg_str[128];\n");
fprintf(fp," ra->dump_register(node->in(idx"); fprintf(fp," ra->dump_register(node->in(idx");
if ( index != 0 ) fprintf(fp, "+%d",index); if ( index != 0 ) fprintf(fp, "+%d",index);
fprintf(fp, "),reg_str);\n"); fprintf(fp, "),reg_str);\n");
fprintf(fp," tty->print(\"%cs\",reg_str);\n",'%'); fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');
fprintf(fp," }\n"); fprintf(fp," }\n");
} else { } else {
fprintf(fp,"tty->print(\"No format defined for %s\n\");\n", _ident); fprintf(fp," st->print(\"No format defined for %s\n\");\n", _ident);
assert( false,"Internal error:\n output_external_operand() attempting to output other than a Register or Constant"); assert( false,"Internal error:\n output_external_operand() attempting to output other than a Register or Constant");
} }
} }
void OperandForm::format_constant(FILE *fp, uint const_index, uint const_type) { void OperandForm::format_constant(FILE *fp, uint const_index, uint const_type) {
switch(const_type) { switch(const_type) {
case Form::idealI: fprintf(fp,"st->print(\"#%%d\", _c%d);\n", const_index); break; case Form::idealI: fprintf(fp," st->print(\"#%%d\", _c%d);\n", const_index); break;
case Form::idealP: fprintf(fp,"_c%d->dump_on(st);\n", const_index); break; case Form::idealP: fprintf(fp," if (_c%d) _c%d->dump_on(st);\n", const_index, const_index); break;
case Form::idealN: fprintf(fp,"_c%d->dump_on(st);\n", const_index); break; case Form::idealNKlass:
case Form::idealL: fprintf(fp,"st->print(\"#%%lld\", _c%d);\n", const_index); break; case Form::idealN: fprintf(fp," if (_c%d) _c%d->dump_on(st);\n", const_index, const_index); break;
case Form::idealF: fprintf(fp,"st->print(\"#%%f\", _c%d);\n", const_index); break; case Form::idealL: fprintf(fp," st->print(\"#%%lld\", _c%d);\n", const_index); break;
case Form::idealD: fprintf(fp,"st->print(\"#%%f\", _c%d);\n", const_index); break; case Form::idealF: fprintf(fp," st->print(\"#%%f\", _c%d);\n", const_index); break;
case Form::idealD: fprintf(fp," st->print(\"#%%f\", _c%d);\n", const_index); break;
default: default:
assert( false, "ShouldNotReachHere()"); assert( false, "ShouldNotReachHere()");
} }
@ -2825,17 +2866,8 @@ void Component::output(FILE *fp) {
fprintf(fp,"Component:"); // Write to output files fprintf(fp,"Component:"); // Write to output files
fprintf(fp, " name = %s", _name); fprintf(fp, " name = %s", _name);
fprintf(fp, ", type = %s", _type); fprintf(fp, ", type = %s", _type);
const char * usedef = "Undefined Use/Def info"; assert(_usedef != 0, "unknown effect");
switch (_usedef) { fprintf(fp, ", use/def = %s\n", getUsedefName());
case USE: usedef = "USE"; break;
case USE_DEF: usedef = "USE_DEF"; break;
case USE_KILL: usedef = "USE_KILL"; break;
case KILL: usedef = "KILL"; break;
case TEMP: usedef = "TEMP"; break;
case DEF: usedef = "DEF"; break;
default: assert(false, "unknown effect");
}
fprintf(fp, ", use/def = %s\n", usedef);
} }
@ -2927,9 +2959,9 @@ int ComponentList::num_operands() {
return count; return count;
} }
// Return zero-based position in list; -1 if not in list. // Return zero-based position of operand 'name' in list; -1 if not in list.
// if parameter 'usedef' is ::USE, it will match USE, USE_DEF, ... // if parameter 'usedef' is ::USE, it will match USE, USE_DEF, ...
int ComponentList::operand_position(const char *name, int usedef) { int ComponentList::operand_position(const char *name, int usedef, Form *fm) {
PreserveIter pi(this); PreserveIter pi(this);
int position = 0; int position = 0;
int num_opnds = num_operands(); int num_opnds = num_operands();
@ -2952,10 +2984,18 @@ int ComponentList::operand_position(const char *name, int usedef) {
return position+1; return position+1;
} else { } else {
if( preceding_non_use && strcmp(component->_name, preceding_non_use->_name) ) { if( preceding_non_use && strcmp(component->_name, preceding_non_use->_name) ) {
fprintf(stderr, "the name '%s' should not precede the name '%s'\n", preceding_non_use->_name, name); fprintf(stderr, "the name '%s(%s)' should not precede the name '%s(%s)'",
preceding_non_use->_name, preceding_non_use->getUsedefName(),
name, component->getUsedefName());
if (fm && fm->is_instruction()) fprintf(stderr, "in form '%s'", fm->is_instruction()->_ident);
if (fm && fm->is_operand()) fprintf(stderr, "in form '%s'", fm->is_operand()->_ident);
fprintf(stderr, "\n");
} }
if( position >= num_opnds ) { if( position >= num_opnds ) {
fprintf(stderr, "the name '%s' is too late in its name list\n", name); fprintf(stderr, "the name '%s' is too late in its name list", name);
if (fm && fm->is_instruction()) fprintf(stderr, "in form '%s'", fm->is_instruction()->_ident);
if (fm && fm->is_operand()) fprintf(stderr, "in form '%s'", fm->is_operand()->_ident);
fprintf(stderr, "\n");
} }
assert(position < num_opnds, "advertised index in bounds"); assert(position < num_opnds, "advertised index in bounds");
return position; return position;
@ -3001,10 +3041,10 @@ int ComponentList::operand_position(const char *name) {
return Not_in_list; return Not_in_list;
} }
int ComponentList::operand_position_format(const char *name) { int ComponentList::operand_position_format(const char *name, Form *fm) {
PreserveIter pi(this); PreserveIter pi(this);
int first_position = operand_position(name); int first_position = operand_position(name);
int use_position = operand_position(name, Component::USE); int use_position = operand_position(name, Component::USE, fm);
return ((first_position < use_position) ? use_position : first_position); return ((first_position < use_position) ? use_position : first_position);
} }
@ -3267,8 +3307,8 @@ const char *MatchNode::reduce_right(FormDict &globals) const {
// If we are a "Set", start from the right child. // If we are a "Set", start from the right child.
const MatchNode *const mnode = sets_result() ? const MatchNode *const mnode = sets_result() ?
(const MatchNode *const)this->_rChild : (const MatchNode *)this->_rChild :
(const MatchNode *const)this; (const MatchNode *)this;
// If our right child exists, it is the right reduction // If our right child exists, it is the right reduction
if ( mnode->_rChild ) { if ( mnode->_rChild ) {
@ -3285,8 +3325,8 @@ const char *MatchNode::reduce_left(FormDict &globals) const {
// If we are a "Set", start from the right child. // If we are a "Set", start from the right child.
const MatchNode *const mnode = sets_result() ? const MatchNode *const mnode = sets_result() ?
(const MatchNode *const)this->_rChild : (const MatchNode *)this->_rChild :
(const MatchNode *const)this; (const MatchNode *)this;
// If our left child exists, it is the left reduction // If our left child exists, it is the left reduction
if ( mnode->_lChild ) { if ( mnode->_lChild ) {
@ -3390,9 +3430,9 @@ void MatchNode::output(FILE *fp) {
int MatchNode::needs_ideal_memory_edge(FormDict &globals) const { int MatchNode::needs_ideal_memory_edge(FormDict &globals) const {
static const char *needs_ideal_memory_list[] = { static const char *needs_ideal_memory_list[] = {
"StoreI","StoreL","StoreP","StoreN","StoreD","StoreF" , "StoreI","StoreL","StoreP","StoreN","StoreNKlass","StoreD","StoreF" ,
"StoreB","StoreC","Store" ,"StoreFP", "StoreB","StoreC","Store" ,"StoreFP",
"LoadI", "LoadUI2L", "LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" , "LoadI", "LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" ,
"LoadB" , "LoadUB", "LoadUS" ,"LoadS" ,"Load" , "LoadB" , "LoadUB", "LoadUS" ,"LoadS" ,"Load" ,
"StoreVector", "LoadVector", "StoreVector", "LoadVector",
"LoadRange", "LoadKlass", "LoadNKlass", "LoadL_unaligned", "LoadD_unaligned", "LoadRange", "LoadKlass", "LoadNKlass", "LoadL_unaligned", "LoadD_unaligned",
@ -3947,6 +3987,8 @@ int MatchRule::is_expensive() const {
strcmp(opType,"ConvL2I")==0 || strcmp(opType,"ConvL2I")==0 ||
strcmp(opType,"DecodeN")==0 || strcmp(opType,"DecodeN")==0 ||
strcmp(opType,"EncodeP")==0 || strcmp(opType,"EncodeP")==0 ||
strcmp(opType,"EncodePKlass")==0 ||
strcmp(opType,"DecodeNKlass")==0 ||
strcmp(opType,"RoundDouble")==0 || strcmp(opType,"RoundDouble")==0 ||
strcmp(opType,"RoundFloat")==0 || strcmp(opType,"RoundFloat")==0 ||
strcmp(opType,"ReverseBytesI")==0 || strcmp(opType,"ReverseBytesI")==0 ||
@ -4108,12 +4150,17 @@ void MatchRule::dump() {
output(stderr); output(stderr);
} }
void MatchRule::output(FILE *fp) { // Write just one line.
void MatchRule::output_short(FILE *fp) {
fprintf(fp,"MatchRule: ( %s",_name); fprintf(fp,"MatchRule: ( %s",_name);
if (_lChild) _lChild->output(fp); if (_lChild) _lChild->output(fp);
if (_rChild) _rChild->output(fp); if (_rChild) _rChild->output(fp);
fprintf(fp," )\n"); fprintf(fp," )");
fprintf(fp," nesting depth = %d\n", _depth); }
void MatchRule::output(FILE *fp) {
output_short(fp);
fprintf(fp,"\n nesting depth = %d\n", _depth);
if (_result) fprintf(fp," Result Type = %s", _result); if (_result) fprintf(fp," Result Type = %s", _result);
fprintf(fp,"\n"); fprintf(fp,"\n");
} }

View file

@ -76,7 +76,7 @@ class InstructForm : public Form {
private: private:
bool _ideal_only; // Not a user-defined instruction bool _ideal_only; // Not a user-defined instruction
// Members used for tracking CISC-spilling // Members used for tracking CISC-spilling
uint _cisc_spill_operand;// Which operand may cisc-spill int _cisc_spill_operand;// Which operand may cisc-spill
void set_cisc_spill_operand(uint op_index) { _cisc_spill_operand = op_index; } void set_cisc_spill_operand(uint op_index) { _cisc_spill_operand = op_index; }
bool _is_cisc_alternate; bool _is_cisc_alternate;
InstructForm *_cisc_spill_alternate;// cisc possible replacement InstructForm *_cisc_spill_alternate;// cisc possible replacement
@ -103,7 +103,7 @@ public:
RewriteRule *_rewrule; // Rewrite rule for this instruction RewriteRule *_rewrule; // Rewrite rule for this instruction
FormatRule *_format; // Format for assembly generation FormatRule *_format; // Format for assembly generation
Peephole *_peephole; // List of peephole rules for instruction Peephole *_peephole; // List of peephole rules for instruction
const char *_ins_pipe; // Instruction Scheduline description class const char *_ins_pipe; // Instruction Scheduling description class
uint *_uniq_idx; // Indexes of unique operands uint *_uniq_idx; // Indexes of unique operands
int _uniq_idx_length; // Length of _uniq_idx array int _uniq_idx_length; // Length of _uniq_idx array
@ -198,6 +198,7 @@ public:
virtual const char *cost(); // Access ins_cost attribute virtual const char *cost(); // Access ins_cost attribute
virtual uint num_opnds(); // Count of num_opnds for MachNode class virtual uint num_opnds(); // Count of num_opnds for MachNode class
// Counts USE_DEF opnds twice. See also num_unique_opnds().
virtual uint num_post_match_opnds(); virtual uint num_post_match_opnds();
virtual uint num_consts(FormDict &globals) const;// Constants in match rule virtual uint num_consts(FormDict &globals) const;// Constants in match rule
// Constants in match rule with specified type // Constants in match rule with specified type
@ -228,6 +229,7 @@ public:
// Return number of relocation entries needed for this instruction. // Return number of relocation entries needed for this instruction.
virtual uint reloc(FormDict &globals); virtual uint reloc(FormDict &globals);
const char *opnd_ident(int idx); // Name of operand #idx.
const char *reduce_result(); const char *reduce_result();
// Return the name of the operand on the right hand side of the binary match // Return the name of the operand on the right hand side of the binary match
// Return NULL if there is no right hand side // Return NULL if there is no right hand side
@ -240,7 +242,7 @@ public:
// Check if this instruction can cisc-spill to 'alternate' // Check if this instruction can cisc-spill to 'alternate'
bool cisc_spills_to(ArchDesc &AD, InstructForm *alternate); bool cisc_spills_to(ArchDesc &AD, InstructForm *alternate);
InstructForm *cisc_spill_alternate() { return _cisc_spill_alternate; } InstructForm *cisc_spill_alternate() { return _cisc_spill_alternate; }
uint cisc_spill_operand() const { return _cisc_spill_operand; } int cisc_spill_operand() const { return _cisc_spill_operand; }
bool is_cisc_alternate() const { return _is_cisc_alternate; } bool is_cisc_alternate() const { return _is_cisc_alternate; }
void set_cisc_alternate(bool val) { _is_cisc_alternate = val; } void set_cisc_alternate(bool val) { _is_cisc_alternate = val; }
const char *cisc_reg_mask_name() const { return _cisc_reg_mask_name; } const char *cisc_reg_mask_name() const { return _cisc_reg_mask_name; }
@ -277,6 +279,7 @@ public:
return idx; return idx;
} }
} }
const char *unique_opnd_ident(int idx); // Name of operand at unique idx.
// Operands which are only KILLs aren't part of the input array and // Operands which are only KILLs aren't part of the input array and
// require special handling in some cases. Their position in this // require special handling in some cases. Their position in this
@ -889,6 +892,7 @@ public:
void dump(); // Debug printer void dump(); // Debug printer
void output(FILE *fp); // Write to output files void output(FILE *fp); // Write to output files
const char* getUsedefName();
public: public:
// Implementation depends upon working bit intersection and union. // Implementation depends upon working bit intersection and union.
@ -1030,6 +1034,7 @@ public:
void matchrule_swap_commutative_op(const char* instr_ident, int count, int& match_rules_cnt); void matchrule_swap_commutative_op(const char* instr_ident, int count, int& match_rules_cnt);
void dump(); void dump();
void output_short(FILE *fp);
void output(FILE *fp); void output(FILE *fp);
}; };

View file

@ -341,14 +341,20 @@ int main(int argc, char *argv[])
static void usage(ArchDesc& AD) static void usage(ArchDesc& AD)
{ {
printf("Architecture Description Language Compiler\n\n"); printf("Architecture Description Language Compiler\n\n");
printf("Usage: adl [-doqw] [-Dflag[=def]] [-Uflag] [-cFILENAME] [-hFILENAME] [-aDFAFILE] ADLFILE\n"); printf("Usage: adlc [-doqwTs] [-#]* [-D<FLAG>[=<DEF>]] [-U<FLAG>] [-c<CPP_FILE_NAME>] [-h<HPP_FILE_NAME>] [-a<DFA_FILE_NAME>] [-v<GLOBALS_FILE_NAME>] <ADL_FILE_NAME>\n");
printf(" d produce DFA debugging info\n"); printf(" d produce DFA debugging info\n");
printf(" o no output produced, syntax and semantic checking only\n"); printf(" o no output produced, syntax and semantic checking only\n");
printf(" q quiet mode, supresses all non-essential messages\n"); printf(" q quiet mode, supresses all non-essential messages\n");
printf(" w suppress warning messages\n"); printf(" w suppress warning messages\n");
printf(" T make DFA as many subroutine calls\n");
printf(" s output which instructions are cisc-spillable\n");
printf(" D define preprocessor symbol\n");
printf(" U undefine preprocessor symbol\n");
printf(" c specify CPP file name (default: %s)\n", AD._CPP_file._name); printf(" c specify CPP file name (default: %s)\n", AD._CPP_file._name);
printf(" h specify HPP file name (default: %s)\n", AD._HPP_file._name); printf(" h specify HPP file name (default: %s)\n", AD._HPP_file._name);
printf(" a specify DFA output file name\n"); printf(" a specify DFA output file name\n");
printf(" v specify adGlobals output file name\n");
printf(" # increment ADL debug level\n");
printf("\n"); printf("\n");
} }
@ -450,22 +456,6 @@ static char *strip_ext(char *fname)
return fname; return fname;
} }
//------------------------------strip_path_and_ext------------------------------
static char *strip_path_and_ext(char *fname)
{
char *ep;
char *sp;
if (fname) {
for (sp = fname; *sp; sp++)
if (*sp == '/') fname = sp+1;
ep = fname; // start at first character and look for '.'
while (ep <= (fname + strlen(fname) - 1) && *ep != '.') ep++;
if (*ep == '.') *ep = '\0'; // truncate string at '.'
}
return fname;
}
//------------------------------base_plus_suffix------------------------------- //------------------------------base_plus_suffix-------------------------------
// New concatenated string // New concatenated string
static char *base_plus_suffix(const char* base, const char *suffix) static char *base_plus_suffix(const char* base, const char *suffix)
@ -477,18 +467,6 @@ static char *base_plus_suffix(const char* base, const char *suffix)
return fname; return fname;
} }
//------------------------------prefix_plus_base_plus_suffix-------------------
// New concatenated string
static char *prefix_plus_base_plus_suffix(const char* prefix, const char* base, const char *suffix)
{
int len = (int)strlen(prefix) + (int)strlen(base) + (int)strlen(suffix) + 1;
char* fname = new char[len];
sprintf(fname,"%s%s%s",prefix,base,suffix);
return fname;
}
//------------------------------get_legal_text--------------------------------- //------------------------------get_legal_text---------------------------------
// Get pointer to legal text at the beginning of AD file. // Get pointer to legal text at the beginning of AD file.
// This code assumes that a legal text starts at the beginning of .ad files, // This code assumes that a legal text starts at the beginning of .ad files,

View file

@ -518,6 +518,14 @@ static int pipeline_res_mask_initializer(
int cycles = piperesource->_cycles; int cycles = piperesource->_cycles;
uint stage = pipeline->_stages.index(piperesource->_stage); uint stage = pipeline->_stages.index(piperesource->_stage);
if (NameList::Not_in_list == stage) {
fprintf(stderr,
"pipeline_res_mask_initializer: "
"semantic error: "
"pipeline stage undeclared: %s\n",
piperesource->_stage);
exit(1);
}
uint upper_limit = stage+cycles-1; uint upper_limit = stage+cycles-1;
uint lower_limit = stage-1; uint lower_limit = stage-1;
uint upper_idx = upper_limit >> 5; uint upper_idx = upper_limit >> 5;
@ -1000,7 +1008,7 @@ void ArchDesc::build_pipe_classes(FILE *fp_cpp) {
} }
fprintf(fp_cpp, "};\n\n"); fprintf(fp_cpp, "};\n\n");
fprintf(fp_cpp, "#ifndef PRODUCT\n"); fprintf(fp_cpp, "#ifndef PRODUCT\n");
fprintf(fp_cpp, "void Bundle::dump() const {\n"); fprintf(fp_cpp, "void Bundle::dump(outputStream *st) const {\n");
fprintf(fp_cpp, " static const char * bundle_flags[] = {\n"); fprintf(fp_cpp, " static const char * bundle_flags[] = {\n");
fprintf(fp_cpp, " \"\",\n"); fprintf(fp_cpp, " \"\",\n");
fprintf(fp_cpp, " \"use nop delay\",\n"); fprintf(fp_cpp, " \"use nop delay\",\n");
@ -1019,22 +1027,22 @@ void ArchDesc::build_pipe_classes(FILE *fp_cpp) {
// See if the same string is in the table // See if the same string is in the table
fprintf(fp_cpp, " bool needs_comma = false;\n\n"); fprintf(fp_cpp, " bool needs_comma = false;\n\n");
fprintf(fp_cpp, " if (_flags) {\n"); fprintf(fp_cpp, " if (_flags) {\n");
fprintf(fp_cpp, " tty->print(\"%%s\", bundle_flags[_flags]);\n"); fprintf(fp_cpp, " st->print(\"%%s\", bundle_flags[_flags]);\n");
fprintf(fp_cpp, " needs_comma = true;\n"); fprintf(fp_cpp, " needs_comma = true;\n");
fprintf(fp_cpp, " };\n"); fprintf(fp_cpp, " };\n");
fprintf(fp_cpp, " if (instr_count()) {\n"); fprintf(fp_cpp, " if (instr_count()) {\n");
fprintf(fp_cpp, " tty->print(\"%%s%%d instr%%s\", needs_comma ? \", \" : \"\", instr_count(), instr_count() != 1 ? \"s\" : \"\");\n"); fprintf(fp_cpp, " st->print(\"%%s%%d instr%%s\", needs_comma ? \", \" : \"\", instr_count(), instr_count() != 1 ? \"s\" : \"\");\n");
fprintf(fp_cpp, " needs_comma = true;\n"); fprintf(fp_cpp, " needs_comma = true;\n");
fprintf(fp_cpp, " };\n"); fprintf(fp_cpp, " };\n");
fprintf(fp_cpp, " uint r = resources_used();\n"); fprintf(fp_cpp, " uint r = resources_used();\n");
fprintf(fp_cpp, " if (r) {\n"); fprintf(fp_cpp, " if (r) {\n");
fprintf(fp_cpp, " tty->print(\"%%sresource%%s:\", needs_comma ? \", \" : \"\", (r & (r-1)) != 0 ? \"s\" : \"\");\n"); fprintf(fp_cpp, " st->print(\"%%sresource%%s:\", needs_comma ? \", \" : \"\", (r & (r-1)) != 0 ? \"s\" : \"\");\n");
fprintf(fp_cpp, " for (uint i = 0; i < %d; i++)\n", _pipeline->_rescount); fprintf(fp_cpp, " for (uint i = 0; i < %d; i++)\n", _pipeline->_rescount);
fprintf(fp_cpp, " if ((r & (1 << i)) != 0)\n"); fprintf(fp_cpp, " if ((r & (1 << i)) != 0)\n");
fprintf(fp_cpp, " tty->print(\" %%s\", resource_names[i]);\n"); fprintf(fp_cpp, " st->print(\" %%s\", resource_names[i]);\n");
fprintf(fp_cpp, " needs_comma = true;\n"); fprintf(fp_cpp, " needs_comma = true;\n");
fprintf(fp_cpp, " };\n"); fprintf(fp_cpp, " };\n");
fprintf(fp_cpp, " tty->print(\"\\n\");\n"); fprintf(fp_cpp, " st->print(\"\\n\");\n");
fprintf(fp_cpp, "}\n"); fprintf(fp_cpp, "}\n");
fprintf(fp_cpp, "#endif\n"); fprintf(fp_cpp, "#endif\n");
} }
@ -1048,39 +1056,6 @@ static void defineOut_RegMask(FILE *fp, const char *node, const char *regMask) {
node, regMask); node, regMask);
} }
// Scan the peepmatch and output a test for each instruction
static void check_peepmatch_instruction_tree(FILE *fp, PeepMatch *pmatch, PeepConstraint *pconstraint) {
int parent = -1;
int inst_position = 0;
const char* inst_name = NULL;
int input = 0;
fprintf(fp, " // Check instruction sub-tree\n");
pmatch->reset();
for( pmatch->next_instruction( parent, inst_position, inst_name, input );
inst_name != NULL;
pmatch->next_instruction( parent, inst_position, inst_name, input ) ) {
// If this is not a placeholder
if( ! pmatch->is_placeholder() ) {
// Define temporaries 'inst#', based on parent and parent's input index
if( parent != -1 ) { // root was initialized
fprintf(fp, " inst%d = inst%d->in(%d);\n",
inst_position, parent, input);
}
// When not the root
// Test we have the correct instruction by comparing the rule
if( parent != -1 ) {
fprintf(fp, " matches = matches && ( inst%d->rule() == %s_rule );",
inst_position, inst_name);
}
} else {
// Check that user did not try to constrain a placeholder
assert( ! pconstraint->constrains_instruction(inst_position),
"fatal(): Can not constrain a placeholder instruction");
}
}
}
static void print_block_index(FILE *fp, int inst_position) { static void print_block_index(FILE *fp, int inst_position) {
assert( inst_position >= 0, "Instruction number less than zero"); assert( inst_position >= 0, "Instruction number less than zero");
fprintf(fp, "block_index"); fprintf(fp, "block_index");
@ -1242,7 +1217,7 @@ static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch
if( left_op_index != 0 ) { if( left_op_index != 0 ) {
assert( (left_index <= 9999) && (left_op_index <= 9999), "exceed string size"); assert( (left_index <= 9999) && (left_op_index <= 9999), "exceed string size");
// Must have index into operands // Must have index into operands
sprintf(left_reg_index,",inst%d_idx%d", left_index, left_op_index); sprintf(left_reg_index,",inst%d_idx%d", (int)left_index, left_op_index);
} else { } else {
strcpy(left_reg_index, ""); strcpy(left_reg_index, "");
} }
@ -1255,7 +1230,7 @@ static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch
if( right_op_index != 0 ) { if( right_op_index != 0 ) {
assert( (right_index <= 9999) && (right_op_index <= 9999), "exceed string size"); assert( (right_index <= 9999) && (right_op_index <= 9999), "exceed string size");
// Must have index into operands // Must have index into operands
sprintf(right_reg_index,",inst%d_idx%d", right_index, right_op_index); sprintf(right_reg_index,",inst%d_idx%d", (int)right_index, right_op_index);
} else { } else {
strcpy(right_reg_index, ""); strcpy(right_reg_index, "");
} }
@ -1645,7 +1620,7 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
new_pos = new_inst->operand_position(parameter,Component::USE); new_pos = new_inst->operand_position(parameter,Component::USE);
exp_pos += node->num_opnds(); exp_pos += node->num_opnds();
// If there is no use of the created operand, just skip it // If there is no use of the created operand, just skip it
if (new_pos != -1) { if (new_pos != NameList::Not_in_list) {
//Copy the operand from the original made above //Copy the operand from the original made above
fprintf(fp," n%d->set_opnd_array(%d, op%d->clone(C)); // %s\n", fprintf(fp," n%d->set_opnd_array(%d, op%d->clone(C)); // %s\n",
cnt, new_pos, exp_pos-node->num_opnds(), opid); cnt, new_pos, exp_pos-node->num_opnds(), opid);
@ -1789,7 +1764,8 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
// Build mapping from num_edges to local variables // Build mapping from num_edges to local variables
fprintf(fp," unsigned num0 = 0;\n"); fprintf(fp," unsigned num0 = 0;\n");
for( i = 1; i < cur_num_opnds; i++ ) { for( i = 1; i < cur_num_opnds; i++ ) {
fprintf(fp," unsigned num%d = opnd_array(%d)->num_edges();\n",i,i); fprintf(fp," unsigned num%d = opnd_array(%d)->num_edges();",i,i);
fprintf(fp, " \t// %s\n", node->opnd_ident(i));
} }
// Build a mapping from operand index to input edges // Build a mapping from operand index to input edges
fprintf(fp," unsigned idx0 = oper_input_base();\n"); fprintf(fp," unsigned idx0 = oper_input_base();\n");
@ -1934,6 +1910,7 @@ public:
} }
// Track necessary state when identifying a replacement variable // Track necessary state when identifying a replacement variable
// @arg rep_var: The formal parameter of the encoding.
void update_state(const char *rep_var) { void update_state(const char *rep_var) {
// A replacement variable or one of its subfields // A replacement variable or one of its subfields
// Obtain replacement variable from list // Obtain replacement variable from list
@ -1955,7 +1932,7 @@ public:
} }
} }
else { else {
// Lookup its position in parameter list // Lookup its position in (formal) parameter list of encoding
int param_no = _encoding.rep_var_index(rep_var); int param_no = _encoding.rep_var_index(rep_var);
if ( param_no == -1 ) { if ( param_no == -1 ) {
_AD.syntax_err( _encoding._linenum, _AD.syntax_err( _encoding._linenum,
@ -1964,6 +1941,7 @@ public:
} }
// Lookup the corresponding ins_encode parameter // Lookup the corresponding ins_encode parameter
// This is the argument (actual parameter) to the encoding.
const char *inst_rep_var = _ins_encode.rep_var_name(_inst, param_no); const char *inst_rep_var = _ins_encode.rep_var_name(_inst, param_no);
if (inst_rep_var == NULL) { if (inst_rep_var == NULL) {
_AD.syntax_err( _ins_encode._linenum, _AD.syntax_err( _ins_encode._linenum,
@ -2329,6 +2307,7 @@ private:
// Add parameter for index position, if not result operand // Add parameter for index position, if not result operand
if( _operand_idx != 0 ) fprintf(_fp,",idx%d", _operand_idx); if( _operand_idx != 0 ) fprintf(_fp,",idx%d", _operand_idx);
fprintf(_fp,")"); fprintf(_fp,")");
fprintf(_fp, "/* %s */", _operand_name);
} }
} else { } else {
assert( _reg_status == LITERAL_OUTPUT, "should have output register literal in emit_rep_var"); assert( _reg_status == LITERAL_OUTPUT, "should have output register literal in emit_rep_var");
@ -2368,7 +2347,7 @@ private:
} }
} else { } else {
assert( _constant_status == LITERAL_OUTPUT, "should have output constant literal in emit_rep_var"); assert( _constant_status == LITERAL_OUTPUT, "should have output constant literal in emit_rep_var");
// Cosntant literal has already been sent to output file, nothing more needed // Constant literal has already been sent to output file, nothing more needed
} }
} }
else if ( strcmp(rep_var,"$disp") == 0 ) { else if ( strcmp(rep_var,"$disp") == 0 ) {
@ -2387,6 +2366,8 @@ private:
} }
else { else {
printf("emit_field: %s\n",rep_var); printf("emit_field: %s\n",rep_var);
globalAD->syntax_err(_inst._linenum, "Unknown replacement variable %s in format statement of %s.",
rep_var, _inst._ident);
assert( false, "UnImplemented()"); assert( false, "UnImplemented()");
} }
} }
@ -2579,7 +2560,7 @@ void ArchDesc::defineEmit(FILE* fp, InstructForm& inst) {
} }
// (3) and (4) // (3) and (4)
fprintf(fp, "}\n"); fprintf(fp, "}\n\n");
} }
// defineEvalConstant --------------------------------------------------------- // defineEvalConstant ---------------------------------------------------------
@ -2750,15 +2731,6 @@ static void defineClone(FILE *fp, FormDict &globalNames, OperandForm &oper) {
fprintf(fp,"}\n"); fprintf(fp,"}\n");
} }
static void define_hash(FILE *fp, char *operand) {
fprintf(fp,"uint %sOper::hash() const { return 5; }\n", operand);
}
static void define_cmp(FILE *fp, char *operand) {
fprintf(fp,"uint %sOper::cmp( const MachOper &oper ) const { return opcode() == oper.opcode(); }\n", operand);
}
// Helper functions for bug 4796752, abstracted with minimal modification // Helper functions for bug 4796752, abstracted with minimal modification
// from define_oper_interface() // from define_oper_interface()
OperandForm *rep_var_to_operand(const char *encoding, OperandForm &oper, FormDict &globals) { OperandForm *rep_var_to_operand(const char *encoding, OperandForm &oper, FormDict &globals) {
@ -2852,14 +2824,14 @@ void ArchDesc::define_oper_interface(FILE *fp, OperandForm &oper, FormDict &glob
} else if ( (strcmp(name,"disp") == 0) ) { } else if ( (strcmp(name,"disp") == 0) ) {
fprintf(fp,"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n"); fprintf(fp,"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n");
} else { } else {
fprintf(fp,"() const { "); fprintf(fp,"() const { \n");
} }
// Check for hexadecimal value OR replacement variable // Check for hexadecimal value OR replacement variable
if( *encoding == '$' ) { if( *encoding == '$' ) {
// Replacement variable // Replacement variable
const char *rep_var = encoding + 1; const char *rep_var = encoding + 1;
fprintf(fp,"// Replacement variable: %s\n", encoding+1); fprintf(fp," // Replacement variable: %s\n", encoding+1);
// Lookup replacement variable, rep_var, in operand's component list // Lookup replacement variable, rep_var, in operand's component list
const Component *comp = oper._components.search(rep_var); const Component *comp = oper._components.search(rep_var);
assert( comp != NULL, "Replacement variable not found in components"); assert( comp != NULL, "Replacement variable not found in components");
@ -2880,10 +2852,10 @@ void ArchDesc::define_oper_interface(FILE *fp, OperandForm &oper, FormDict &glob
} else if ( op->ideal_to_sReg_type(op->_ident) != Form::none ) { } else if ( op->ideal_to_sReg_type(op->_ident) != Form::none ) {
// StackSlot for an sReg comes either from input node or from self, when idx==0 // StackSlot for an sReg comes either from input node or from self, when idx==0
fprintf(fp," if( idx != 0 ) {\n"); fprintf(fp," if( idx != 0 ) {\n");
fprintf(fp," // Access register number for input operand\n"); fprintf(fp," // Access stack offset (register number) for input operand\n");
fprintf(fp," return ra_->reg2offset(ra_->get_reg_first(node->in(idx)));/* sReg */\n"); fprintf(fp," return ra_->reg2offset(ra_->get_reg_first(node->in(idx)));/* sReg */\n");
fprintf(fp," }\n"); fprintf(fp," }\n");
fprintf(fp," // Access register number from myself\n"); fprintf(fp," // Access stack offset (register number) from myself\n");
fprintf(fp," return ra_->reg2offset(ra_->get_reg_first(node));/* sReg */\n"); fprintf(fp," return ra_->reg2offset(ra_->get_reg_first(node));/* sReg */\n");
} else if (op->_matrule && op->_matrule->is_base_constant(globals)) { } else if (op->_matrule && op->_matrule->is_base_constant(globals)) {
// Constant // Constant
@ -2900,7 +2872,7 @@ void ArchDesc::define_oper_interface(FILE *fp, OperandForm &oper, FormDict &glob
} }
else if( *encoding == '0' && *(encoding+1) == 'x' ) { else if( *encoding == '0' && *(encoding+1) == 'x' ) {
// Hex value // Hex value
fprintf(fp,"return %s;", encoding); fprintf(fp," return %s;\n", encoding);
} else { } else {
assert( false, "Do not support octal or decimal encode constants"); assert( false, "Do not support octal or decimal encode constants");
} }
@ -3134,7 +3106,7 @@ void ArchDesc::defineClasses(FILE *fp) {
uint reloc_size = instr->reloc(_globalNames); uint reloc_size = instr->reloc(_globalNames);
if ( reloc_size != 0 ) { if ( reloc_size != 0 ) {
fprintf(fp,"int %sNode::reloc() const {\n", instr->_ident); fprintf(fp,"int %sNode::reloc() const {\n", instr->_ident);
fprintf(fp, " return %d;\n", reloc_size ); fprintf(fp," return %d;\n", reloc_size);
fprintf(fp,"}\n"); fprintf(fp,"}\n");
fprintf(fp,"\n"); fprintf(fp,"\n");
} }
@ -3241,7 +3213,7 @@ void ArchDesc::defineClasses(FILE *fp) {
class OutputReduceOp : public OutputMap { class OutputReduceOp : public OutputMap {
public: public:
OutputReduceOp(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) OutputReduceOp(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD)
: OutputMap(hpp, cpp, globals, AD) {}; : OutputMap(hpp, cpp, globals, AD, "reduceOp") {};
void declaration() { fprintf(_hpp, "extern const int reduceOp[];\n"); } void declaration() { fprintf(_hpp, "extern const int reduceOp[];\n"); }
void definition() { fprintf(_cpp, "const int reduceOp[] = {\n"); } void definition() { fprintf(_cpp, "const int reduceOp[] = {\n"); }
@ -3276,7 +3248,7 @@ public:
class OutputLeftOp : public OutputMap { class OutputLeftOp : public OutputMap {
public: public:
OutputLeftOp(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) OutputLeftOp(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD)
: OutputMap(hpp, cpp, globals, AD) {}; : OutputMap(hpp, cpp, globals, AD, "leftOp") {};
void declaration() { fprintf(_hpp, "extern const int leftOp[];\n"); } void declaration() { fprintf(_hpp, "extern const int leftOp[];\n"); }
void definition() { fprintf(_cpp, "const int leftOp[] = {\n"); } void definition() { fprintf(_cpp, "const int leftOp[] = {\n"); }
@ -3306,7 +3278,7 @@ public:
class OutputRightOp : public OutputMap { class OutputRightOp : public OutputMap {
public: public:
OutputRightOp(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) OutputRightOp(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD)
: OutputMap(hpp, cpp, globals, AD) {}; : OutputMap(hpp, cpp, globals, AD, "rightOp") {};
void declaration() { fprintf(_hpp, "extern const int rightOp[];\n"); } void declaration() { fprintf(_hpp, "extern const int rightOp[];\n"); }
void definition() { fprintf(_cpp, "const int rightOp[] = {\n"); } void definition() { fprintf(_cpp, "const int rightOp[] = {\n"); }
@ -3336,11 +3308,11 @@ public:
class OutputRuleName : public OutputMap { class OutputRuleName : public OutputMap {
public: public:
OutputRuleName(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) OutputRuleName(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD)
: OutputMap(hpp, cpp, globals, AD) {}; : OutputMap(hpp, cpp, globals, AD, "ruleName") {};
void declaration() { fprintf(_hpp, "extern const char *ruleName[];\n"); } void declaration() { fprintf(_hpp, "extern const char *ruleName[];\n"); }
void definition() { fprintf(_cpp, "const char *ruleName[] = {\n"); } void definition() { fprintf(_cpp, "const char *ruleName[] = {\n"); }
void closing() { fprintf(_cpp, " \"no trailing comma\"\n"); void closing() { fprintf(_cpp, " \"invalid rule name\" // no trailing comma\n");
OutputMap::closing(); OutputMap::closing();
} }
void map(OpClassForm &opc) { fprintf(_cpp, " \"%s\"", _AD.machOperEnum(opc._ident) ); } void map(OpClassForm &opc) { fprintf(_cpp, " \"%s\"", _AD.machOperEnum(opc._ident) ); }
@ -3354,7 +3326,7 @@ public:
class OutputSwallowed : public OutputMap { class OutputSwallowed : public OutputMap {
public: public:
OutputSwallowed(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) OutputSwallowed(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD)
: OutputMap(hpp, cpp, globals, AD) {}; : OutputMap(hpp, cpp, globals, AD, "swallowed") {};
void declaration() { fprintf(_hpp, "extern const bool swallowed[];\n"); } void declaration() { fprintf(_hpp, "extern const bool swallowed[];\n"); }
void definition() { fprintf(_cpp, "const bool swallowed[] = {\n"); } void definition() { fprintf(_cpp, "const bool swallowed[] = {\n"); }
@ -3375,7 +3347,7 @@ public:
class OutputInstChainRule : public OutputMap { class OutputInstChainRule : public OutputMap {
public: public:
OutputInstChainRule(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) OutputInstChainRule(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD)
: OutputMap(hpp, cpp, globals, AD) {}; : OutputMap(hpp, cpp, globals, AD, "instruction_chain_rule") {};
void declaration() { fprintf(_hpp, "extern const bool instruction_chain_rule[];\n"); } void declaration() { fprintf(_hpp, "extern const bool instruction_chain_rule[];\n"); }
void definition() { fprintf(_cpp, "const bool instruction_chain_rule[] = {\n"); } void definition() { fprintf(_cpp, "const bool instruction_chain_rule[] = {\n"); }
@ -3416,7 +3388,7 @@ void ArchDesc::build_map(OutputMap &map) {
if ( op->ideal_only() ) continue; if ( op->ideal_only() ) continue;
// Generate the entry for this opcode // Generate the entry for this opcode
map.map(*op); fprintf(fp_cpp, ", // %d\n", idx); fprintf(fp_cpp, " /* %4d */", idx); map.map(*op); fprintf(fp_cpp, ",\n");
++idx; ++idx;
}; };
fprintf(fp_cpp, " // last operand\n"); fprintf(fp_cpp, " // last operand\n");
@ -3425,7 +3397,7 @@ void ArchDesc::build_map(OutputMap &map) {
map.record_position(OutputMap::BEGIN_OPCLASSES, idx ); map.record_position(OutputMap::BEGIN_OPCLASSES, idx );
_opclass.reset(); _opclass.reset();
for(; (opc = (OpClassForm*)_opclass.iter()) != NULL; ) { for(; (opc = (OpClassForm*)_opclass.iter()) != NULL; ) {
map.map(*opc); fprintf(fp_cpp, ", // %d\n", idx); fprintf(fp_cpp, " /* %4d */", idx); map.map(*opc); fprintf(fp_cpp, ",\n");
++idx; ++idx;
}; };
fprintf(fp_cpp, " // last operand class\n"); fprintf(fp_cpp, " // last operand class\n");
@ -3435,7 +3407,7 @@ void ArchDesc::build_map(OutputMap &map) {
_internalOpNames.reset(); _internalOpNames.reset();
char *name = NULL; char *name = NULL;
for(; (name = (char *)_internalOpNames.iter()) != NULL; ) { for(; (name = (char *)_internalOpNames.iter()) != NULL; ) {
map.map(name); fprintf(fp_cpp, ", // %d\n", idx); fprintf(fp_cpp, " /* %4d */", idx); map.map(name); fprintf(fp_cpp, ",\n");
++idx; ++idx;
}; };
fprintf(fp_cpp, " // last internally defined operand\n"); fprintf(fp_cpp, " // last internally defined operand\n");
@ -3453,7 +3425,7 @@ void ArchDesc::build_map(OutputMap &map) {
if ( ! inst->is_simple_chain_rule(_globalNames) ) continue; if ( ! inst->is_simple_chain_rule(_globalNames) ) continue;
if ( inst->rematerialize(_globalNames, get_registers()) ) continue; if ( inst->rematerialize(_globalNames, get_registers()) ) continue;
map.map(*inst); fprintf(fp_cpp, ", // %d\n", idx); fprintf(fp_cpp, " /* %4d */", idx); map.map(*inst); fprintf(fp_cpp, ",\n");
++idx; ++idx;
}; };
map.record_position(OutputMap::BEGIN_REMATERIALIZE, idx ); map.record_position(OutputMap::BEGIN_REMATERIALIZE, idx );
@ -3464,7 +3436,7 @@ void ArchDesc::build_map(OutputMap &map) {
if ( ! inst->is_simple_chain_rule(_globalNames) ) continue; if ( ! inst->is_simple_chain_rule(_globalNames) ) continue;
if ( ! inst->rematerialize(_globalNames, get_registers()) ) continue; if ( ! inst->rematerialize(_globalNames, get_registers()) ) continue;
map.map(*inst); fprintf(fp_cpp, ", // %d\n", idx); fprintf(fp_cpp, " /* %4d */", idx); map.map(*inst); fprintf(fp_cpp, ",\n");
++idx; ++idx;
}; };
map.record_position(OutputMap::END_INST_CHAIN_RULES, idx ); map.record_position(OutputMap::END_INST_CHAIN_RULES, idx );
@ -3478,7 +3450,7 @@ void ArchDesc::build_map(OutputMap &map) {
if ( inst->is_simple_chain_rule(_globalNames) ) continue; if ( inst->is_simple_chain_rule(_globalNames) ) continue;
if ( ! inst->rematerialize(_globalNames, get_registers()) ) continue; if ( ! inst->rematerialize(_globalNames, get_registers()) ) continue;
map.map(*inst); fprintf(fp_cpp, ", // %d\n", idx); fprintf(fp_cpp, " /* %4d */", idx); map.map(*inst); fprintf(fp_cpp, ",\n");
++idx; ++idx;
}; };
map.record_position(OutputMap::END_REMATERIALIZE, idx ); map.record_position(OutputMap::END_REMATERIALIZE, idx );
@ -3489,7 +3461,7 @@ void ArchDesc::build_map(OutputMap &map) {
if ( inst->is_simple_chain_rule(_globalNames) ) continue; if ( inst->is_simple_chain_rule(_globalNames) ) continue;
if ( inst->rematerialize(_globalNames, get_registers()) ) continue; if ( inst->rematerialize(_globalNames, get_registers()) ) continue;
map.map(*inst); fprintf(fp_cpp, ", // %d\n", idx); fprintf(fp_cpp, " /* %4d */", idx); map.map(*inst); fprintf(fp_cpp, ",\n");
++idx; ++idx;
}; };
} }
@ -3571,7 +3543,7 @@ void ArchDesc::buildReduceMaps(FILE *fp_hpp, FILE *fp_cpp) {
next = _register->iter_RegDefs(); next = _register->iter_RegDefs();
char policy = reg_save_policy(rdef->_callconv); char policy = reg_save_policy(rdef->_callconv);
const char *comma = (next != NULL) ? "," : " // no trailing comma"; const char *comma = (next != NULL) ? "," : " // no trailing comma";
fprintf(fp_cpp, " '%c'%s\n", policy, comma); fprintf(fp_cpp, " '%c'%s // %s\n", policy, comma, rdef->_regname);
} }
fprintf(fp_cpp, "};\n\n"); fprintf(fp_cpp, "};\n\n");
@ -3583,7 +3555,7 @@ void ArchDesc::buildReduceMaps(FILE *fp_hpp, FILE *fp_cpp) {
next = _register->iter_RegDefs(); next = _register->iter_RegDefs();
char policy = reg_save_policy(rdef->_c_conv); char policy = reg_save_policy(rdef->_c_conv);
const char *comma = (next != NULL) ? "," : " // no trailing comma"; const char *comma = (next != NULL) ? "," : " // no trailing comma";
fprintf(fp_cpp, " '%c'%s\n", policy, comma); fprintf(fp_cpp, " '%c'%s // %s\n", policy, comma, rdef->_regname);
} }
fprintf(fp_cpp, "};\n\n"); fprintf(fp_cpp, "};\n\n");
@ -3644,6 +3616,8 @@ static void path_to_constant(FILE *fp, FormDict &globals,
fprintf(fp, "_leaf->bottom_type()->is_ptr()"); fprintf(fp, "_leaf->bottom_type()->is_ptr()");
} else if ( (strcmp(optype,"ConN") == 0) ) { } else if ( (strcmp(optype,"ConN") == 0) ) {
fprintf(fp, "_leaf->bottom_type()->is_narrowoop()"); fprintf(fp, "_leaf->bottom_type()->is_narrowoop()");
} else if ( (strcmp(optype,"ConNKlass") == 0) ) {
fprintf(fp, "_leaf->bottom_type()->is_narrowklass()");
} else if ( (strcmp(optype,"ConF") == 0) ) { } else if ( (strcmp(optype,"ConF") == 0) ) {
fprintf(fp, "_leaf->getf()"); fprintf(fp, "_leaf->getf()");
} else if ( (strcmp(optype,"ConD") == 0) ) { } else if ( (strcmp(optype,"ConD") == 0) ) {
@ -3792,7 +3766,7 @@ void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *inden
// For each operand not in the match rule, call MachOperGenerator // For each operand not in the match rule, call MachOperGenerator
// with the enum for the opcode that needs to be built. // with the enum for the opcode that needs to be built.
ComponentList clist = inst->_components; ComponentList clist = inst->_components;
int index = clist.operand_position(comp->_name, comp->_usedef); int index = clist.operand_position(comp->_name, comp->_usedef, inst);
const char *opcode = machOperEnum(comp->_type); const char *opcode = machOperEnum(comp->_type);
fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index); fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index);
fprintf(fp_cpp, "MachOperGenerator(%s, C));\n", opcode); fprintf(fp_cpp, "MachOperGenerator(%s, C));\n", opcode);
@ -4137,6 +4111,9 @@ static int PrintAdlcCisc = 0;
// Get info for the CISC_oracle and MachNode::cisc_version() // Get info for the CISC_oracle and MachNode::cisc_version()
void ArchDesc::identify_cisc_spill_instructions() { void ArchDesc::identify_cisc_spill_instructions() {
if (_frame == NULL)
return;
// Find the user-defined operand for cisc-spilling // Find the user-defined operand for cisc-spilling
if( _frame->_cisc_spilling_operand_name != NULL ) { if( _frame->_cisc_spilling_operand_name != NULL ) {
const Form *form = _globalNames[_frame->_cisc_spilling_operand_name]; const Form *form = _globalNames[_frame->_cisc_spilling_operand_name];

View file

@ -25,6 +25,8 @@
// output_h.cpp - Class HPP file output routines for architecture definition // output_h.cpp - Class HPP file output routines for architecture definition
#include "adlc.hpp" #include "adlc.hpp"
// The comment delimiter used in format statements after assembler instructions.
#define commentSeperator "!"
// Generate the #define that describes the number of registers. // Generate the #define that describes the number of registers.
static void defineRegCount(FILE *fp, RegisterForm *registers) { static void defineRegCount(FILE *fp, RegisterForm *registers) {
@ -79,10 +81,15 @@ void ArchDesc::buildMachRegisterNumbers(FILE *fp_hpp) {
_register->reset_RegDefs(); _register->reset_RegDefs();
int i = 0; int i = 0;
while( (reg_def = _register->iter_RegDefs()) != NULL ) { while( (reg_def = _register->iter_RegDefs()) != NULL ) {
fprintf(fp_hpp," %s_num,\t\t// %d\n", reg_def->_regname, i++); fprintf(fp_hpp," %s_num,", reg_def->_regname);
for (int j = 0; j < 20-(int)strlen(reg_def->_regname); j++) fprintf(fp_hpp, " ");
fprintf(fp_hpp," // enum %3d, regnum %3d, reg encode %3s\n",
i++,
reg_def->register_num(),
reg_def->register_encode());
} }
// Finish defining enumeration // Finish defining enumeration
fprintf(fp_hpp, " _last_Mach_Reg\t// %d\n", i); fprintf(fp_hpp, " _last_Mach_Reg // %d\n", i);
fprintf(fp_hpp, "};\n"); fprintf(fp_hpp, "};\n");
} }
@ -121,13 +128,24 @@ void ArchDesc::buildMachRegisterEncodes(FILE *fp_hpp) {
fprintf(fp_hpp, "// in the order of occurrence in the alloc_class(es).\n"); fprintf(fp_hpp, "// in the order of occurrence in the alloc_class(es).\n");
fprintf(fp_hpp, "enum MachRegisterEncodes {\n"); fprintf(fp_hpp, "enum MachRegisterEncodes {\n");
// Find max enum string length.
size_t maxlen = 0;
_register->reset_RegDefs();
reg_def = _register->iter_RegDefs();
while (reg_def != NULL) {
size_t len = strlen(reg_def->_regname);
if (len > maxlen) maxlen = len;
reg_def = _register->iter_RegDefs();
}
// Output the register encoding for each register in the allocation classes // Output the register encoding for each register in the allocation classes
_register->reset_RegDefs(); _register->reset_RegDefs();
reg_def_next = _register->iter_RegDefs(); reg_def_next = _register->iter_RegDefs();
while( (reg_def = reg_def_next) != NULL ) { while( (reg_def = reg_def_next) != NULL ) {
reg_def_next = _register->iter_RegDefs(); reg_def_next = _register->iter_RegDefs();
fprintf(fp_hpp," %s_enc = %s%s\n", fprintf(fp_hpp," %s_enc", reg_def->_regname);
reg_def->_regname, reg_def->register_encode(), reg_def_next == NULL? "" : "," ); for (size_t i = strlen(reg_def->_regname); i < maxlen; i++) fprintf(fp_hpp, " ");
fprintf(fp_hpp," = %3s%s\n", reg_def->register_encode(), reg_def_next == NULL? "" : "," );
} }
// Finish defining enumeration // Finish defining enumeration
fprintf(fp_hpp, "};\n"); fprintf(fp_hpp, "};\n");
@ -177,14 +195,6 @@ static void in_RegMask(FILE *fp) {
fprintf(fp," virtual const RegMask *in_RegMask(int index) const;\n"); fprintf(fp," virtual const RegMask *in_RegMask(int index) const;\n");
} }
static void declare_hash(FILE *fp) {
fprintf(fp," virtual uint hash() const;\n");
}
static void declare_cmp(FILE *fp) {
fprintf(fp," virtual uint cmp( const MachOper &oper ) const;\n");
}
static void declareConstStorage(FILE *fp, FormDict &globals, OperandForm *oper) { static void declareConstStorage(FILE *fp, FormDict &globals, OperandForm *oper) {
int i = 0; int i = 0;
Component *comp; Component *comp;
@ -207,6 +217,10 @@ static void declareConstStorage(FILE *fp, FormDict &globals, OperandForm *oper)
if (i > 0) fprintf(fp,", "); if (i > 0) fprintf(fp,", ");
fprintf(fp," const TypeNarrowOop *_c%d;\n", i); fprintf(fp," const TypeNarrowOop *_c%d;\n", i);
} }
else if (!strcmp(type, "ConNKlass")) {
if (i > 0) fprintf(fp,", ");
fprintf(fp," const TypeNarrowKlass *_c%d;\n", i);
}
else if (!strcmp(type, "ConL")) { else if (!strcmp(type, "ConL")) {
if (i > 0) fprintf(fp,", "); if (i > 0) fprintf(fp,", ");
fprintf(fp," jlong _c%d;\n", i); fprintf(fp," jlong _c%d;\n", i);
@ -243,6 +257,10 @@ static void declareConstStorage(FILE *fp, FormDict &globals, OperandForm *oper)
fprintf(fp," const TypePtr *_c%d;\n", i); fprintf(fp," const TypePtr *_c%d;\n", i);
i++; i++;
} }
else if (!strcmp(comp->base_type(globals), "ConNKlass")) {
fprintf(fp," const TypePtr *_c%d;\n", i);
i++;
}
else if (!strcmp(comp->base_type(globals), "ConL")) { else if (!strcmp(comp->base_type(globals), "ConL")) {
fprintf(fp," jlong _c%d;\n", i); fprintf(fp," jlong _c%d;\n", i);
i++; i++;
@ -289,6 +307,7 @@ static void defineConstructor(FILE *fp, const char *name, uint num_consts,
break; break;
} }
case Form::idealN : { fprintf(fp,"const TypeNarrowOop *c%d", i); break; } case Form::idealN : { fprintf(fp,"const TypeNarrowOop *c%d", i); break; }
case Form::idealNKlass : { fprintf(fp,"const TypeNarrowKlass *c%d", i); break; }
case Form::idealP : { fprintf(fp,"const TypePtr *c%d", i); break; } case Form::idealP : { fprintf(fp,"const TypePtr *c%d", i); break; }
case Form::idealL : { fprintf(fp,"jlong c%d", i); break; } case Form::idealL : { fprintf(fp,"jlong c%d", i); break; }
case Form::idealF : { fprintf(fp,"jfloat c%d", i); break; } case Form::idealF : { fprintf(fp,"jfloat c%d", i); break; }
@ -316,6 +335,11 @@ static void defineConstructor(FILE *fp, const char *name, uint num_consts,
fprintf(fp,"const TypePtr *c%d", i); fprintf(fp,"const TypePtr *c%d", i);
i++; i++;
} }
else if (!strcmp(comp->base_type(globals), "ConNKlass")) {
if (i > 0) fprintf(fp,", ");
fprintf(fp,"const TypePtr *c%d", i);
i++;
}
else if (!strcmp(comp->base_type(globals), "ConL")) { else if (!strcmp(comp->base_type(globals), "ConL")) {
if (i > 0) fprintf(fp,", "); if (i > 0) fprintf(fp,", ");
fprintf(fp,"jlong c%d", i); fprintf(fp,"jlong c%d", i);
@ -370,6 +394,7 @@ static void defineCCodeDump(OperandForm* oper, FILE *fp, int i) {
static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i, OperandForm* oper) { static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i, OperandForm* oper) {
if (!strcmp(ideal_type, "ConI")) { if (!strcmp(ideal_type, "ConI")) {
fprintf(fp," st->print(\"#%%d\", _c%d);\n", i); fprintf(fp," st->print(\"#%%d\", _c%d);\n", i);
fprintf(fp," st->print(\"/0x%%08x\", _c%d);\n", i);
++i; ++i;
} }
else if (!strcmp(ideal_type, "ConP")) { else if (!strcmp(ideal_type, "ConP")) {
@ -380,16 +405,25 @@ static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i, Operand
fprintf(fp," _c%d->dump_on(st);\n", i); fprintf(fp," _c%d->dump_on(st);\n", i);
++i; ++i;
} }
else if (!strcmp(ideal_type, "ConNKlass")) {
fprintf(fp," _c%d->dump_on(st);\n", i);
++i;
}
else if (!strcmp(ideal_type, "ConL")) { else if (!strcmp(ideal_type, "ConL")) {
fprintf(fp," st->print(\"#\" INT64_FORMAT, _c%d);\n", i); fprintf(fp," st->print(\"#\" INT64_FORMAT, _c%d);\n", i);
fprintf(fp," st->print(\"/\" PTR64_FORMAT, _c%d);\n", i);
++i; ++i;
} }
else if (!strcmp(ideal_type, "ConF")) { else if (!strcmp(ideal_type, "ConF")) {
fprintf(fp," st->print(\"#%%f\", _c%d);\n", i); fprintf(fp," st->print(\"#%%f\", _c%d);\n", i);
fprintf(fp," jint _c%di = JavaValue(_c%d).get_jint();\n", i, i);
fprintf(fp," st->print(\"/0x%%x/\", _c%di);\n", i);
++i; ++i;
} }
else if (!strcmp(ideal_type, "ConD")) { else if (!strcmp(ideal_type, "ConD")) {
fprintf(fp," st->print(\"#%%f\", _c%d);\n", i); fprintf(fp," st->print(\"#%%f\", _c%d);\n", i);
fprintf(fp," jlong _c%dl = JavaValue(_c%d).get_jlong();\n", i, i);
fprintf(fp," st->print(\"/\" PTR64_FORMAT, _c%dl);\n", i);
++i; ++i;
} }
else if (!strcmp(ideal_type, "Bool")) { else if (!strcmp(ideal_type, "Bool")) {
@ -411,7 +445,7 @@ void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_
} }
// Local pointer indicates remaining part of format rule // Local pointer indicates remaining part of format rule
uint idx = 0; // position of operand in match rule int idx = 0; // position of operand in match rule
// Generate internal format function, used when stored locally // Generate internal format function, used when stored locally
fprintf(fp, "\n#ifndef PRODUCT\n"); fprintf(fp, "\n#ifndef PRODUCT\n");
@ -426,13 +460,12 @@ void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_
oper._format->_rep_vars.reset(); oper._format->_rep_vars.reset();
oper._format->_strings.reset(); oper._format->_strings.reset();
while ( (string = oper._format->_strings.iter()) != NULL ) { while ( (string = oper._format->_strings.iter()) != NULL ) {
fprintf(fp," ");
// Check if this is a standard string or a replacement variable // Check if this is a standard string or a replacement variable
if ( string != NameList::_signal ) { if ( string != NameList::_signal ) {
// Normal string // Normal string
// Pass through to st->print // Pass through to st->print
fprintf(fp,"st->print(\"%s\");\n", string); fprintf(fp," st->print(\"%s\");\n", string);
} else { } else {
// Replacement variable // Replacement variable
const char *rep_var = oper._format->_rep_vars.iter(); const char *rep_var = oper._format->_rep_vars.iter();
@ -498,13 +531,12 @@ void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_
oper._format->_rep_vars.reset(); oper._format->_rep_vars.reset();
oper._format->_strings.reset(); oper._format->_strings.reset();
while ( (string = oper._format->_strings.iter()) != NULL ) { while ( (string = oper._format->_strings.iter()) != NULL ) {
fprintf(fp," ");
// Check if this is a standard string or a replacement variable // Check if this is a standard string or a replacement variable
if ( string != NameList::_signal ) { if ( string != NameList::_signal ) {
// Normal string // Normal string
// Pass through to st->print // Pass through to st->print
fprintf(fp,"st->print(\"%s\");\n", string); fprintf(fp," st->print(\"%s\");\n", string);
} else { } else {
// Replacement variable // Replacement variable
const char *rep_var = oper._format->_rep_vars.iter(); const char *rep_var = oper._format->_rep_vars.iter();
@ -529,7 +561,7 @@ void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_
if ( op != NULL ) op->ext_format(fp, globals, idx); if ( op != NULL ) op->ext_format(fp, globals, idx);
// Lookup the index position of the replacement variable // Lookup the index position of the replacement variable
idx = oper._components.operand_position_format(rep_var); idx = oper._components.operand_position_format(rep_var, &oper);
if ( idx == -1 ) { if ( idx == -1 ) {
fprintf(stderr, fprintf(stderr,
"Using a name, %s, that isn't in match rule\n", rep_var); "Using a name, %s, that isn't in match rule\n", rep_var);
@ -640,10 +672,11 @@ void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &inst, bool for_c
if( call_type != Form::invalid_type ) { if( call_type != Form::invalid_type ) {
switch( call_type ) { switch( call_type ) {
case Form::JAVA_DYNAMIC: case Form::JAVA_DYNAMIC:
fprintf(fp," _method->print_short_name();\n"); fprintf(fp," _method->print_short_name(st);\n");
break; break;
case Form::JAVA_STATIC: case Form::JAVA_STATIC:
fprintf(fp," if( _method ) _method->print_short_name(st); else st->print(\" wrapper for: %%s\", _name);\n"); fprintf(fp," if( _method ) _method->print_short_name(st);\n");
fprintf(fp," else st->print(\" wrapper for: %%s\", _name);\n");
fprintf(fp," if( !_method ) dump_trap_args(st);\n"); fprintf(fp," if( !_method ) dump_trap_args(st);\n");
break; break;
case Form::JAVA_COMPILED: case Form::JAVA_COMPILED:
@ -655,18 +688,18 @@ void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &inst, bool for_c
fprintf(fp," st->print(\" %%s\", _name);"); fprintf(fp," st->print(\" %%s\", _name);");
break; break;
default: default:
assert(0,"ShouldNotReacHere"); assert(0,"ShouldNotReachHere");
} }
fprintf(fp, " st->print_cr(\"\");\n" ); fprintf(fp, " st->print_cr(\"\");\n" );
fprintf(fp, " if (_jvms) _jvms->format(ra, this, st); else st->print_cr(\" No JVM State Info\");\n" ); fprintf(fp, " if (_jvms) _jvms->format(ra, this, st); else st->print_cr(\" No JVM State Info\");\n" );
fprintf(fp, " st->print(\" # \");\n" ); fprintf(fp, " st->print(\" # \");\n" );
fprintf(fp, " if( _jvms ) _oop_map->print_on(st);\n"); fprintf(fp, " if( _jvms && _oop_map ) _oop_map->print_on(st);\n");
} }
else if(inst.is_ideal_safepoint()) { else if(inst.is_ideal_safepoint()) {
fprintf(fp, " st->print(\"\");\n" ); fprintf(fp, " st->print(\"\");\n" );
fprintf(fp, " if (_jvms) _jvms->format(ra, this, st); else st->print_cr(\" No JVM State Info\");\n" ); fprintf(fp, " if (_jvms) _jvms->format(ra, this, st); else st->print_cr(\" No JVM State Info\");\n" );
fprintf(fp, " st->print(\" # \");\n" ); fprintf(fp, " st->print(\" # \");\n" );
fprintf(fp, " if( _jvms ) _oop_map->print_on(st);\n"); fprintf(fp, " if( _jvms && _oop_map ) _oop_map->print_on(st);\n");
} }
else if( inst.is_ideal_if() ) { else if( inst.is_ideal_if() ) {
fprintf(fp, " st->print(\" P=%%f C=%%f\",_prob,_fcnt);\n" ); fprintf(fp, " st->print(\" P=%%f C=%%f\",_prob,_fcnt);\n" );
@ -675,7 +708,7 @@ void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &inst, bool for_c
// Print out the field name if available to improve readability // Print out the field name if available to improve readability
fprintf(fp, " if (ra->C->alias_type(adr_type())->field() != NULL) {\n"); fprintf(fp, " if (ra->C->alias_type(adr_type())->field() != NULL) {\n");
fprintf(fp, " ciField* f = ra->C->alias_type(adr_type())->field();\n"); fprintf(fp, " ciField* f = ra->C->alias_type(adr_type())->field();\n");
fprintf(fp, " st->print(\" ! Field: \");\n"); fprintf(fp, " st->print(\" %s Field: \");\n", commentSeperator);
fprintf(fp, " if (f->is_volatile())\n"); fprintf(fp, " if (f->is_volatile())\n");
fprintf(fp, " st->print(\"volatile \");\n"); fprintf(fp, " st->print(\"volatile \");\n");
fprintf(fp, " f->holder()->name()->print_symbol_on(st);\n"); fprintf(fp, " f->holder()->name()->print_symbol_on(st);\n");
@ -683,21 +716,15 @@ void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &inst, bool for_c
fprintf(fp, " f->name()->print_symbol_on(st);\n"); fprintf(fp, " f->name()->print_symbol_on(st);\n");
fprintf(fp, " if (f->is_constant())\n"); fprintf(fp, " if (f->is_constant())\n");
fprintf(fp, " st->print(\" (constant)\");\n"); fprintf(fp, " st->print(\" (constant)\");\n");
fprintf(fp, " } else\n"); fprintf(fp, " } else {\n");
// Make sure 'Volatile' gets printed out // Make sure 'Volatile' gets printed out
fprintf(fp, " if (ra->C->alias_type(adr_type())->is_volatile())\n"); fprintf(fp, " if (ra->C->alias_type(adr_type())->is_volatile())\n");
fprintf(fp, " st->print(\" volatile!\");\n"); fprintf(fp, " st->print(\" volatile!\");\n");
fprintf(fp, " }\n");
} }
// Complete the definition of the format function // Complete the definition of the format function
fprintf(fp, " }\n#endif\n"); fprintf(fp, "}\n#endif\n");
}
static bool is_non_constant(char* x) {
// Tells whether the string (part of an operator interface) is non-constant.
// Simply detect whether there is an occurrence of a formal parameter,
// which will always begin with '$'.
return strchr(x, '$') == 0;
} }
void ArchDesc::declare_pipe_classes(FILE *fp_hpp) { void ArchDesc::declare_pipe_classes(FILE *fp_hpp) {
@ -1089,7 +1116,7 @@ void ArchDesc::declare_pipe_classes(FILE *fp_hpp) {
fprintf(fp_hpp, " static void initialize_nops(MachNode *nop_list[%d], Compile* C);\n\n", fprintf(fp_hpp, " static void initialize_nops(MachNode *nop_list[%d], Compile* C);\n\n",
_pipeline->_nopcnt); _pipeline->_nopcnt);
fprintf(fp_hpp, "#ifndef PRODUCT\n"); fprintf(fp_hpp, "#ifndef PRODUCT\n");
fprintf(fp_hpp, " void dump() const;\n"); fprintf(fp_hpp, " void dump(outputStream *st = tty) const;\n");
fprintf(fp_hpp, "#endif\n"); fprintf(fp_hpp, "#endif\n");
fprintf(fp_hpp, "};\n\n"); fprintf(fp_hpp, "};\n\n");
@ -1239,7 +1266,7 @@ void ArchDesc::declareClasses(FILE *fp) {
if( type != NULL ) { if( type != NULL ) {
Form::DataType data_type = oper->is_base_constant(_globalNames); Form::DataType data_type = oper->is_base_constant(_globalNames);
// Check if we are an ideal pointer type // Check if we are an ideal pointer type
if( data_type == Form::idealP || data_type == Form::idealN ) { if( data_type == Form::idealP || data_type == Form::idealN || data_type == Form::idealNKlass ) {
// Return the ideal type we already have: <TypePtr *> // Return the ideal type we already have: <TypePtr *>
fprintf(fp," return _c0;"); fprintf(fp," return _c0;");
} else { } else {
@ -1377,6 +1404,16 @@ void ArchDesc::declareClasses(FILE *fp) {
fprintf(fp, " return _c0->get_ptrtype()->reloc();"); fprintf(fp, " return _c0->get_ptrtype()->reloc();");
fprintf(fp, " }\n"); fprintf(fp, " }\n");
} }
else if (!strcmp(oper->ideal_type(_globalNames), "ConNKlass")) {
// Access the locally stored constant
fprintf(fp," virtual intptr_t constant() const {");
fprintf(fp, " return _c0->get_ptrtype()->get_con();");
fprintf(fp, " }\n");
// Generate query to determine if this pointer is an oop
fprintf(fp," virtual relocInfo::relocType constant_reloc() const {");
fprintf(fp, " return _c0->get_ptrtype()->reloc();");
fprintf(fp, " }\n");
}
else if (!strcmp(oper->ideal_type(_globalNames), "ConL")) { else if (!strcmp(oper->ideal_type(_globalNames), "ConL")) {
fprintf(fp," virtual intptr_t constant() const {"); fprintf(fp," virtual intptr_t constant() const {");
// We don't support addressing modes with > 4Gig offsets. // We don't support addressing modes with > 4Gig offsets.
@ -1503,12 +1540,19 @@ void ArchDesc::declareClasses(FILE *fp) {
fprintf(fp, " GrowableArray<Label*> _index2label;\n"); fprintf(fp, " GrowableArray<Label*> _index2label;\n");
} }
fprintf(fp,"public:\n"); fprintf(fp,"public:\n");
fprintf(fp," MachOper *opnd_array(uint operand_index) const { assert(operand_index < _num_opnds, \"invalid _opnd_array index\"); return _opnd_array[operand_index]; }\n"); fprintf(fp," MachOper *opnd_array(uint operand_index) const {\n");
fprintf(fp," void set_opnd_array(uint operand_index, MachOper *operand) { assert(operand_index < _num_opnds, \"invalid _opnd_array index\"); _opnd_array[operand_index] = operand; }\n"); fprintf(fp," assert(operand_index < _num_opnds, \"invalid _opnd_array index\");\n");
fprintf(fp," return _opnd_array[operand_index];\n");
fprintf(fp," }\n");
fprintf(fp," void set_opnd_array(uint operand_index, MachOper *operand) {\n");
fprintf(fp," assert(operand_index < _num_opnds, \"invalid _opnd_array index\");\n");
fprintf(fp," _opnd_array[operand_index] = operand;\n");
fprintf(fp," }\n");
fprintf(fp,"private:\n"); fprintf(fp,"private:\n");
if ( instr->is_ideal_jump() ) { if ( instr->is_ideal_jump() ) {
fprintf(fp," virtual void add_case_label(int index_num, Label* blockLabel) {\n"); fprintf(fp," virtual void add_case_label(int index_num, Label* blockLabel) {\n");
fprintf(fp," _index2label.at_put_grow(index_num, blockLabel);}\n"); fprintf(fp," _index2label.at_put_grow(index_num, blockLabel);\n");
fprintf(fp," }\n");
} }
if( can_cisc_spill() && (instr->cisc_spill_alternate() != NULL) ) { if( can_cisc_spill() && (instr->cisc_spill_alternate() != NULL) ) {
fprintf(fp," const RegMask *_cisc_RegMask;\n"); fprintf(fp," const RegMask *_cisc_RegMask;\n");
@ -1803,13 +1847,14 @@ void ArchDesc::declareClasses(FILE *fp) {
// as is done for pointers // as is done for pointers
// //
// Construct appropriate constant type containing the constant value. // Construct appropriate constant type containing the constant value.
fprintf(fp," virtual const class Type *bottom_type() const{\n"); fprintf(fp," virtual const class Type *bottom_type() const {\n");
switch( data_type ) { switch( data_type ) {
case Form::idealI: case Form::idealI:
fprintf(fp," return TypeInt::make(opnd_array(1)->constant());\n"); fprintf(fp," return TypeInt::make(opnd_array(1)->constant());\n");
break; break;
case Form::idealP: case Form::idealP:
case Form::idealN: case Form::idealN:
case Form::idealNKlass:
fprintf(fp," return opnd_array(1)->type();\n"); fprintf(fp," return opnd_array(1)->type();\n");
break; break;
case Form::idealD: case Form::idealD:
@ -1833,7 +1878,7 @@ void ArchDesc::declareClasses(FILE *fp) {
// !!!!! !!!!! // !!!!! !!!!!
// Provide explicit bottom type for conversions to int // Provide explicit bottom type for conversions to int
// On Intel the result operand is a stackSlot, untyped. // On Intel the result operand is a stackSlot, untyped.
fprintf(fp," virtual const class Type *bottom_type() const{"); fprintf(fp," virtual const class Type *bottom_type() const {");
fprintf(fp, " return TypeInt::INT;"); fprintf(fp, " return TypeInt::INT;");
fprintf(fp, " };\n"); fprintf(fp, " };\n");
}*/ }*/
@ -1854,7 +1899,7 @@ void ArchDesc::declareClasses(FILE *fp) {
// BoxNode provides the address of a stack slot. // BoxNode provides the address of a stack slot.
// Define its bottom type to be TypeRawPtr::BOTTOM instead of TypePtr::BOTTOM // Define its bottom type to be TypeRawPtr::BOTTOM instead of TypePtr::BOTTOM
// This prevent s insert_anti_dependencies from complaining. It will // This prevent s insert_anti_dependencies from complaining. It will
// complain if it see that the pointer base is TypePtr::BOTTOM since // complain if it sees that the pointer base is TypePtr::BOTTOM since
// it doesn't understand what that might alias. // it doesn't understand what that might alias.
fprintf(fp," const Type *bottom_type() const { return TypeRawPtr::BOTTOM; } // Box?\n"); fprintf(fp," const Type *bottom_type() const { return TypeRawPtr::BOTTOM; } // Box?\n");
} }
@ -2017,7 +2062,7 @@ void ArchDesc::defineStateClass(FILE *fp) {
class OutputMachOperands : public OutputMap { class OutputMachOperands : public OutputMap {
public: public:
OutputMachOperands(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) OutputMachOperands(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD)
: OutputMap(hpp, cpp, globals, AD) {}; : OutputMap(hpp, cpp, globals, AD, "MachOperands") {};
void declaration() { } void declaration() { }
void definition() { fprintf(_cpp, "enum MachOperands {\n"); } void definition() { fprintf(_cpp, "enum MachOperands {\n"); }
@ -2052,7 +2097,7 @@ class OutputMachOpcodes : public OutputMap {
int end_instructions; int end_instructions;
public: public:
OutputMachOpcodes(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD) OutputMachOpcodes(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD)
: OutputMap(hpp, cpp, globals, AD), : OutputMap(hpp, cpp, globals, AD, "MachOpcodes"),
begin_inst_chain_rule(-1), end_inst_chain_rule(-1), end_instructions(-1) begin_inst_chain_rule(-1), end_inst_chain_rule(-1), end_instructions(-1)
{}; {};

View file

@ -32,6 +32,7 @@
#include "c1/c1_ValueMap.hpp" #include "c1/c1_ValueMap.hpp"
#include "c1/c1_ValueStack.hpp" #include "c1/c1_ValueStack.hpp"
#include "code/debugInfoRec.hpp" #include "code/debugInfoRec.hpp"
#include "compiler/compileLog.hpp"
typedef enum { typedef enum {
@ -67,10 +68,25 @@ static int totalInstructionNodes = 0;
class PhaseTraceTime: public TraceTime { class PhaseTraceTime: public TraceTime {
private: private:
JavaThread* _thread; JavaThread* _thread;
CompileLog* _log;
public: public:
PhaseTraceTime(TimerName timer): PhaseTraceTime(TimerName timer)
TraceTime("", &timers[timer], CITime || CITimeEach, Verbose) { : TraceTime("", &timers[timer], CITime || CITimeEach, Verbose), _log(NULL) {
if (Compilation::current() != NULL) {
_log = Compilation::current()->log();
}
if (_log != NULL) {
_log->begin_head("phase name='%s'", timer_name[timer]);
_log->stamp();
_log->end_head();
}
}
~PhaseTraceTime() {
if (_log != NULL)
_log->done("phase");
} }
}; };
@ -390,6 +406,10 @@ void Compilation::compile_method() {
PhaseTraceTime timeit(_t_codeinstall); PhaseTraceTime timeit(_t_codeinstall);
install_code(frame_size); install_code(frame_size);
} }
if (log() != NULL) // Print code cache state into compiler log
log()->code_cache_state();
totalInstructionNodes += Instruction::number_of_instructions(); totalInstructionNodes += Instruction::number_of_instructions();
} }
@ -456,6 +476,7 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho
int osr_bci, BufferBlob* buffer_blob) int osr_bci, BufferBlob* buffer_blob)
: _compiler(compiler) : _compiler(compiler)
, _env(env) , _env(env)
, _log(env->log())
, _method(method) , _method(method)
, _osr_bci(osr_bci) , _osr_bci(osr_bci)
, _hir(NULL) , _hir(NULL)

View file

@ -66,6 +66,7 @@ class Compilation: public StackObj {
int _next_block_id; int _next_block_id;
AbstractCompiler* _compiler; AbstractCompiler* _compiler;
ciEnv* _env; ciEnv* _env;
CompileLog* _log;
ciMethod* _method; ciMethod* _method;
int _osr_bci; int _osr_bci;
IR* _hir; IR* _hir;
@ -123,6 +124,7 @@ class Compilation: public StackObj {
// accessors // accessors
ciEnv* env() const { return _env; } ciEnv* env() const { return _env; }
CompileLog* log() const { return _log; }
AbstractCompiler* compiler() const { return _compiler; } AbstractCompiler* compiler() const { return _compiler; }
bool has_exception_handlers() const { return _has_exception_handlers; } bool has_exception_handlers() const { return _has_exception_handlers; }
bool has_fpu_code() const { return _has_fpu_code; } bool has_fpu_code() const { return _has_fpu_code; }

View file

@ -1682,6 +1682,12 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder); ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder);
ciInstanceKlass* actual_recv = callee_holder; ciInstanceKlass* actual_recv = callee_holder;
CompileLog* log = compilation()->log();
if (log != NULL)
log->elem("call method='%d' instr='%s'",
log->identify(target),
Bytecodes::name(code));
// Some methods are obviously bindable without any type checks so // Some methods are obviously bindable without any type checks so
// convert them directly to an invokespecial or invokestatic. // convert them directly to an invokespecial or invokestatic.
if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) { if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) {
@ -1826,6 +1832,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
} }
code = Bytecodes::_invokespecial; code = Bytecodes::_invokespecial;
} }
// check if we could do inlining // check if we could do inlining
if (!PatchALot && Inline && klass->is_loaded() && if (!PatchALot && Inline && klass->is_loaded() &&
(klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized()) (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized())
@ -2448,6 +2455,7 @@ BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) {
#endif #endif
_skip_block = false; _skip_block = false;
assert(state() != NULL, "ValueStack missing!"); assert(state() != NULL, "ValueStack missing!");
CompileLog* log = compilation()->log();
ciBytecodeStream s(method()); ciBytecodeStream s(method());
s.reset_to_bci(bci); s.reset_to_bci(bci);
int prev_bci = bci; int prev_bci = bci;
@ -2466,6 +2474,9 @@ BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) {
(block_at(s.cur_bci()) == NULL || block_at(s.cur_bci()) == block())) { (block_at(s.cur_bci()) == NULL || block_at(s.cur_bci()) == block())) {
assert(state()->kind() == ValueStack::Parsing, "invalid state kind"); assert(state()->kind() == ValueStack::Parsing, "invalid state kind");
if (log != NULL)
log->set_context("bc code='%d' bci='%d'", (int)code, s.cur_bci());
// Check for active jsr during OSR compilation // Check for active jsr during OSR compilation
if (compilation()->is_osr_compile() if (compilation()->is_osr_compile()
&& scope()->is_top_scope() && scope()->is_top_scope()
@ -2686,8 +2697,13 @@ BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) {
case Bytecodes::_breakpoint : BAILOUT_("concurrent setting of breakpoint", NULL); case Bytecodes::_breakpoint : BAILOUT_("concurrent setting of breakpoint", NULL);
default : ShouldNotReachHere(); break; default : ShouldNotReachHere(); break;
} }
if (log != NULL)
log->clear_context(); // skip marker if nothing was printed
// save current bci to setup Goto at the end // save current bci to setup Goto at the end
prev_bci = s.cur_bci(); prev_bci = s.cur_bci();
} }
CHECK_BAILOUT_(NULL); CHECK_BAILOUT_(NULL);
// stop processing of this block (see try_inline_full) // stop processing of this block (see try_inline_full)
@ -3667,7 +3683,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode
INLINE_BAILOUT("total inlining greater than DesiredMethodLimit"); INLINE_BAILOUT("total inlining greater than DesiredMethodLimit");
} }
// printing // printing
print_inlining(callee, ""); print_inlining(callee);
} }
// NOTE: Bailouts from this point on, which occur at the // NOTE: Bailouts from this point on, which occur at the
@ -4133,8 +4149,19 @@ void GraphBuilder::append_unsafe_CAS(ciMethod* callee) {
void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool success) { void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool success) {
CompileLog* log = compilation()->log();
if (log != NULL) {
if (success) {
if (msg != NULL)
log->inline_success(msg);
else
log->inline_success("receiver is statically known");
} else {
log->inline_fail(msg);
}
}
if (!PrintInlining) return; if (!PrintInlining) return;
assert(msg != NULL, "must be");
CompileTask::print_inlining(callee, scope()->level(), bci(), msg); CompileTask::print_inlining(callee, scope()->level(), bci(), msg);
if (success && CIPrintMethodCodes) { if (success && CIPrintMethodCodes) {
callee->print_codes(); callee->print_codes();

View file

@ -31,6 +31,7 @@
#include "c1/c1_ValueStack.hpp" #include "c1/c1_ValueStack.hpp"
#include "ci/ciMethodData.hpp" #include "ci/ciMethodData.hpp"
#include "ci/ciStreams.hpp" #include "ci/ciStreams.hpp"
#include "compiler/compileLog.hpp"
class MemoryBuffer; class MemoryBuffer;
@ -369,7 +370,7 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
void append_unsafe_CAS(ciMethod* callee); void append_unsafe_CAS(ciMethod* callee);
bool append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add); bool append_unsafe_get_and_set_obj(ciMethod* callee, bool is_add);
void print_inlining(ciMethod* callee, const char* msg, bool success = true); void print_inlining(ciMethod* callee, const char* msg = NULL, bool success = true);
void profile_call(ciMethod* callee, Value recv, ciKlass* predicted_holder); void profile_call(ciMethod* callee, Value recv, ciKlass* predicted_holder);
void profile_invocation(ciMethod* inlinee, ValueStack* state); void profile_invocation(ciMethod* inlinee, ValueStack* state);

View file

@ -1286,7 +1286,7 @@ void LIRGenerator::do_getClass(Intrinsic* x) {
if (x->needs_null_check()) { if (x->needs_null_check()) {
info = state_for(x); info = state_for(x);
} }
__ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), UseCompressedKlassPointers ? T_OBJECT : T_ADDRESS), result, info); __ move(new LIR_Address(rcvr.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), result, info);
__ move_wide(new LIR_Address(result, in_bytes(Klass::java_mirror_offset()), T_OBJECT), result); __ move_wide(new LIR_Address(result, in_bytes(Klass::java_mirror_offset()), T_OBJECT), result);
} }

View file

@ -29,6 +29,7 @@
#include "c1/c1_ValueSet.hpp" #include "c1/c1_ValueSet.hpp"
#include "c1/c1_ValueStack.hpp" #include "c1/c1_ValueStack.hpp"
#include "utilities/bitMap.inline.hpp" #include "utilities/bitMap.inline.hpp"
#include "compiler/compileLog.hpp"
define_array(ValueSetArray, ValueSet*); define_array(ValueSetArray, ValueSet*);
define_stack(ValueSetList, ValueSetArray); define_stack(ValueSetList, ValueSetArray);
@ -54,7 +55,18 @@ class CE_Eliminator: public BlockClosure {
// substituted some ifops/phis, so resolve the substitution // substituted some ifops/phis, so resolve the substitution
SubstitutionResolver sr(_hir); SubstitutionResolver sr(_hir);
} }
CompileLog* log = _hir->compilation()->log();
if (log != NULL)
log->set_context("optimize name='cee'");
} }
~CE_Eliminator() {
CompileLog* log = _hir->compilation()->log();
if (log != NULL)
log->clear_context(); // skip marker if nothing was printed
}
int cee_count() const { return _cee_count; } int cee_count() const { return _cee_count; }
int ifop_count() const { return _ifop_count; } int ifop_count() const { return _ifop_count; }
@ -306,6 +318,15 @@ class BlockMerger: public BlockClosure {
, _merge_count(0) , _merge_count(0)
{ {
_hir->iterate_preorder(this); _hir->iterate_preorder(this);
CompileLog* log = _hir->compilation()->log();
if (log != NULL)
log->set_context("optimize name='eliminate_blocks'");
}
~BlockMerger() {
CompileLog* log = _hir->compilation()->log();
if (log != NULL)
log->clear_context(); // skip marker if nothing was printed
} }
bool try_merge(BlockBegin* block) { bool try_merge(BlockBegin* block) {
@ -574,6 +595,15 @@ class NullCheckEliminator: public ValueVisitor {
, _work_list(new BlockList()) { , _work_list(new BlockList()) {
_visitable_instructions = new ValueSet(); _visitable_instructions = new ValueSet();
_visitor.set_eliminator(this); _visitor.set_eliminator(this);
CompileLog* log = _opt->ir()->compilation()->log();
if (log != NULL)
log->set_context("optimize name='null_check_elimination'");
}
~NullCheckEliminator() {
CompileLog* log = _opt->ir()->compilation()->log();
if (log != NULL)
log->clear_context(); // skip marker if nothing was printed
} }
Optimizer* opt() { return _opt; } Optimizer* opt() { return _opt; }

View file

@ -1126,7 +1126,8 @@ void ciEnv::record_method_not_compilable(const char* reason, bool all_tiers) {
if (all_tiers) { if (all_tiers) {
log()->elem("method_not_compilable"); log()->elem("method_not_compilable");
} else { } else {
log()->elem("method_not_compilable_at_tier"); log()->elem("method_not_compilable_at_tier level='%d'",
current()->task()->comp_level());
} }
} }
_compilable = new_compilable; _compilable = new_compilable;

View file

@ -146,7 +146,7 @@ void ciObjectFactory::init_shared_objects() {
for (int i = T_BOOLEAN; i <= T_CONFLICT; i++) { for (int i = T_BOOLEAN; i <= T_CONFLICT; i++) {
BasicType t = (BasicType)i; BasicType t = (BasicType)i;
if (type2name(t) != NULL && t != T_OBJECT && t != T_ARRAY && t != T_NARROWOOP) { if (type2name(t) != NULL && t != T_OBJECT && t != T_ARRAY && t != T_NARROWOOP && t != T_NARROWKLASS) {
ciType::_basic_types[t] = new (_arena) ciType(t); ciType::_basic_types[t] = new (_arena) ciType(t);
init_ident_of(ciType::_basic_types[t]); init_ident_of(ciType::_basic_types[t]);
} }

View file

@ -816,9 +816,6 @@ Array<Klass*>* ClassFileParser::parse_interfaces(constantPoolHandle cp,
unresolved_klass, class_loader, protection_domain, unresolved_klass, class_loader, protection_domain,
false, CHECK_NULL); false, CHECK_NULL);
interf = KlassHandle(THREAD, k); interf = KlassHandle(THREAD, k);
if (LinkWellKnownClasses) // my super type is well known to me
cp->klass_at_put(interface_index, interf()); // eagerly resolve
} }
if (!Klass::cast(interf())->is_interface()) { if (!Klass::cast(interf())->is_interface()) {
@ -1020,9 +1017,10 @@ static FieldAllocationType _basic_type_to_atype[2 * (T_CONFLICT + 1)] = {
NONSTATIC_OOP, // T_ARRAY = 13, NONSTATIC_OOP, // T_ARRAY = 13,
BAD_ALLOCATION_TYPE, // T_VOID = 14, BAD_ALLOCATION_TYPE, // T_VOID = 14,
BAD_ALLOCATION_TYPE, // T_ADDRESS = 15, BAD_ALLOCATION_TYPE, // T_ADDRESS = 15,
BAD_ALLOCATION_TYPE, // T_NARROWOOP= 16, BAD_ALLOCATION_TYPE, // T_NARROWOOP = 16,
BAD_ALLOCATION_TYPE, // T_METADATA = 17, BAD_ALLOCATION_TYPE, // T_METADATA = 17,
BAD_ALLOCATION_TYPE, // T_CONFLICT = 18, BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 18,
BAD_ALLOCATION_TYPE, // T_CONFLICT = 19,
BAD_ALLOCATION_TYPE, // 0 BAD_ALLOCATION_TYPE, // 0
BAD_ALLOCATION_TYPE, // 1 BAD_ALLOCATION_TYPE, // 1
BAD_ALLOCATION_TYPE, // 2 BAD_ALLOCATION_TYPE, // 2
@ -1039,9 +1037,10 @@ static FieldAllocationType _basic_type_to_atype[2 * (T_CONFLICT + 1)] = {
STATIC_OOP, // T_ARRAY = 13, STATIC_OOP, // T_ARRAY = 13,
BAD_ALLOCATION_TYPE, // T_VOID = 14, BAD_ALLOCATION_TYPE, // T_VOID = 14,
BAD_ALLOCATION_TYPE, // T_ADDRESS = 15, BAD_ALLOCATION_TYPE, // T_ADDRESS = 15,
BAD_ALLOCATION_TYPE, // T_NARROWOOP= 16, BAD_ALLOCATION_TYPE, // T_NARROWOOP = 16,
BAD_ALLOCATION_TYPE, // T_METADATA = 17, BAD_ALLOCATION_TYPE, // T_METADATA = 17,
BAD_ALLOCATION_TYPE, // T_CONFLICT = 18, BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 18,
BAD_ALLOCATION_TYPE, // T_CONFLICT = 19,
}; };
static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type) { static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type) {
@ -3192,8 +3191,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
KlassHandle kh (THREAD, k); KlassHandle kh (THREAD, k);
super_klass = instanceKlassHandle(THREAD, kh()); super_klass = instanceKlassHandle(THREAD, kh());
if (LinkWellKnownClasses) // my super class is well known to me
cp->klass_at_put(super_class_index, super_klass()); // eagerly resolve
} }
if (super_klass.not_null()) { if (super_klass.not_null()) {
if (super_klass->is_interface()) { if (super_klass->is_interface()) {
@ -3639,7 +3636,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// has to be changed accordingly. // has to be changed accordingly.
this_klass->set_initial_method_idnum(methods->length()); this_klass->set_initial_method_idnum(methods->length());
this_klass->set_name(cp->klass_name_at(this_class_index)); this_klass->set_name(cp->klass_name_at(this_class_index));
if (LinkWellKnownClasses || is_anonymous()) // I am well known to myself if (is_anonymous()) // I am well known to myself
cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve
if (fields_annotations != NULL || if (fields_annotations != NULL ||

View file

@ -344,7 +344,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
// constant pool construction, but in later versions they can. // constant pool construction, but in later versions they can.
// %%% Let's phase out the old is_klass_reference. // %%% Let's phase out the old is_klass_reference.
bool is_klass_reference(constantPoolHandle cp, int index) { bool is_klass_reference(constantPoolHandle cp, int index) {
return ((LinkWellKnownClasses || EnableInvokeDynamic) return (EnableInvokeDynamic
? cp->tag_at(index).is_klass_or_reference() ? cp->tag_at(index).is_klass_or_reference()
: cp->tag_at(index).is_klass_reference()); : cp->tag_at(index).is_klass_reference());
} }

View file

@ -291,16 +291,6 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
Handle protection_domain, Handle protection_domain,
bool is_superclass, bool is_superclass,
TRAPS) { TRAPS) {
// Try to get one of the well-known klasses.
// They are trusted, and do not participate in circularities.
if (LinkWellKnownClasses) {
Klass* k = find_well_known_klass(class_name);
if (k != NULL) {
return k;
}
}
// Double-check, if child class is already loaded, just return super-class,interface // Double-check, if child class is already loaded, just return super-class,interface
// Don't add a placedholder if already loaded, i.e. already in system dictionary // Don't add a placedholder if already loaded, i.e. already in system dictionary
// Make sure there's a placeholder for the *child* before resolving. // Make sure there's a placeholder for the *child* before resolving.
@ -926,14 +916,6 @@ Klass* SystemDictionary::find_instance_or_array_klass(Symbol* class_name,
Klass* k = NULL; Klass* k = NULL;
assert(class_name != NULL, "class name must be non NULL"); assert(class_name != NULL, "class name must be non NULL");
// Try to get one of the well-known klasses.
if (LinkWellKnownClasses) {
k = find_well_known_klass(class_name);
if (k != NULL) {
return k;
}
}
if (FieldType::is_array(class_name)) { if (FieldType::is_array(class_name)) {
// The name refers to an array. Parse the name. // The name refers to an array. Parse the name.
// dimension and object_key in FieldArrayInfo are assigned as a // dimension and object_key in FieldArrayInfo are assigned as a
@ -954,38 +936,6 @@ Klass* SystemDictionary::find_instance_or_array_klass(Symbol* class_name,
return k; return k;
} }
// Quick range check for names of well-known classes:
static Symbol* wk_klass_name_limits[2] = {NULL, NULL};
#ifndef PRODUCT
static int find_wkk_calls, find_wkk_probes, find_wkk_wins;
// counts for "hello world": 3983, 1616, 1075
// => 60% hit after limit guard, 25% total win rate
#endif
Klass* SystemDictionary::find_well_known_klass(Symbol* class_name) {
// A bounds-check on class_name will quickly get a negative result.
NOT_PRODUCT(find_wkk_calls++);
if (class_name >= wk_klass_name_limits[0] &&
class_name <= wk_klass_name_limits[1]) {
NOT_PRODUCT(find_wkk_probes++);
vmSymbols::SID sid = vmSymbols::find_sid(class_name);
if (sid != vmSymbols::NO_SID) {
Klass* k = NULL;
switch (sid) {
#define WK_KLASS_CASE(name, symbol, ignore_option) \
case vmSymbols::VM_SYMBOL_ENUM_NAME(symbol): \
k = WK_KLASS(name); break;
WK_KLASSES_DO(WK_KLASS_CASE)
#undef WK_KLASS_CASE
}
NOT_PRODUCT(if (k != NULL) find_wkk_wins++);
return k;
}
}
return NULL;
}
// Note: this method is much like resolve_from_stream, but // Note: this method is much like resolve_from_stream, but
// updates no supplemental data structures. // updates no supplemental data structures.
// TODO consolidate the two methods with a helper routine? // TODO consolidate the two methods with a helper routine?
@ -1939,23 +1889,12 @@ void SystemDictionary::initialize_wk_klasses_until(WKID limit_id, WKID &start_id
int opt = (info & right_n_bits(CEIL_LG_OPTION_LIMIT)); int opt = (info & right_n_bits(CEIL_LG_OPTION_LIMIT));
initialize_wk_klass((WKID)id, opt, CHECK); initialize_wk_klass((WKID)id, opt, CHECK);
// Update limits, so find_well_known_klass can be very fast:
Symbol* s = vmSymbols::symbol_at((vmSymbols::SID)sid);
if (wk_klass_name_limits[1] == NULL) {
wk_klass_name_limits[0] = wk_klass_name_limits[1] = s;
} else if (wk_klass_name_limits[1] < s) {
wk_klass_name_limits[1] = s;
} else if (wk_klass_name_limits[0] > s) {
wk_klass_name_limits[0] = s;
}
} }
// move the starting value forward to the limit: // move the starting value forward to the limit:
start_id = limit_id; start_id = limit_id;
} }
void SystemDictionary::initialize_preloaded_classes(TRAPS) { void SystemDictionary::initialize_preloaded_classes(TRAPS) {
assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once"); assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once");
// Preload commonly used klasses // Preload commonly used klasses

View file

@ -92,93 +92,93 @@ class SymbolPropertyTable;
// The order of these definitions is significant; it is the order in which // The order of these definitions is significant; it is the order in which
// preloading is actually performed by initialize_preloaded_classes. // preloading is actually performed by initialize_preloaded_classes.
#define WK_KLASSES_DO(template) \ #define WK_KLASSES_DO(do_klass) \
/* well-known classes */ \ /* well-known classes */ \
template(Object_klass, java_lang_Object, Pre) \ do_klass(Object_klass, java_lang_Object, Pre ) \
template(String_klass, java_lang_String, Pre) \ do_klass(String_klass, java_lang_String, Pre ) \
template(Class_klass, java_lang_Class, Pre) \ do_klass(Class_klass, java_lang_Class, Pre ) \
template(Cloneable_klass, java_lang_Cloneable, Pre) \ do_klass(Cloneable_klass, java_lang_Cloneable, Pre ) \
template(ClassLoader_klass, java_lang_ClassLoader, Pre) \ do_klass(ClassLoader_klass, java_lang_ClassLoader, Pre ) \
template(Serializable_klass, java_io_Serializable, Pre) \ do_klass(Serializable_klass, java_io_Serializable, Pre ) \
template(System_klass, java_lang_System, Pre) \ do_klass(System_klass, java_lang_System, Pre ) \
template(Throwable_klass, java_lang_Throwable, Pre) \ do_klass(Throwable_klass, java_lang_Throwable, Pre ) \
template(Error_klass, java_lang_Error, Pre) \ do_klass(Error_klass, java_lang_Error, Pre ) \
template(ThreadDeath_klass, java_lang_ThreadDeath, Pre) \ do_klass(ThreadDeath_klass, java_lang_ThreadDeath, Pre ) \
template(Exception_klass, java_lang_Exception, Pre) \ do_klass(Exception_klass, java_lang_Exception, Pre ) \
template(RuntimeException_klass, java_lang_RuntimeException, Pre) \ do_klass(RuntimeException_klass, java_lang_RuntimeException, Pre ) \
template(ProtectionDomain_klass, java_security_ProtectionDomain, Pre) \ do_klass(ProtectionDomain_klass, java_security_ProtectionDomain, Pre ) \
template(AccessControlContext_klass, java_security_AccessControlContext, Pre) \ do_klass(AccessControlContext_klass, java_security_AccessControlContext, Pre ) \
template(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \ do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre ) \
template(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \ do_klass(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre ) \
template(LinkageError_klass, java_lang_LinkageError, Pre) \ do_klass(LinkageError_klass, java_lang_LinkageError, Pre ) \
template(ClassCastException_klass, java_lang_ClassCastException, Pre) \ do_klass(ClassCastException_klass, java_lang_ClassCastException, Pre ) \
template(ArrayStoreException_klass, java_lang_ArrayStoreException, Pre) \ do_klass(ArrayStoreException_klass, java_lang_ArrayStoreException, Pre ) \
template(VirtualMachineError_klass, java_lang_VirtualMachineError, Pre) \ do_klass(VirtualMachineError_klass, java_lang_VirtualMachineError, Pre ) \
template(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre) \ do_klass(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre ) \
template(StackOverflowError_klass, java_lang_StackOverflowError, Pre) \ do_klass(StackOverflowError_klass, java_lang_StackOverflowError, Pre ) \
template(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, Pre) \ do_klass(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, Pre ) \
template(Reference_klass, java_lang_ref_Reference, Pre) \ do_klass(Reference_klass, java_lang_ref_Reference, Pre ) \
\ \
/* Preload ref klasses and set reference types */ \ /* Preload ref klasses and set reference types */ \
template(SoftReference_klass, java_lang_ref_SoftReference, Pre) \ do_klass(SoftReference_klass, java_lang_ref_SoftReference, Pre ) \
template(WeakReference_klass, java_lang_ref_WeakReference, Pre) \ do_klass(WeakReference_klass, java_lang_ref_WeakReference, Pre ) \
template(FinalReference_klass, java_lang_ref_FinalReference, Pre) \ do_klass(FinalReference_klass, java_lang_ref_FinalReference, Pre ) \
template(PhantomReference_klass, java_lang_ref_PhantomReference, Pre) \ do_klass(PhantomReference_klass, java_lang_ref_PhantomReference, Pre ) \
template(Finalizer_klass, java_lang_ref_Finalizer, Pre) \ do_klass(Finalizer_klass, java_lang_ref_Finalizer, Pre ) \
\ \
template(Thread_klass, java_lang_Thread, Pre) \ do_klass(Thread_klass, java_lang_Thread, Pre ) \
template(ThreadGroup_klass, java_lang_ThreadGroup, Pre) \ do_klass(ThreadGroup_klass, java_lang_ThreadGroup, Pre ) \
template(Properties_klass, java_util_Properties, Pre) \ do_klass(Properties_klass, java_util_Properties, Pre ) \
template(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre) \ do_klass(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre ) \
template(reflect_Field_klass, java_lang_reflect_Field, Pre) \ do_klass(reflect_Field_klass, java_lang_reflect_Field, Pre ) \
template(reflect_Method_klass, java_lang_reflect_Method, Pre) \ do_klass(reflect_Method_klass, java_lang_reflect_Method, Pre ) \
template(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre) \ do_klass(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre ) \
\ \
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \ /* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \ do_klass(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt ) \
template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \ do_klass(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \ do_klass(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \ do_klass(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt ) \
template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \ do_klass(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15 ) \
template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \ do_klass(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15 ) \
\ \
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \ /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
template(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre_JSR292) \ do_klass(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre_JSR292 ) \
template(MemberName_klass, java_lang_invoke_MemberName, Pre_JSR292) \ do_klass(MemberName_klass, java_lang_invoke_MemberName, Pre_JSR292 ) \
template(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives, Pre_JSR292) \ do_klass(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives, Pre_JSR292 ) \
template(LambdaForm_klass, java_lang_invoke_LambdaForm, Opt) \ do_klass(LambdaForm_klass, java_lang_invoke_LambdaForm, Opt ) \
template(MethodType_klass, java_lang_invoke_MethodType, Pre_JSR292) \ do_klass(MethodType_klass, java_lang_invoke_MethodType, Pre_JSR292 ) \
template(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre_JSR292) \ do_klass(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre_JSR292 ) \
template(CallSite_klass, java_lang_invoke_CallSite, Pre_JSR292) \ do_klass(CallSite_klass, java_lang_invoke_CallSite, Pre_JSR292 ) \
template(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite, Pre_JSR292) \ do_klass(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite, Pre_JSR292 ) \
template(MutableCallSite_klass, java_lang_invoke_MutableCallSite, Pre_JSR292) \ do_klass(MutableCallSite_klass, java_lang_invoke_MutableCallSite, Pre_JSR292 ) \
template(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre_JSR292) \ do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre_JSR292 ) \
/* Note: MethodHandle must be first, and VolatileCallSite last in group */ \ /* Note: MethodHandle must be first, and VolatileCallSite last in group */ \
\ \
template(StringBuffer_klass, java_lang_StringBuffer, Pre) \ do_klass(StringBuffer_klass, java_lang_StringBuffer, Pre ) \
template(StringBuilder_klass, java_lang_StringBuilder, Pre) \ do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \
\ \
/* It's NULL in non-1.4 JDKs. */ \ /* It's NULL in non-1.4 JDKs. */ \
template(StackTraceElement_klass, java_lang_StackTraceElement, Opt) \ do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \ /* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
template(nio_Buffer_klass, java_nio_Buffer, Opt) \ do_klass(nio_Buffer_klass, java_nio_Buffer, Opt ) \
\ \
template(DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \ do_klass(DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel ) \
\ \
template(PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt) \ do_klass(PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt ) \
\ \
/* Preload boxing klasses */ \ /* Preload boxing klasses */ \
template(Boolean_klass, java_lang_Boolean, Pre) \ do_klass(Boolean_klass, java_lang_Boolean, Pre ) \
template(Character_klass, java_lang_Character, Pre) \ do_klass(Character_klass, java_lang_Character, Pre ) \
template(Float_klass, java_lang_Float, Pre) \ do_klass(Float_klass, java_lang_Float, Pre ) \
template(Double_klass, java_lang_Double, Pre) \ do_klass(Double_klass, java_lang_Double, Pre ) \
template(Byte_klass, java_lang_Byte, Pre) \ do_klass(Byte_klass, java_lang_Byte, Pre ) \
template(Short_klass, java_lang_Short, Pre) \ do_klass(Short_klass, java_lang_Short, Pre ) \
template(Integer_klass, java_lang_Integer, Pre) \ do_klass(Integer_klass, java_lang_Integer, Pre ) \
template(Long_klass, java_lang_Long, Pre) \ do_klass(Long_klass, java_lang_Long, Pre ) \
/*end*/ /*end*/
@ -280,9 +280,6 @@ public:
Handle protection_domain, Handle protection_domain,
TRAPS); TRAPS);
// If the given name is known to vmSymbols, return the well-know klass:
static Klass* find_well_known_klass(Symbol* class_name);
// Lookup an instance or array class that has already been loaded // Lookup an instance or array class that has already been loaded
// either into the given class loader, or else into another class // either into the given class loader, or else into another class
// loader that is constrained (via loader constraints) to produce // loader that is constrained (via loader constraints) to produce
@ -392,9 +389,9 @@ public:
return k; return k;
} }
static Klass* check_klass_Pre(Klass* k) { return check_klass(k); } static Klass* check_klass_Pre( Klass* k) { return check_klass(k); }
static Klass* check_klass_Pre_JSR292(Klass* k) { return EnableInvokeDynamic ? check_klass(k) : k; } static Klass* check_klass_Pre_JSR292(Klass* k) { return EnableInvokeDynamic ? check_klass(k) : k; }
static Klass* check_klass_Opt(Klass* k) { return k; } static Klass* check_klass_Opt( Klass* k) { return k; }
static Klass* check_klass_Opt_Kernel(Klass* k) { return k; } //== Opt static Klass* check_klass_Opt_Kernel(Klass* k) { return k; } //== Opt
static Klass* check_klass_Opt_Only_JDK15(Klass* k) { static Klass* check_klass_Opt_Only_JDK15(Klass* k) {
assert(JDK_Version::is_gte_jdk15x_version(), "JDK 1.5 only"); assert(JDK_Version::is_gte_jdk15x_version(), "JDK 1.5 only");

View file

@ -324,24 +324,6 @@ vmIntrinsics::ID vmIntrinsics::for_raw_conversion(BasicType src, BasicType dest)
return vmIntrinsics::_none; return vmIntrinsics::_none;
} }
Method* vmIntrinsics::method_for(vmIntrinsics::ID id) {
if (id == _none) return NULL;
Symbol* cname = vmSymbols::symbol_at(class_for(id));
Symbol* mname = vmSymbols::symbol_at(name_for(id));
Symbol* msig = vmSymbols::symbol_at(signature_for(id));
if (cname == NULL || mname == NULL || msig == NULL) return NULL;
Klass* k = SystemDictionary::find_well_known_klass(cname);
if (k == NULL) return NULL;
Method* m = InstanceKlass::cast(k)->find_method(mname, msig);
if (m == NULL &&
cname == vmSymbols::java_lang_invoke_MethodHandle() &&
msig == vmSymbols::star_name()) {
// Any signature polymorphic method is represented by a fixed concrete signature:
m = InstanceKlass::cast(k)->find_method(mname, vmSymbols::object_array_object_signature());
}
return m;
}
#define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0" #define VM_INTRINSIC_INITIALIZE(id, klass, name, sig, flags) #id "\0"
static const char* vm_intrinsic_name_bodies = static const char* vm_intrinsic_name_bodies =

View file

@ -1138,9 +1138,6 @@ public:
static const char* short_name_as_C_string(ID id, char* buf, int size); static const char* short_name_as_C_string(ID id, char* buf, int size);
// Access to intrinsic methods:
static Method* method_for(ID id);
// Wrapper object methods: // Wrapper object methods:
static ID for_boxing(BasicType type); static ID for_boxing(BasicType type);
static ID for_unboxing(BasicType type); static ID for_unboxing(BasicType type);

View file

@ -333,12 +333,14 @@ void Dependencies::encode_content_bytes() {
for (int j = 0; j < stride; j++) { for (int j = 0; j < stride; j++) {
if (j == skipj) continue; if (j == skipj) continue;
ciBaseObject* v = deps->at(i+j); ciBaseObject* v = deps->at(i+j);
int idx;
if (v->is_object()) { if (v->is_object()) {
bytes.write_int(_oop_recorder->find_index(v->as_object()->constant_encoding())); idx = _oop_recorder->find_index(v->as_object()->constant_encoding());
} else { } else {
ciMetadata* meta = v->as_metadata(); ciMetadata* meta = v->as_metadata();
bytes.write_int(_oop_recorder->find_index(meta->constant_encoding())); idx = _oop_recorder->find_index(meta->constant_encoding());
} }
bytes.write_int(idx);
} }
} }
} }
@ -665,6 +667,14 @@ inline oop Dependencies::DepStream::recorded_oop_at(int i) {
Metadata* Dependencies::DepStream::argument(int i) { Metadata* Dependencies::DepStream::argument(int i) {
Metadata* result = recorded_metadata_at(argument_index(i)); Metadata* result = recorded_metadata_at(argument_index(i));
if (result == NULL) { // Explicit context argument can be compressed
int ctxkj = dep_context_arg(type()); // -1 if no explicit context arg
if (ctxkj >= 0 && i == ctxkj && ctxkj+1 < argument_count()) {
result = ctxk_encoded_as_null(type(), argument(ctxkj+1));
}
}
assert(result == NULL || result->is_klass() || result->is_method(), "must be"); assert(result == NULL || result->is_klass() || result->is_method(), "must be");
return result; return result;
} }
@ -680,25 +690,21 @@ Klass* Dependencies::DepStream::context_type() {
// Most dependencies have an explicit context type argument. // Most dependencies have an explicit context type argument.
{ {
int ctxkj = dep_context_arg(_type); // -1 if no explicit context arg int ctxkj = dep_context_arg(type()); // -1 if no explicit context arg
if (ctxkj >= 0) { if (ctxkj >= 0) {
Metadata* k = argument(ctxkj); Metadata* k = argument(ctxkj);
if (k != NULL) { // context type was not compressed away assert(k != NULL && k->is_klass(), "type check");
assert(k->is_klass(), "type check"); return (Klass*)k;
return (Klass*) k;
}
// recompute "default" context type
return ctxk_encoded_as_null(_type, argument(ctxkj+1));
} }
} }
// Some dependencies are using the klass of the first object // Some dependencies are using the klass of the first object
// argument as implicit context type (e.g. call_site_target_value). // argument as implicit context type (e.g. call_site_target_value).
{ {
int ctxkj = dep_implicit_context_arg(_type); int ctxkj = dep_implicit_context_arg(type());
if (ctxkj >= 0) { if (ctxkj >= 0) {
Klass* k = argument_oop(ctxkj)->klass(); Klass* k = argument_oop(ctxkj)->klass();
assert(k->is_klass(), "type check"); assert(k != NULL && k->is_klass(), "type check");
return (Klass*) k; return (Klass*) k;
} }
} }

View file

@ -1570,7 +1570,8 @@ void CompileBroker::compiler_thread_loop() {
} }
CompileLog* log = thread->log(); CompileLog* log = thread->log();
if (log != NULL) { if (log != NULL) {
log->begin_elem("start_compile_thread thread='" UINTX_FORMAT "' process='%d'", log->begin_elem("start_compile_thread name='%s' thread='" UINTX_FORMAT "' process='%d'",
thread->name(),
os::current_thread_id(), os::current_thread_id(),
os::current_process_id()); os::current_process_id());
log->stamp(); log->stamp();

View file

@ -302,3 +302,48 @@ void CompileLog::finish_log(outputStream* file) {
char buf[4 * K]; char buf[4 * K];
finish_log_on_error(file, buf, sizeof(buf)); finish_log_on_error(file, buf, sizeof(buf));
} }
// ------------------------------------------------------------------
// CompileLog::inline_success
//
// Print about successful method inlining.
void CompileLog::inline_success(const char* reason) {
begin_elem("inline_success reason='");
text(reason);
end_elem("'");
}
// ------------------------------------------------------------------
// CompileLog::inline_fail
//
// Print about failed method inlining.
void CompileLog::inline_fail(const char* reason) {
begin_elem("inline_fail reason='");
text(reason);
end_elem("'");
}
// ------------------------------------------------------------------
// CompileLog::set_context
//
// Set XML tag as an optional marker - it is printed only if
// there are other entries after until it is reset.
void CompileLog::set_context(const char* format, ...) {
va_list ap;
va_start(ap, format);
clear_context();
_context.print("<");
_context.vprint(format, ap);
_context.print_cr("/>");
va_end(ap);
}
// ------------------------------------------------------------------
// CompileLog::code_cache_state
//
// Print code cache state.
void CompileLog::code_cache_state() {
begin_elem("code_cache");
CodeCache::log_state(this);
end_elem("");
}

View file

@ -62,7 +62,13 @@ class CompileLog : public xmlStream {
intx thread_id() { return _thread_id; } intx thread_id() { return _thread_id; }
const char* file() { return _file; } const char* file() { return _file; }
// Optional context marker, to help place actions that occur during
// parsing. If there is no log output until the next context string
// or reset, context string will be silently ignored
stringStream* context() { return &_context; } stringStream* context() { return &_context; }
void clear_context() { context()->reset(); }
void set_context(const char* format, ...);
void name(ciSymbol* s); // name='s' void name(ciSymbol* s); // name='s'
void name(Symbol* s) { xmlStream::name(s); } void name(Symbol* s) { xmlStream::name(s); }
@ -71,6 +77,9 @@ class CompileLog : public xmlStream {
int identify(ciBaseObject* obj); int identify(ciBaseObject* obj);
void clear_identities(); void clear_identities();
void inline_fail (const char* reason);
void inline_success(const char* reason);
// virtuals // virtuals
virtual void see_tag(const char* tag, bool push); virtual void see_tag(const char* tag, bool push);
virtual void pop_tag(const char* tag); virtual void pop_tag(const char* tag);
@ -78,6 +87,9 @@ class CompileLog : public xmlStream {
// make a provisional end of log mark // make a provisional end of log mark
void mark_file_end() { _file_end = out()->count(); } void mark_file_end() { _file_end = out()->count(); }
// Print code cache statistics
void code_cache_state();
// copy all logs to the given stream // copy all logs to the given stream
static void finish_log(outputStream* out); static void finish_log(outputStream* out);
static void finish_log_on_error(outputStream* out, char *buf, int buflen); static void finish_log_on_error(outputStream* out, char *buf, int buflen);

View file

@ -222,7 +222,7 @@ ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(
// depends on this property. // depends on this property.
debug_only( debug_only(
FreeChunk* junk = NULL; FreeChunk* junk = NULL;
assert(UseCompressedOops || assert(UseCompressedKlassPointers ||
junk->prev_addr() == (void*)(oop(junk)->klass_addr()), junk->prev_addr() == (void*)(oop(junk)->klass_addr()),
"Offset of FreeChunk::_prev within FreeChunk must match" "Offset of FreeChunk::_prev within FreeChunk must match"
" that of OopDesc::_klass within OopDesc"); " that of OopDesc::_klass within OopDesc");

View file

@ -135,6 +135,8 @@ class Metaspace : public CHeapObj<mtClass> {
MetaWord* expand_and_allocate(size_t size, MetaWord* expand_and_allocate(size_t size,
MetadataType mdtype); MetadataType mdtype);
static bool is_initialized() { return _class_space_list != NULL; }
#ifndef PRODUCT #ifndef PRODUCT
bool contains(const void *ptr) const; bool contains(const void *ptr) const;
bool contains_class(const void *ptr) const; bool contains_class(const void *ptr) const;

View file

@ -151,7 +151,9 @@ size_t Universe::_heap_used_at_last_gc = 0;
CollectedHeap* Universe::_collectedHeap = NULL; CollectedHeap* Universe::_collectedHeap = NULL;
NarrowOopStruct Universe::_narrow_oop = { NULL, 0, true }; NarrowPtrStruct Universe::_narrow_oop = { NULL, 0, true };
NarrowPtrStruct Universe::_narrow_klass = { NULL, 0, true };
address Universe::_narrow_ptrs_base;
void Universe::basic_type_classes_do(void f(Klass*)) { void Universe::basic_type_classes_do(void f(Klass*)) {
@ -807,7 +809,7 @@ jint Universe::initialize_heap() {
} }
if ((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) { if ((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) {
// Can't reserve heap below 32Gb. // Can't reserve heap below 32Gb.
Universe::set_narrow_oop_base(Universe::heap()->base() - os::vm_page_size()); // keep the Universe::narrow_oop_base() set in Universe::reserve_heap()
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
if (verbose) { if (verbose) {
tty->print(", Compressed Oops with base: "PTR_FORMAT, Universe::narrow_oop_base()); tty->print(", Compressed Oops with base: "PTR_FORMAT, Universe::narrow_oop_base());
@ -838,8 +840,16 @@ jint Universe::initialize_heap() {
tty->cr(); tty->cr();
tty->cr(); tty->cr();
} }
if (UseCompressedKlassPointers) {
Universe::set_narrow_klass_base(Universe::narrow_oop_base());
Universe::set_narrow_klass_shift(MIN2(Universe::narrow_oop_shift(), LogKlassAlignmentInBytes));
} }
assert(Universe::narrow_oop_base() == (Universe::heap()->base() - os::vm_page_size()) || Universe::set_narrow_ptrs_base(Universe::narrow_oop_base());
}
// Universe::narrow_oop_base() is one page below the metaspace
// base. The actual metaspace base depends on alignment constraints
// so we don't know its exact location here.
assert((intptr_t)Universe::narrow_oop_base() <= (intptr_t)(Universe::heap()->base() - os::vm_page_size() - ClassMetaspaceSize) ||
Universe::narrow_oop_base() == NULL, "invalid value"); Universe::narrow_oop_base() == NULL, "invalid value");
assert(Universe::narrow_oop_shift() == LogMinObjAlignmentInBytes || assert(Universe::narrow_oop_shift() == LogMinObjAlignmentInBytes ||
Universe::narrow_oop_shift() == 0, "invalid value"); Universe::narrow_oop_shift() == 0, "invalid value");
@ -861,7 +871,10 @@ jint Universe::initialize_heap() {
ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) {
// Add in the class metaspace area so the classes in the headers can // Add in the class metaspace area so the classes in the headers can
// be compressed the same as instances. // be compressed the same as instances.
size_t total_reserved = align_size_up(heap_size + ClassMetaspaceSize, alignment); // Need to round class space size up because it's below the heap and
// the actual alignment depends on its size.
size_t metaspace_size = align_size_up(ClassMetaspaceSize, alignment);
size_t total_reserved = align_size_up(heap_size + metaspace_size, alignment);
char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop); char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);
ReservedHeapSpace total_rs(total_reserved, alignment, UseLargePages, addr); ReservedHeapSpace total_rs(total_reserved, alignment, UseLargePages, addr);
@ -895,11 +908,23 @@ ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) {
return total_rs; return total_rs;
} }
// Split the reserved space into main Java heap and a space for classes // Split the reserved space into main Java heap and a space for
// so that they can be compressed using the same algorithm as compressed oops // classes so that they can be compressed using the same algorithm
ReservedSpace heap_rs = total_rs.first_part(heap_size); // as compressed oops. If compress oops and compress klass ptrs are
ReservedSpace class_rs = total_rs.last_part(heap_size, alignment); // used we need the meta space first: if the alignment used for
// compressed oops is greater than the one used for compressed klass
// ptrs, a metadata space on top of the heap could become
// unreachable.
ReservedSpace class_rs = total_rs.first_part(metaspace_size);
ReservedSpace heap_rs = total_rs.last_part(metaspace_size, alignment);
Metaspace::initialize_class_space(class_rs); Metaspace::initialize_class_space(class_rs);
if (UseCompressedOops) {
// Universe::initialize_heap() will reset this to NULL if unscaled
// or zero-based narrow oops are actually used.
address base = (address)(total_rs.base() - os::vm_page_size());
Universe::set_narrow_oop_base(base);
}
return heap_rs; return heap_rs;
} }

View file

@ -105,16 +105,16 @@ class LatestMethodOopCache : public CommonMethodOopCache {
Method* get_Method(); Method* get_Method();
}; };
// For UseCompressedOops. // For UseCompressedOops and UseCompressedKlassPointers.
struct NarrowOopStruct { struct NarrowPtrStruct {
// Base address for oop-within-java-object materialization. // Base address for oop/klass-within-java-object materialization.
// NULL if using wide oops or zero based narrow oops. // NULL if using wide oops/klasses or zero based narrow oops/klasses.
address _base; address _base;
// Number of shift bits for encoding/decoding narrow oops. // Number of shift bits for encoding/decoding narrow ptrs.
// 0 if using wide oops or zero based unscaled narrow oops, // 0 if using wide ptrs or zero based unscaled narrow ptrs,
// LogMinObjAlignmentInBytes otherwise. // LogMinObjAlignmentInBytes/LogKlassAlignmentInBytes otherwise.
int _shift; int _shift;
// Generate code with implicit null checks for narrow oops. // Generate code with implicit null checks for narrow ptrs.
bool _use_implicit_null_checks; bool _use_implicit_null_checks;
}; };
@ -206,7 +206,10 @@ class Universe: AllStatic {
static CollectedHeap* _collectedHeap; static CollectedHeap* _collectedHeap;
// For UseCompressedOops. // For UseCompressedOops.
static struct NarrowOopStruct _narrow_oop; static struct NarrowPtrStruct _narrow_oop;
// For UseCompressedKlassPointers.
static struct NarrowPtrStruct _narrow_klass;
static address _narrow_ptrs_base;
// array of dummy objects used with +FullGCAlot // array of dummy objects used with +FullGCAlot
debug_only(static objArrayOop _fullgc_alot_dummy_array;) debug_only(static objArrayOop _fullgc_alot_dummy_array;)
@ -259,8 +262,21 @@ class Universe: AllStatic {
HeapBasedNarrowOop = 2 HeapBasedNarrowOop = 2
}; };
static char* preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode); static char* preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode);
static void set_narrow_oop_base(address base) { _narrow_oop._base = base; } static char* preferred_metaspace_base(size_t heap_size, NARROW_OOP_MODE mode);
static void set_narrow_oop_use_implicit_null_checks(bool use) { _narrow_oop._use_implicit_null_checks = use; } static void set_narrow_oop_base(address base) {
assert(UseCompressedOops, "no compressed oops?");
_narrow_oop._base = base;
}
static void set_narrow_klass_base(address base) {
assert(UseCompressedKlassPointers, "no compressed klass ptrs?");
_narrow_klass._base = base;
}
static void set_narrow_oop_use_implicit_null_checks(bool use) {
assert(UseCompressedOops, "no compressed ptrs?");
_narrow_oop._use_implicit_null_checks = use;
}
static bool reserve_metaspace_helper(bool with_base = false);
static ReservedHeapSpace reserve_heap_metaspace(size_t heap_size, size_t alignment, bool& contiguous);
// Debugging // Debugging
static int _verify_count; // number of verifies done static int _verify_count; // number of verifies done
@ -354,14 +370,30 @@ class Universe: AllStatic {
static CollectedHeap* heap() { return _collectedHeap; } static CollectedHeap* heap() { return _collectedHeap; }
// For UseCompressedOops // For UseCompressedOops
static address* narrow_oop_base_addr() { return &_narrow_oop._base; }
static address narrow_oop_base() { return _narrow_oop._base; } static address narrow_oop_base() { return _narrow_oop._base; }
static bool is_narrow_oop_base(void* addr) { return (narrow_oop_base() == (address)addr); } static bool is_narrow_oop_base(void* addr) { return (narrow_oop_base() == (address)addr); }
static int narrow_oop_shift() { return _narrow_oop._shift; } static int narrow_oop_shift() { return _narrow_oop._shift; }
static bool narrow_oop_use_implicit_null_checks() { return _narrow_oop._use_implicit_null_checks; } static bool narrow_oop_use_implicit_null_checks() { return _narrow_oop._use_implicit_null_checks; }
// For UseCompressedKlassPointers
static address narrow_klass_base() { return _narrow_klass._base; }
static bool is_narrow_klass_base(void* addr) { return (narrow_klass_base() == (address)addr); }
static int narrow_klass_shift() { return _narrow_klass._shift; }
static bool narrow_klass_use_implicit_null_checks() { return _narrow_klass._use_implicit_null_checks; }
static address* narrow_ptrs_base_addr() { return &_narrow_ptrs_base; }
static void set_narrow_ptrs_base(address a) { _narrow_ptrs_base = a; }
static address narrow_ptrs_base() { return _narrow_ptrs_base; }
// this is set in vm_version on sparc (and then reset in universe afaict) // this is set in vm_version on sparc (and then reset in universe afaict)
static void set_narrow_oop_shift(int shift) { _narrow_oop._shift = shift; } static void set_narrow_oop_shift(int shift) {
_narrow_oop._shift = shift;
}
static void set_narrow_klass_shift(int shift) {
assert(shift == 0 || shift == LogKlassAlignmentInBytes, "invalid shift for klass ptrs");
_narrow_klass._shift = shift;
}
// Reserve Java heap and determine CompressedOops mode // Reserve Java heap and determine CompressedOops mode
static ReservedSpace reserve_heap(size_t heap_size, size_t alignment); static ReservedSpace reserve_heap(size_t heap_size, size_t alignment);

View file

@ -37,7 +37,9 @@ class instanceOopDesc : public oopDesc {
// If compressed, the offset of the fields of the instance may not be aligned. // If compressed, the offset of the fields of the instance may not be aligned.
static int base_offset_in_bytes() { static int base_offset_in_bytes() {
return UseCompressedKlassPointers ? // offset computation code breaks if UseCompressedKlassPointers
// only is true
return (UseCompressedOops && UseCompressedKlassPointers) ?
klass_gap_offset_in_bytes() : klass_gap_offset_in_bytes() :
sizeof(instanceOopDesc); sizeof(instanceOopDesc);
} }

View file

@ -712,7 +712,8 @@ void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report)
} }
if ((TraceDeoptimization || LogCompilation) && (xtty != NULL)) { if ((TraceDeoptimization || LogCompilation) && (xtty != NULL)) {
ttyLocker ttyl; ttyLocker ttyl;
xtty->begin_elem("make_not_%scompilable thread='%d'", is_osr ? "osr_" : "", (int) os::current_thread_id()); xtty->begin_elem("make_not_%scompilable thread='" UINTX_FORMAT "'",
is_osr ? "osr_" : "", os::current_thread_id());
xtty->method(this); xtty->method(this);
xtty->stamp(); xtty->stamp();
xtty->end_elem(); xtty->end_elem();

View file

@ -185,8 +185,8 @@ inline bool oopDesc::is_null(narrowOop obj) { return obj == 0; }
inline bool check_obj_alignment(oop obj) { inline bool check_obj_alignment(oop obj) {
return (intptr_t)obj % MinObjAlignmentInBytes == 0; return (intptr_t)obj % MinObjAlignmentInBytes == 0;
} }
inline bool check_obj_alignment(Klass* obj) { inline bool check_klass_alignment(Klass* obj) {
return (intptr_t)obj % MinObjAlignmentInBytes == 0; return (intptr_t)obj % KlassAlignmentInBytes == 0;
} }
inline narrowOop oopDesc::encode_heap_oop_not_null(oop v) { inline narrowOop oopDesc::encode_heap_oop_not_null(oop v) {
@ -228,9 +228,9 @@ inline oop oopDesc::decode_heap_oop(oop v) { return v; }
inline narrowOop oopDesc::encode_klass_not_null(Klass* v) { inline narrowOop oopDesc::encode_klass_not_null(Klass* v) {
assert(!is_null(v), "oop value can never be zero"); assert(!is_null(v), "oop value can never be zero");
assert(check_obj_alignment(v), "Address not aligned"); assert(check_klass_alignment(v), "Address not aligned");
address base = Universe::narrow_oop_base(); address base = Universe::narrow_klass_base();
int shift = Universe::narrow_oop_shift(); int shift = Universe::narrow_klass_shift();
uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1)); uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1));
assert(OopEncodingHeapMax > pd, "change encoding max if new encoding"); assert(OopEncodingHeapMax > pd, "change encoding max if new encoding");
uint64_t result = pd >> shift; uint64_t result = pd >> shift;
@ -245,10 +245,10 @@ inline narrowOop oopDesc::encode_klass(Klass* v) {
inline Klass* oopDesc::decode_klass_not_null(narrowOop v) { inline Klass* oopDesc::decode_klass_not_null(narrowOop v) {
assert(!is_null(v), "narrow oop value can never be zero"); assert(!is_null(v), "narrow oop value can never be zero");
address base = Universe::narrow_oop_base(); address base = Universe::narrow_klass_base();
int shift = Universe::narrow_oop_shift(); int shift = Universe::narrow_klass_shift();
Klass* result = (Klass*)(void*)((uintptr_t)base + ((uintptr_t)v << shift)); Klass* result = (Klass*)(void*)((uintptr_t)base + ((uintptr_t)v << shift));
assert(check_obj_alignment(result), err_msg("address not aligned: " PTR_FORMAT, (void*) result)); assert(check_klass_alignment(result), err_msg("address not aligned: " PTR_FORMAT, (void*) result));
return result; return result;
} }

View file

@ -439,9 +439,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
WarmCallInfo wci = *(initial_wci); WarmCallInfo wci = *(initial_wci);
failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci); failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci);
if (failure_msg != NULL && C->log() != NULL) { if (failure_msg != NULL && C->log() != NULL) {
C->log()->begin_elem("inline_fail reason='"); C->log()->inline_fail(failure_msg);
C->log()->text("%s", failure_msg);
C->log()->end_elem("'");
} }
#ifndef PRODUCT #ifndef PRODUCT

View file

@ -1386,7 +1386,7 @@ static Node* split_flow_path(PhaseGVN *phase, PhiNode *phi) {
Node *n = phi->in(i); Node *n = phi->in(i);
if( !n ) return NULL; if( !n ) return NULL;
if( phase->type(n) == Type::TOP ) return NULL; if( phase->type(n) == Type::TOP ) return NULL;
if( n->Opcode() == Op_ConP || n->Opcode() == Op_ConN ) if( n->Opcode() == Op_ConP || n->Opcode() == Op_ConN || n->Opcode() == Op_ConNKlass )
break; break;
} }
if( i >= phi->req() ) // Only split for constants if( i >= phi->req() ) // Only split for constants
@ -1875,17 +1875,19 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
} }
#ifdef _LP64 #ifdef _LP64
// Push DecodeN down through phi. // Push DecodeN/DecodeNKlass down through phi.
// The rest of phi graph will transform by split EncodeP node though phis up. // The rest of phi graph will transform by split EncodeP node though phis up.
if (UseCompressedOops && can_reshape && progress == NULL) { if ((UseCompressedOops || UseCompressedKlassPointers) && can_reshape && progress == NULL) {
bool may_push = true; bool may_push = true;
bool has_decodeN = false; bool has_decodeN = false;
bool is_decodeN = false;
for (uint i=1; i<req(); ++i) {// For all paths in for (uint i=1; i<req(); ++i) {// For all paths in
Node *ii = in(i); Node *ii = in(i);
if (ii->is_DecodeN() && ii->bottom_type() == bottom_type()) { if (ii->is_DecodeNarrowPtr() && ii->bottom_type() == bottom_type()) {
// Do optimization if a non dead path exist. // Do optimization if a non dead path exist.
if (ii->in(1)->bottom_type() != Type::TOP) { if (ii->in(1)->bottom_type() != Type::TOP) {
has_decodeN = true; has_decodeN = true;
is_decodeN = ii->is_DecodeN();
} }
} else if (!ii->is_Phi()) { } else if (!ii->is_Phi()) {
may_push = false; may_push = false;
@ -1895,13 +1897,18 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if (has_decodeN && may_push) { if (has_decodeN && may_push) {
PhaseIterGVN *igvn = phase->is_IterGVN(); PhaseIterGVN *igvn = phase->is_IterGVN();
// Make narrow type for new phi. // Make narrow type for new phi.
const Type* narrow_t = TypeNarrowOop::make(this->bottom_type()->is_ptr()); const Type* narrow_t;
if (is_decodeN) {
narrow_t = TypeNarrowOop::make(this->bottom_type()->is_ptr());
} else {
narrow_t = TypeNarrowKlass::make(this->bottom_type()->is_ptr());
}
PhiNode* new_phi = new (phase->C) PhiNode(r, narrow_t); PhiNode* new_phi = new (phase->C) PhiNode(r, narrow_t);
uint orig_cnt = req(); uint orig_cnt = req();
for (uint i=1; i<req(); ++i) {// For all paths in for (uint i=1; i<req(); ++i) {// For all paths in
Node *ii = in(i); Node *ii = in(i);
Node* new_ii = NULL; Node* new_ii = NULL;
if (ii->is_DecodeN()) { if (ii->is_DecodeNarrowPtr()) {
assert(ii->bottom_type() == bottom_type(), "sanity"); assert(ii->bottom_type() == bottom_type(), "sanity");
new_ii = ii->in(1); new_ii = ii->in(1);
} else { } else {
@ -1909,14 +1916,22 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if (ii->as_Phi() == this) { if (ii->as_Phi() == this) {
new_ii = new_phi; new_ii = new_phi;
} else { } else {
if (is_decodeN) {
new_ii = new (phase->C) EncodePNode(ii, narrow_t); new_ii = new (phase->C) EncodePNode(ii, narrow_t);
} else {
new_ii = new (phase->C) EncodePKlassNode(ii, narrow_t);
}
igvn->register_new_node_with_optimizer(new_ii); igvn->register_new_node_with_optimizer(new_ii);
} }
} }
new_phi->set_req(i, new_ii); new_phi->set_req(i, new_ii);
} }
igvn->register_new_node_with_optimizer(new_phi, this); igvn->register_new_node_with_optimizer(new_phi, this);
if (is_decodeN) {
progress = new (phase->C) DecodeNNode(new_phi, bottom_type()); progress = new (phase->C) DecodeNNode(new_phi, bottom_type());
} else {
progress = new (phase->C) DecodeNKlassNode(new_phi, bottom_type());
}
} }
} }
#endif #endif

View file

@ -91,6 +91,7 @@ macro(GetAndSetP)
macro(GetAndSetN) macro(GetAndSetN)
macro(Con) macro(Con)
macro(ConN) macro(ConN)
macro(ConNKlass)
macro(ConD) macro(ConD)
macro(ConF) macro(ConF)
macro(ConI) macro(ConI)
@ -118,6 +119,7 @@ macro(CountTrailingZerosI)
macro(CountTrailingZerosL) macro(CountTrailingZerosL)
macro(CreateEx) macro(CreateEx)
macro(DecodeN) macro(DecodeN)
macro(DecodeNKlass)
macro(DivD) macro(DivD)
macro(DivF) macro(DivF)
macro(DivI) macro(DivI)
@ -126,6 +128,7 @@ macro(DivMod)
macro(DivModI) macro(DivModI)
macro(DivModL) macro(DivModL)
macro(EncodeP) macro(EncodeP)
macro(EncodePKlass)
macro(ExpD) macro(ExpD)
macro(FastLock) macro(FastLock)
macro(FastUnlock) macro(FastUnlock)
@ -147,7 +150,6 @@ macro(LoadD)
macro(LoadD_unaligned) macro(LoadD_unaligned)
macro(LoadF) macro(LoadF)
macro(LoadI) macro(LoadI)
macro(LoadUI2L)
macro(LoadKlass) macro(LoadKlass)
macro(LoadNKlass) macro(LoadNKlass)
macro(LoadL) macro(LoadL)
@ -233,6 +235,7 @@ macro(StoreI)
macro(StoreL) macro(StoreL)
macro(StoreP) macro(StoreP)
macro(StoreN) macro(StoreN)
macro(StoreNKlass)
macro(StrComp) macro(StrComp)
macro(StrEquals) macro(StrEquals)
macro(StrIndexOf) macro(StrIndexOf)

View file

@ -828,6 +828,9 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
has_unsafe_access(), has_unsafe_access(),
SharedRuntime::is_wide_vector(max_vector_size()) SharedRuntime::is_wide_vector(max_vector_size())
); );
if (log() != NULL) // Print code cache state into compiler log
log()->code_cache_state();
} }
} }
@ -2236,6 +2239,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
nop != Op_CreateEx && nop != Op_CreateEx &&
nop != Op_CheckCastPP && nop != Op_CheckCastPP &&
nop != Op_DecodeN && nop != Op_DecodeN &&
nop != Op_DecodeNKlass &&
!n->is_Mem() ) { !n->is_Mem() ) {
Node *x = n->clone(); Node *x = n->clone();
call->set_req( TypeFunc::Parms, x ); call->set_req( TypeFunc::Parms, x );
@ -2284,11 +2288,11 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
case Op_GetAndSetN: case Op_GetAndSetN:
case Op_StoreP: case Op_StoreP:
case Op_StoreN: case Op_StoreN:
case Op_StoreNKlass:
case Op_LoadB: case Op_LoadB:
case Op_LoadUB: case Op_LoadUB:
case Op_LoadUS: case Op_LoadUS:
case Op_LoadI: case Op_LoadI:
case Op_LoadUI2L:
case Op_LoadKlass: case Op_LoadKlass:
case Op_LoadNKlass: case Op_LoadNKlass:
case Op_LoadL: case Op_LoadL:
@ -2318,7 +2322,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
addp->in(AddPNode::Base) == n->in(AddPNode::Base), addp->in(AddPNode::Base) == n->in(AddPNode::Base),
"Base pointers must match" ); "Base pointers must match" );
#ifdef _LP64 #ifdef _LP64
if (UseCompressedOops && if ((UseCompressedOops || UseCompressedKlassPointers) &&
addp->Opcode() == Op_ConP && addp->Opcode() == Op_ConP &&
addp == n->in(AddPNode::Base) && addp == n->in(AddPNode::Base) &&
n->in(AddPNode::Offset)->is_Con()) { n->in(AddPNode::Offset)->is_Con()) {
@ -2327,16 +2331,18 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
// instructions (4) then load 64-bits constant (7). // instructions (4) then load 64-bits constant (7).
// Do this transformation here since IGVN will convert ConN back to ConP. // Do this transformation here since IGVN will convert ConN back to ConP.
const Type* t = addp->bottom_type(); const Type* t = addp->bottom_type();
if (t->isa_oopptr()) { if (t->isa_oopptr() || t->isa_klassptr()) {
Node* nn = NULL; Node* nn = NULL;
int op = t->isa_oopptr() ? Op_ConN : Op_ConNKlass;
// Look for existing ConN node of the same exact type. // Look for existing ConN node of the same exact type.
Compile* C = Compile::current(); Compile* C = Compile::current();
Node* r = C->root(); Node* r = C->root();
uint cnt = r->outcnt(); uint cnt = r->outcnt();
for (uint i = 0; i < cnt; i++) { for (uint i = 0; i < cnt; i++) {
Node* m = r->raw_out(i); Node* m = r->raw_out(i);
if (m!= NULL && m->Opcode() == Op_ConN && if (m!= NULL && m->Opcode() == op &&
m->bottom_type()->make_ptr() == t) { m->bottom_type()->make_ptr() == t) {
nn = m; nn = m;
break; break;
@ -2345,7 +2351,11 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
if (nn != NULL) { if (nn != NULL) {
// Decode a narrow oop to match address // Decode a narrow oop to match address
// [R12 + narrow_oop_reg<<3 + offset] // [R12 + narrow_oop_reg<<3 + offset]
if (t->isa_oopptr()) {
nn = new (C) DecodeNNode(nn, t); nn = new (C) DecodeNNode(nn, t);
} else {
nn = new (C) DecodeNKlassNode(nn, t);
}
n->set_req(AddPNode::Base, nn); n->set_req(AddPNode::Base, nn);
n->set_req(AddPNode::Address, nn); n->set_req(AddPNode::Address, nn);
if (addp->outcnt() == 0) { if (addp->outcnt() == 0) {
@ -2400,22 +2410,24 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
case Op_CmpP: case Op_CmpP:
// Do this transformation here to preserve CmpPNode::sub() and // Do this transformation here to preserve CmpPNode::sub() and
// other TypePtr related Ideal optimizations (for example, ptr nullness). // other TypePtr related Ideal optimizations (for example, ptr nullness).
if (n->in(1)->is_DecodeN() || n->in(2)->is_DecodeN()) { if (n->in(1)->is_DecodeNarrowPtr() || n->in(2)->is_DecodeNarrowPtr()) {
Node* in1 = n->in(1); Node* in1 = n->in(1);
Node* in2 = n->in(2); Node* in2 = n->in(2);
if (!in1->is_DecodeN()) { if (!in1->is_DecodeNarrowPtr()) {
in2 = in1; in2 = in1;
in1 = n->in(2); in1 = n->in(2);
} }
assert(in1->is_DecodeN(), "sanity"); assert(in1->is_DecodeNarrowPtr(), "sanity");
Compile* C = Compile::current(); Compile* C = Compile::current();
Node* new_in2 = NULL; Node* new_in2 = NULL;
if (in2->is_DecodeN()) { if (in2->is_DecodeNarrowPtr()) {
assert(in2->Opcode() == in1->Opcode(), "must be same node type");
new_in2 = in2->in(1); new_in2 = in2->in(1);
} else if (in2->Opcode() == Op_ConP) { } else if (in2->Opcode() == Op_ConP) {
const Type* t = in2->bottom_type(); const Type* t = in2->bottom_type();
if (t == TypePtr::NULL_PTR) { if (t == TypePtr::NULL_PTR) {
assert(in1->is_DecodeN(), "compare klass to null?");
// Don't convert CmpP null check into CmpN if compressed // Don't convert CmpP null check into CmpN if compressed
// oops implicit null check is not generated. // oops implicit null check is not generated.
// This will allow to generate normal oop implicit null check. // This will allow to generate normal oop implicit null check.
@ -2460,6 +2472,8 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
// //
} else if (t->isa_oopptr()) { } else if (t->isa_oopptr()) {
new_in2 = ConNode::make(C, t->make_narrowoop()); new_in2 = ConNode::make(C, t->make_narrowoop());
} else if (t->isa_klassptr()) {
new_in2 = ConNode::make(C, t->make_narrowklass());
} }
} }
if (new_in2 != NULL) { if (new_in2 != NULL) {
@ -2476,23 +2490,28 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
break; break;
case Op_DecodeN: case Op_DecodeN:
assert(!n->in(1)->is_EncodeP(), "should be optimized out"); case Op_DecodeNKlass:
assert(!n->in(1)->is_EncodeNarrowPtr(), "should be optimized out");
// DecodeN could be pinned when it can't be fold into // DecodeN could be pinned when it can't be fold into
// an address expression, see the code for Op_CastPP above. // an address expression, see the code for Op_CastPP above.
assert(n->in(0) == NULL || !Matcher::narrow_oop_use_complex_address(), "no control"); assert(n->in(0) == NULL || (UseCompressedOops && !Matcher::narrow_oop_use_complex_address()), "no control");
break; break;
case Op_EncodeP: { case Op_EncodeP:
case Op_EncodePKlass: {
Node* in1 = n->in(1); Node* in1 = n->in(1);
if (in1->is_DecodeN()) { if (in1->is_DecodeNarrowPtr()) {
n->subsume_by(in1->in(1)); n->subsume_by(in1->in(1));
} else if (in1->Opcode() == Op_ConP) { } else if (in1->Opcode() == Op_ConP) {
Compile* C = Compile::current(); Compile* C = Compile::current();
const Type* t = in1->bottom_type(); const Type* t = in1->bottom_type();
if (t == TypePtr::NULL_PTR) { if (t == TypePtr::NULL_PTR) {
assert(t->isa_oopptr(), "null klass?");
n->subsume_by(ConNode::make(C, TypeNarrowOop::NULL_PTR)); n->subsume_by(ConNode::make(C, TypeNarrowOop::NULL_PTR));
} else if (t->isa_oopptr()) { } else if (t->isa_oopptr()) {
n->subsume_by(ConNode::make(C, t->make_narrowoop())); n->subsume_by(ConNode::make(C, t->make_narrowoop()));
} else if (t->isa_klassptr()) {
n->subsume_by(ConNode::make(C, t->make_narrowklass()));
} }
} }
if (in1->outcnt() == 0) { if (in1->outcnt() == 0) {
@ -2526,7 +2545,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
} }
case Op_Phi: case Op_Phi:
if (n->as_Phi()->bottom_type()->isa_narrowoop()) { if (n->as_Phi()->bottom_type()->isa_narrowoop() || n->as_Phi()->bottom_type()->isa_narrowklass()) {
// The EncodeP optimization may create Phi with the same edges // The EncodeP optimization may create Phi with the same edges
// for all paths. It is not handled well by Register Allocator. // for all paths. It is not handled well by Register Allocator.
Node* unique_in = n->in(1); Node* unique_in = n->in(1);
@ -2689,12 +2708,13 @@ static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Re
} }
// Skip next transformation if compressed oops are not used. // Skip next transformation if compressed oops are not used.
if (!UseCompressedOops || !Matcher::gen_narrow_oop_implicit_null_checks()) if ((UseCompressedOops && !Matcher::gen_narrow_oop_implicit_null_checks()) ||
(!UseCompressedOops && !UseCompressedKlassPointers))
return; return;
// Go over safepoints nodes to skip DecodeN nodes for debug edges. // Go over safepoints nodes to skip DecodeN/DecodeNKlass nodes for debug edges.
// It could be done for an uncommon traps or any safepoints/calls // It could be done for an uncommon traps or any safepoints/calls
// if the DecodeN node is referenced only in a debug info. // if the DecodeN/DecodeNKlass node is referenced only in a debug info.
while (sfpt.size() > 0) { while (sfpt.size() > 0) {
n = sfpt.pop(); n = sfpt.pop();
JVMState *jvms = n->as_SafePoint()->jvms(); JVMState *jvms = n->as_SafePoint()->jvms();
@ -2705,7 +2725,7 @@ static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Re
n->as_CallStaticJava()->uncommon_trap_request() != 0); n->as_CallStaticJava()->uncommon_trap_request() != 0);
for (int j = start; j < end; j++) { for (int j = start; j < end; j++) {
Node* in = n->in(j); Node* in = n->in(j);
if (in->is_DecodeN()) { if (in->is_DecodeNarrowPtr()) {
bool safe_to_skip = true; bool safe_to_skip = true;
if (!is_uncommon ) { if (!is_uncommon ) {
// Is it safe to skip? // Is it safe to skip?

View file

@ -54,6 +54,7 @@ ConNode *ConNode::make( Compile* C, const Type *t ) {
case T_ARRAY: return new (C) ConPNode( t->is_aryptr() ); case T_ARRAY: return new (C) ConPNode( t->is_aryptr() );
case T_ADDRESS: return new (C) ConPNode( t->is_ptr() ); case T_ADDRESS: return new (C) ConPNode( t->is_ptr() );
case T_NARROWOOP: return new (C) ConNNode( t->is_narrowoop() ); case T_NARROWOOP: return new (C) ConNNode( t->is_narrowoop() );
case T_NARROWKLASS: return new (C) ConNKlassNode( t->is_narrowklass() );
case T_METADATA: return new (C) ConPNode( t->is_ptr() ); case T_METADATA: return new (C) ConPNode( t->is_ptr() );
// Expected cases: TypePtr::NULL_PTR, any is_rawptr() // Expected cases: TypePtr::NULL_PTR, any is_rawptr()
// Also seen: AnyPtr(TopPTR *+top); from command line: // Also seen: AnyPtr(TopPTR *+top); from command line:
@ -447,7 +448,7 @@ Node *ConstraintCastNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
// If not converting int->oop, throw away cast after constant propagation // If not converting int->oop, throw away cast after constant propagation
Node *CastPPNode::Ideal_DU_postCCP( PhaseCCP *ccp ) { Node *CastPPNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
const Type *t = ccp->type(in(1)); const Type *t = ccp->type(in(1));
if (!t->isa_oop_ptr() || (in(1)->is_DecodeN() && Matcher::gen_narrow_oop_implicit_null_checks())) { if (!t->isa_oop_ptr() || ((in(1)->is_DecodeN()) && Matcher::gen_narrow_oop_implicit_null_checks())) {
return NULL; // do not transform raw pointers or narrow oops return NULL; // do not transform raw pointers or narrow oops
} }
return ConstraintCastNode::Ideal_DU_postCCP(ccp); return ConstraintCastNode::Ideal_DU_postCCP(ccp);
@ -607,15 +608,56 @@ const Type *EncodePNode::Value( PhaseTransform *phase ) const {
if (t == Type::TOP) return Type::TOP; if (t == Type::TOP) return Type::TOP;
if (t == TypePtr::NULL_PTR) return TypeNarrowOop::NULL_PTR; if (t == TypePtr::NULL_PTR) return TypeNarrowOop::NULL_PTR;
assert(t->isa_oop_ptr() || UseCompressedKlassPointers && t->isa_klassptr(), "only oopptr here"); assert(t->isa_oop_ptr(), "only oopptr here");
return t->make_narrowoop(); return t->make_narrowoop();
} }
Node *EncodePNode::Ideal_DU_postCCP( PhaseCCP *ccp ) { Node *EncodeNarrowPtrNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
return MemNode::Ideal_common_DU_postCCP(ccp, this, in(1)); return MemNode::Ideal_common_DU_postCCP(ccp, this, in(1));
} }
Node* DecodeNKlassNode::Identity(PhaseTransform* phase) {
const Type *t = phase->type( in(1) );
if( t == Type::TOP ) return in(1);
if (in(1)->is_EncodePKlass()) {
// (DecodeNKlass (EncodePKlass p)) -> p
return in(1)->in(1);
}
return this;
}
const Type *DecodeNKlassNode::Value( PhaseTransform *phase ) const {
const Type *t = phase->type( in(1) );
if (t == Type::TOP) return Type::TOP;
assert(t != TypeNarrowKlass::NULL_PTR, "null klass?");
assert(t->isa_narrowklass(), "only narrow klass ptr here");
return t->make_ptr();
}
Node* EncodePKlassNode::Identity(PhaseTransform* phase) {
const Type *t = phase->type( in(1) );
if( t == Type::TOP ) return in(1);
if (in(1)->is_DecodeNKlass()) {
// (EncodePKlass (DecodeNKlass p)) -> p
return in(1)->in(1);
}
return this;
}
const Type *EncodePKlassNode::Value( PhaseTransform *phase ) const {
const Type *t = phase->type( in(1) );
if (t == Type::TOP) return Type::TOP;
assert (t != TypePtr::NULL_PTR, "null klass?");
assert(UseCompressedKlassPointers && t->isa_klassptr(), "only klass ptr here");
return t->make_narrowklass();
}
//============================================================================= //=============================================================================
//------------------------------Identity--------------------------------------- //------------------------------Identity---------------------------------------
Node *Conv2BNode::Identity( PhaseTransform *phase ) { Node *Conv2BNode::Identity( PhaseTransform *phase ) {

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