Merge
This commit is contained in:
commit
3a32124e5c
@ -89,6 +89,7 @@ public interface Address {
|
||||
public Address getAddressAt (long offset) throws UnmappedAddressException, UnalignedAddressException;
|
||||
/** Returns the decoded address at the given offset */
|
||||
public Address getCompOopAddressAt (long offset) throws UnmappedAddressException, UnalignedAddressException;
|
||||
public Address getCompKlassAddressAt (long offset) throws UnmappedAddressException, UnalignedAddressException;
|
||||
|
||||
//
|
||||
// Java-related routines
|
||||
|
@ -121,6 +121,9 @@ public interface Debugger extends SymbolLookup, ThreadAccess {
|
||||
public long getHeapOopSize();
|
||||
public long getNarrowOopBase();
|
||||
public int getNarrowOopShift();
|
||||
public long getKlassPtrSize();
|
||||
public long getNarrowKlassBase();
|
||||
public int getNarrowKlassShift();
|
||||
|
||||
public ReadResult readBytesFromProcess(long address, long numBytes)
|
||||
throws DebuggerException;
|
||||
|
@ -58,6 +58,10 @@ public abstract class DebuggerBase implements Debugger {
|
||||
protected long heapOopSize;
|
||||
protected long narrowOopBase; // heap base for 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()
|
||||
private PageCache cache;
|
||||
|
||||
@ -159,10 +163,14 @@ public abstract class DebuggerBase implements Debugger {
|
||||
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.klassPtrSize = klassPtrSize;
|
||||
this.narrowOopBase = narrowOopBase;
|
||||
this.narrowOopShift = narrowOopShift;
|
||||
this.narrowKlassBase = narrowKlassBase;
|
||||
this.narrowKlassShift = narrowKlassShift;
|
||||
}
|
||||
|
||||
/** May be called by subclasses if desired to initialize the page
|
||||
@ -464,6 +472,15 @@ public abstract class DebuggerBase implements Debugger {
|
||||
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)
|
||||
throws UnmappedAddressException, UnalignedAddressException {
|
||||
writeCInteger(address, machDesc.getAddressSize(), value);
|
||||
@ -551,4 +568,15 @@ public abstract class DebuggerBase implements Debugger {
|
||||
public int getNarrowOopShift() {
|
||||
return narrowOopShift;
|
||||
}
|
||||
|
||||
public long getKlassPtrSize() {
|
||||
return klassPtrSize;
|
||||
}
|
||||
|
||||
public long getNarrowKlassBase() {
|
||||
return narrowKlassBase;
|
||||
}
|
||||
public int getNarrowKlassShift() {
|
||||
return narrowKlassShift;
|
||||
}
|
||||
}
|
||||
|
@ -42,5 +42,7 @@ public interface JVMDebugger extends Debugger {
|
||||
long jintSize,
|
||||
long jlongSize,
|
||||
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);
|
||||
}
|
||||
|
@ -79,6 +79,11 @@ class BsdAddress implements Address {
|
||||
return debugger.readCompOopAddress(addr + offset);
|
||||
}
|
||||
|
||||
public Address getCompKlassAddressAt(long offset)
|
||||
throws UnalignedAddressException, UnmappedAddressException {
|
||||
return debugger.readCompOopAddress(addr + offset);
|
||||
}
|
||||
|
||||
//
|
||||
// Java-related routines
|
||||
//
|
||||
|
@ -46,6 +46,7 @@ public interface BsdDebugger extends JVMDebugger {
|
||||
throws DebuggerException;
|
||||
public BsdAddress readAddress(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 readCompOopHandle(long address) throws DebuggerException;
|
||||
public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException;
|
||||
|
@ -431,6 +431,12 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
|
||||
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 */
|
||||
public BsdOopHandle readOopHandle(long address)
|
||||
throws UnmappedAddressException, UnalignedAddressException,
|
||||
|
@ -80,6 +80,10 @@ class DummyAddress implements Address {
|
||||
return new DummyAddress(debugger, badLong);
|
||||
}
|
||||
|
||||
public Address getCompKlassAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
|
||||
return new DummyAddress(debugger, badLong);
|
||||
}
|
||||
|
||||
//
|
||||
// Java-related routines
|
||||
//
|
||||
|
@ -79,6 +79,11 @@ class LinuxAddress implements Address {
|
||||
return debugger.readCompOopAddress(addr + offset);
|
||||
}
|
||||
|
||||
public Address getCompKlassAddressAt(long offset)
|
||||
throws UnalignedAddressException, UnmappedAddressException {
|
||||
return debugger.readCompKlassAddress(addr + offset);
|
||||
}
|
||||
|
||||
//
|
||||
// Java-related routines
|
||||
//
|
||||
|
@ -46,6 +46,7 @@ public interface LinuxDebugger extends JVMDebugger {
|
||||
throws DebuggerException;
|
||||
public LinuxAddress readAddress(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 readCompOopHandle(long address) throws DebuggerException;
|
||||
public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException;
|
||||
|
@ -429,6 +429,12 @@ public class LinuxDebuggerLocal extends DebuggerBase implements LinuxDebugger {
|
||||
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 */
|
||||
public LinuxOopHandle readOopHandle(long address)
|
||||
throws UnmappedAddressException, UnalignedAddressException,
|
||||
|
@ -76,6 +76,10 @@ class ProcAddress implements Address {
|
||||
return debugger.readCompOopAddress(addr + offset);
|
||||
}
|
||||
|
||||
public Address getCompKlassAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
|
||||
return debugger.readCompKlassAddress(addr + offset);
|
||||
}
|
||||
|
||||
//
|
||||
// Java-related routines
|
||||
//
|
||||
|
@ -47,6 +47,7 @@ public interface ProcDebugger extends JVMDebugger {
|
||||
throws DebuggerException;
|
||||
public ProcAddress readAddress(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 readCompOopHandle(long address) throws DebuggerException;
|
||||
public long[] getThreadIntegerRegisterSet(int tid) throws DebuggerException;
|
||||
|
@ -351,6 +351,12 @@ public class ProcDebuggerLocal extends DebuggerBase implements ProcDebugger {
|
||||
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 */
|
||||
public ProcOopHandle readOopHandle(long address)
|
||||
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
|
||||
|
@ -74,6 +74,9 @@ class RemoteAddress implements Address {
|
||||
public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
|
||||
return debugger.readCompOopAddress(addr + offset);
|
||||
}
|
||||
public Address getCompKlassAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
|
||||
return debugger.readCompKlassAddress(addr + offset);
|
||||
}
|
||||
|
||||
//
|
||||
// Java-related routines
|
||||
|
@ -68,6 +68,9 @@ public interface RemoteDebugger extends Remote {
|
||||
public long getHeapOopSize() throws RemoteException;
|
||||
public long getNarrowOopBase() 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,
|
||||
long addrOrId2, boolean isAddress2) throws RemoteException;
|
||||
|
@ -99,7 +99,10 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger {
|
||||
javaPrimitiveTypesConfigured = true;
|
||||
narrowOopBase = remoteDebugger.getNarrowOopBase();
|
||||
narrowOopShift = remoteDebugger.getNarrowOopShift();
|
||||
narrowKlassBase = remoteDebugger.getNarrowKlassBase();
|
||||
narrowKlassShift = remoteDebugger.getNarrowKlassShift();
|
||||
heapOopSize = remoteDebugger.getHeapOopSize();
|
||||
klassPtrSize = remoteDebugger.getKlassPtrSize();
|
||||
}
|
||||
catch (RemoteException e) {
|
||||
throw new DebuggerException(e);
|
||||
@ -319,6 +322,12 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger {
|
||||
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)
|
||||
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
|
||||
long value = readAddressValue(address);
|
||||
|
@ -126,6 +126,18 @@ public class RemoteDebuggerServer extends UnicastRemoteObject
|
||||
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,
|
||||
long addrOrId2, boolean isAddress2) throws RemoteException {
|
||||
ThreadProxy t1 = getThreadProxy(addrOrId1, isAddress1);
|
||||
|
@ -76,6 +76,10 @@ class WindbgAddress implements Address {
|
||||
return debugger.readCompOopAddress(addr + offset);
|
||||
}
|
||||
|
||||
public Address getCompKlassAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
|
||||
return debugger.readCompKlassAddress(addr + offset);
|
||||
}
|
||||
|
||||
//
|
||||
// Java-related routines
|
||||
//
|
||||
|
@ -46,6 +46,7 @@ public interface WindbgDebugger extends JVMDebugger {
|
||||
throws DebuggerException;
|
||||
public WindbgAddress readAddress(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 readCompOopHandle(long address) throws DebuggerException;
|
||||
|
||||
|
@ -321,6 +321,11 @@ public class WindbgDebuggerLocal extends DebuggerBase implements WindbgDebugger
|
||||
return (WindbgAddress) newAddress(readCompOopAddressValue(address));
|
||||
}
|
||||
|
||||
public WindbgAddress readCompKlassAddress(long address)
|
||||
throws UnmappedAddressException, UnalignedAddressException {
|
||||
return (WindbgAddress) newAddress(readCompKlassAddressValue(address));
|
||||
}
|
||||
|
||||
/** From the WindbgDebugger interface */
|
||||
public WindbgOopHandle readOopHandle(long address)
|
||||
throws UnmappedAddressException, UnalignedAddressException, NotInHeapException {
|
||||
|
@ -53,6 +53,8 @@ public class Universe {
|
||||
|
||||
private static AddressField narrowOopBaseField;
|
||||
private static CIntegerField narrowOopShiftField;
|
||||
private static AddressField narrowKlassBaseField;
|
||||
private static CIntegerField narrowKlassShiftField;
|
||||
|
||||
static {
|
||||
VM.registerVMInitializedObserver(new Observer() {
|
||||
@ -86,6 +88,8 @@ public class Universe {
|
||||
|
||||
narrowOopBaseField = type.getAddressField("_narrow_oop._base");
|
||||
narrowOopShiftField = type.getCIntegerField("_narrow_oop._shift");
|
||||
narrowKlassBaseField = type.getAddressField("_narrow_klass._base");
|
||||
narrowKlassShiftField = type.getCIntegerField("_narrow_klass._shift");
|
||||
}
|
||||
|
||||
public Universe() {
|
||||
@ -111,6 +115,19 @@ public class Universe {
|
||||
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. */
|
||||
public boolean isIn(Address p) {
|
||||
return heap().isIn(p);
|
||||
|
@ -59,7 +59,7 @@ public class Array extends Oop {
|
||||
if (headerSize != 0) {
|
||||
return headerSize;
|
||||
}
|
||||
if (VM.getVM().isCompressedHeadersEnabled()) {
|
||||
if (VM.getVM().isCompressedKlassPointersEnabled()) {
|
||||
headerSize = typeSize;
|
||||
} else {
|
||||
headerSize = VM.getVM().alignUp(typeSize + VM.getVM().getIntSize(),
|
||||
@ -80,7 +80,7 @@ public class Array extends Oop {
|
||||
if (lengthOffsetInBytes != 0) {
|
||||
return lengthOffsetInBytes;
|
||||
}
|
||||
if (VM.getVM().isCompressedHeadersEnabled()) {
|
||||
if (VM.getVM().isCompressedKlassPointersEnabled()) {
|
||||
lengthOffsetInBytes = typeSize - VM.getVM().getIntSize();
|
||||
} else {
|
||||
lengthOffsetInBytes = typeSize;
|
||||
|
@ -53,7 +53,7 @@ public class Instance extends Oop {
|
||||
|
||||
// Returns header size in bytes.
|
||||
public static long getHeaderSize() {
|
||||
if (VM.getVM().isCompressedHeadersEnabled()) {
|
||||
if (VM.getVM().isCompressedKlassPointersEnabled()) {
|
||||
return typeSize - VM.getVM().getIntSize();
|
||||
} else {
|
||||
return typeSize;
|
||||
|
@ -27,7 +27,6 @@ package sun.jvm.hotspot.oops;
|
||||
import sun.jvm.hotspot.runtime.VMObject;
|
||||
import sun.jvm.hotspot.debugger.*;
|
||||
|
||||
// The class for an C int field simply provides access to the value.
|
||||
public class MetadataField extends Field {
|
||||
|
||||
public MetadataField(sun.jvm.hotspot.types.AddressField vmField, long startOffset) {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -47,10 +47,7 @@ public class Oop {
|
||||
Type type = db.lookupType("oopDesc");
|
||||
mark = new CIntField(type.getCIntegerField("_mark"), 0);
|
||||
klass = new MetadataField(type.getAddressField("_metadata._klass"), 0);
|
||||
if (VM.getVM().isCompressedHeadersEnabled()) {
|
||||
// compressedKlass = new CIntField(type.getCIntegerField("_metadata._compressed_klass"), 0);
|
||||
throw new InternalError("unimplemented");
|
||||
}
|
||||
compressedKlass = new NarrowKlassField(type.getAddressField("_metadata._compressed_klass"), 0);
|
||||
headerSize = type.getSize();
|
||||
}
|
||||
|
||||
@ -74,13 +71,13 @@ public class Oop {
|
||||
|
||||
private static CIntField mark;
|
||||
private static MetadataField klass;
|
||||
private static CIntField compressedKlass;
|
||||
private static NarrowKlassField compressedKlass;
|
||||
|
||||
// Accessors for declared fields
|
||||
public Mark getMark() { return new Mark(getHandle()); }
|
||||
public Klass getKlass() {
|
||||
if (VM.getVM().isCompressedHeadersEnabled()) {
|
||||
throw new InternalError("unimplemented");
|
||||
if (VM.getVM().isCompressedKlassPointersEnabled()) {
|
||||
return (Klass)compressedKlass.getValue(getHandle());
|
||||
} else {
|
||||
return (Klass)klass.getValue(getHandle());
|
||||
}
|
||||
@ -150,7 +147,7 @@ public class Oop {
|
||||
void iterateFields(OopVisitor visitor, boolean doVMFields) {
|
||||
if (doVMFields) {
|
||||
visitor.doCInt(mark, true);
|
||||
if (VM.getVM().isCompressedHeadersEnabled()) {
|
||||
if (VM.getVM().isCompressedKlassPointersEnabled()) {
|
||||
throw new InternalError("unimplemented");
|
||||
} else {
|
||||
visitor.doMetadata(klass, true);
|
||||
@ -210,8 +207,8 @@ public class Oop {
|
||||
if (handle == null) {
|
||||
return null;
|
||||
}
|
||||
if (VM.getVM().isCompressedHeadersEnabled()) {
|
||||
throw new InternalError("Unimplemented");
|
||||
if (VM.getVM().isCompressedKlassPointersEnabled()) {
|
||||
return (Klass)Metadata.instantiateWrapperFor(handle.getCompKlassAddressAt(compressedKlass.getOffset()));
|
||||
} else {
|
||||
return (Klass)Metadata.instantiateWrapperFor(handle.getAddressAt(klass.getOffset()));
|
||||
}
|
||||
|
@ -63,11 +63,7 @@ public class java_lang_Class {
|
||||
|
||||
/** get Klass* field at offset hc_klass_offset from a java.lang.Class object */
|
||||
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 */
|
||||
|
@ -103,6 +103,7 @@ public class VM {
|
||||
private int logMinObjAlignmentInBytes;
|
||||
private int heapWordSize;
|
||||
private int heapOopSize;
|
||||
private int klassPtrSize;
|
||||
private int oopSize;
|
||||
/** This is only present in a non-core build */
|
||||
private CodeCache codeCache;
|
||||
@ -129,7 +130,7 @@ public class VM {
|
||||
private static CIntegerType boolType;
|
||||
private Boolean sharingEnabled;
|
||||
private Boolean compressedOopsEnabled;
|
||||
private Boolean compressedHeadersEnabled;
|
||||
private Boolean compressedKlassPointersEnabled;
|
||||
|
||||
// command line flags supplied to VM - see struct Flag in globals.hpp
|
||||
public static final class Flag {
|
||||
@ -350,6 +351,12 @@ public class VM {
|
||||
} else {
|
||||
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 */
|
||||
@ -374,8 +381,9 @@ public class VM {
|
||||
((Observer) iter.next()).update(null, null);
|
||||
}
|
||||
|
||||
debugger.putHeapConst(soleInstance.getHeapOopSize(), Universe.getNarrowOopBase(),
|
||||
Universe.getNarrowOopShift());
|
||||
debugger.putHeapConst(soleInstance.getHeapOopSize(), soleInstance.getKlassPtrSize(),
|
||||
Universe.getNarrowOopBase(), Universe.getNarrowOopShift(),
|
||||
Universe.getNarrowKlassBase(), Universe.getNarrowKlassShift());
|
||||
}
|
||||
|
||||
/** This is used by the debugging system */
|
||||
@ -536,6 +544,10 @@ public class VM {
|
||||
public int getHeapOopSize() {
|
||||
return heapOopSize;
|
||||
}
|
||||
|
||||
public int getKlassPtrSize() {
|
||||
return klassPtrSize;
|
||||
}
|
||||
/** Utility routine for getting data structure alignment correct */
|
||||
public long alignUp(long size, long alignment) {
|
||||
return (size + alignment - 1) & ~(alignment - 1);
|
||||
@ -784,13 +796,13 @@ public class VM {
|
||||
return compressedOopsEnabled.booleanValue();
|
||||
}
|
||||
|
||||
public boolean isCompressedHeadersEnabled() {
|
||||
if (compressedHeadersEnabled == null) {
|
||||
Flag flag = getCommandLineFlag("UseCompressedHeaders");
|
||||
compressedHeadersEnabled = (flag == null) ? Boolean.FALSE:
|
||||
public boolean isCompressedKlassPointersEnabled() {
|
||||
if (compressedKlassPointersEnabled == null) {
|
||||
Flag flag = getCommandLineFlag("UseCompressedKlassPointers");
|
||||
compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE:
|
||||
(flag.getBool()? Boolean.TRUE: Boolean.FALSE);
|
||||
}
|
||||
return compressedHeadersEnabled.booleanValue();
|
||||
return compressedKlassPointersEnabled.booleanValue();
|
||||
}
|
||||
|
||||
public int getObjectAlignmentInBytes() {
|
||||
|
@ -53,9 +53,8 @@ public class RobustOopDeterminator {
|
||||
private static void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("oopDesc");
|
||||
|
||||
if (VM.getVM().isCompressedHeadersEnabled()) {
|
||||
// klassField = type.getNarrowOopField("_metadata._compressed_klass");
|
||||
throw new InternalError("unimplemented");
|
||||
if (VM.getVM().isCompressedKlassPointersEnabled()) {
|
||||
klassField = type.getAddressField("_metadata._compressed_klass");
|
||||
} else {
|
||||
klassField = type.getAddressField("_metadata._klass");
|
||||
}
|
||||
@ -70,7 +69,11 @@ public class RobustOopDeterminator {
|
||||
}
|
||||
try {
|
||||
// Try to instantiate the Klass
|
||||
Metadata.instantiateWrapperFor(klassField.getValue(oop));
|
||||
if (VM.getVM().isCompressedKlassPointersEnabled()) {
|
||||
Metadata.instantiateWrapperFor(oop.getCompKlassAddressAt(klassField.getOffset()));
|
||||
} else {
|
||||
Metadata.instantiateWrapperFor(klassField.getValue(oop));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (AddressException e) {
|
||||
|
@ -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.
|
||||
$(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 ] ; \
|
||||
then rm -f $@; mv $@.tmp $@; \
|
||||
else rm -f $@.tmp; \
|
||||
fi
|
||||
|
||||
$(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 ] ; \
|
||||
then rm -f $@; mv $@.tmp $@; \
|
||||
else rm -f $@.tmp; \
|
||||
fi
|
||||
|
||||
$(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 ] ; \
|
||||
then rm -f $@; mv $@.tmp $@; \
|
||||
else rm -f $@.tmp; \
|
||||
|
@ -206,15 +206,15 @@ CONDITIONALLY_UPDATE_JVMOFFS_TARGET = \
|
||||
|
||||
# $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
|
||||
$(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)
|
||||
|
||||
$(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)
|
||||
|
||||
$(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)
|
||||
|
||||
$(JVMOFFS.o): $(JVMOFFS).h $(JVMOFFS).cpp
|
||||
|
@ -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) {
|
||||
while (offset() % modulus != 0) nop();
|
||||
@ -4660,7 +4675,7 @@ void MacroAssembler::load_klass(Register src_oop, Register klass) {
|
||||
// if this changes, change that.
|
||||
if (UseCompressedKlassPointers) {
|
||||
lduw(src_oop, oopDesc::klass_offset_in_bytes(), klass);
|
||||
decode_heap_oop_not_null(klass);
|
||||
decode_klass_not_null(klass);
|
||||
} else {
|
||||
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) {
|
||||
if (UseCompressedKlassPointers) {
|
||||
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());
|
||||
} else {
|
||||
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.
|
||||
// Also do not verify_oop as this is called by verify_oop.
|
||||
assert (UseCompressedOops, "must be compressed");
|
||||
assert (Universe::heap() != NULL, "java heap should be initialized");
|
||||
assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
|
||||
sllx(src, LogMinObjAlignmentInBytes, dst);
|
||||
if (Universe::narrow_oop_base() != NULL)
|
||||
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() {
|
||||
if (UseCompressedOops) {
|
||||
// call indirectly to solve generation ordering problem
|
||||
AddressLiteral base(Universe::narrow_oop_base_addr());
|
||||
if (UseCompressedOops || UseCompressedKlassPointers) {
|
||||
AddressLiteral base(Universe::narrow_ptrs_base_addr());
|
||||
load_ptr_contents(base, G6_heapbase);
|
||||
}
|
||||
}
|
||||
|
@ -2280,6 +2280,11 @@ public:
|
||||
void encode_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
|
||||
// thread-local information).
|
||||
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
|
||||
|
||||
void set_narrow_oop( jobject obj, Register d );
|
||||
void set_narrow_klass( Klass* k, Register d );
|
||||
|
||||
// nop padding
|
||||
void align(int modulus);
|
||||
|
@ -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 (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 (src->is_address() && Assembler::is_simm13(src->as_address_ptr()->disp())) {
|
||||
return !PatchALot;
|
||||
@ -969,8 +974,18 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case T_METADATA:
|
||||
case T_ADDRESS: __ ld_ptr(base, offset, to_reg->as_register()); break;
|
||||
case T_METADATA: __ 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_OBJECT:
|
||||
{
|
||||
@ -2344,7 +2359,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
|
||||
if (UseCompressedKlassPointers) {
|
||||
// tmp holds the default type. It currently comes uncompressed after the
|
||||
// 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
|
||||
// uncompressed values directly.
|
||||
__ lduw(dst, oopDesc::klass_offset_in_bytes(), tmp2);
|
||||
|
@ -189,7 +189,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
|
||||
if (UseCompressedKlassPointers) {
|
||||
// Save klass
|
||||
mov(klass, t1);
|
||||
encode_heap_oop_not_null(t1);
|
||||
encode_klass_not_null(t1);
|
||||
stw(t1, obj, oopDesc::klass_offset_in_bytes());
|
||||
} else {
|
||||
st_ptr(klass, obj, oopDesc::klass_offset_in_bytes());
|
||||
|
@ -208,8 +208,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
|
||||
Register O1_scratch = O1;
|
||||
Register O4_param_size = O4; // size of parameters
|
||||
|
||||
address code_start = __ pc();
|
||||
|
||||
// here's where control starts out:
|
||||
__ align(CodeEntryAlignment);
|
||||
address entry_point = __ pc();
|
||||
@ -252,22 +250,9 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
|
||||
// O4_first_arg_addr is live!
|
||||
|
||||
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)
|
||||
__ 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) {
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -58,5 +58,3 @@ public:
|
||||
Register recv, Register method_temp,
|
||||
Register temp2, Register temp3,
|
||||
bool for_compiler_entry);
|
||||
|
||||
static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
|
||||
|
@ -97,8 +97,8 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
|
||||
jint inst2;
|
||||
guarantee(Assembler::inv_op2(inst)==Assembler::sethi_op2, "must be sethi");
|
||||
if (format() != 0) {
|
||||
assert(type() == relocInfo::oop_type, "only narrow oops case");
|
||||
jint np = oopDesc::encode_heap_oop((oop)x);
|
||||
assert(type() == relocInfo::oop_type || type() == relocInfo::metadata_type, "only narrow oops or klasses case");
|
||||
jint np = type() == relocInfo::oop_type ? oopDesc::encode_heap_oop((oop)x) : oopDesc::encode_klass((Klass*)x);
|
||||
inst &= ~Assembler::hi22(-1);
|
||||
inst |= Assembler::hi22((intptr_t)np);
|
||||
if (verify_only) {
|
||||
|
@ -557,9 +557,9 @@ int MachCallDynamicJavaNode::ret_addr_offset() {
|
||||
int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size();
|
||||
int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes();
|
||||
int klass_load_size;
|
||||
if (UseCompressedOops && UseCompressedKlassPointers) {
|
||||
if (UseCompressedKlassPointers) {
|
||||
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()
|
||||
else
|
||||
klass_load_size = 3*BytesPerInstWord;
|
||||
@ -1707,11 +1707,11 @@ uint reloc_java_to_interp() {
|
||||
void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
|
||||
st->print_cr("\nUEP:");
|
||||
#ifdef _LP64
|
||||
if (UseCompressedOops) {
|
||||
if (UseCompressedKlassPointers) {
|
||||
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("\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");
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
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?
|
||||
// Intel can load a float constant from a direct address, requiring no
|
||||
// extra registers. Most RISCs will have to materialize an address into a
|
||||
@ -2602,9 +2608,9 @@ encode %{
|
||||
int off = __ offset();
|
||||
__ load_klass(O0, G3_scratch);
|
||||
int klass_load_size;
|
||||
if (UseCompressedOops && UseCompressedKlassPointers) {
|
||||
if (UseCompressedKlassPointers) {
|
||||
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;
|
||||
else
|
||||
klass_load_size = 3*BytesPerInstWord;
|
||||
@ -3610,6 +3616,15 @@ operand immN()
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
operand immNKlass()
|
||||
%{
|
||||
match(ConNKlass);
|
||||
|
||||
op_cost(10);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// NULL Pointer Immediate
|
||||
operand immN0()
|
||||
%{
|
||||
@ -5870,8 +5885,8 @@ instruct loadI2L_immI(iRegL dst, memory mem, immI mask, iRegL tmp) %{
|
||||
%}
|
||||
|
||||
// Load Unsigned Integer into a Long Register
|
||||
instruct loadUI2L(iRegL dst, memory mem) %{
|
||||
match(Set dst (LoadUI2L mem));
|
||||
instruct loadUI2L(iRegL dst, memory mem, immL_32bits mask) %{
|
||||
match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
|
||||
size(4);
|
||||
@ -6159,6 +6174,17 @@ instruct loadConN(iRegN dst, immN src) %{
|
||||
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).
|
||||
instruct loadConL_set64(iRegL dst, immL_cheap con, o7RegL tmp) %{
|
||||
match(Set dst con);
|
||||
@ -6475,6 +6501,25 @@ instruct storeN(memory dst, iRegN src) %{
|
||||
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) %{
|
||||
match(Set dst (StoreN dst src));
|
||||
ins_cost(MEMORY_REF_COST);
|
||||
@ -6582,6 +6627,23 @@ instruct decodeHeapOop_not_null(iRegP dst, iRegN src) %{
|
||||
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-----------------------------------------------
|
||||
// Memory barrier flavors
|
||||
|
@ -117,6 +117,7 @@ void VM_Version::initialize() {
|
||||
// 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.
|
||||
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
|
||||
Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes);
|
||||
#endif // _LP64
|
||||
#ifdef COMPILER2
|
||||
// Indirect branch is the same cost as direct
|
||||
|
@ -220,13 +220,13 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
|
||||
const int basic = 5*BytesPerInstWord +
|
||||
// shift;add for load_klass (only shift with zero heap based)
|
||||
(UseCompressedKlassPointers ?
|
||||
((Universe::narrow_oop_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0);
|
||||
((Universe::narrow_klass_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0);
|
||||
return basic + slop;
|
||||
} else {
|
||||
const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord +
|
||||
// shift;add for load_klass (only shift with zero heap based)
|
||||
(UseCompressedKlassPointers ?
|
||||
((Universe::narrow_oop_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0);
|
||||
((Universe::narrow_klass_base() == NULL) ? BytesPerInstWord : 2*BytesPerInstWord) : 0);
|
||||
return (basic + slop);
|
||||
}
|
||||
}
|
||||
|
@ -6916,7 +6916,7 @@ void MacroAssembler::call_VM_base(Register oop_result,
|
||||
#ifdef ASSERT
|
||||
// TraceBytecodes does not use r12 but saves it over the call, so don't verify
|
||||
// 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
|
||||
|
||||
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
|
||||
if (UseCompressedKlassPointers) {
|
||||
movl(dst, Address(src, oopDesc::klass_offset_in_bytes()));
|
||||
decode_heap_oop_not_null(dst);
|
||||
decode_klass_not_null(dst);
|
||||
} else
|
||||
#endif
|
||||
movptr(dst, Address(src, oopDesc::klass_offset_in_bytes()));
|
||||
@ -10027,15 +10027,10 @@ void MacroAssembler::load_prototype_header(Register dst, Register src) {
|
||||
if (UseCompressedKlassPointers) {
|
||||
assert (Universe::heap() != NULL, "java heap should be initialized");
|
||||
movl(dst, Address(src, oopDesc::klass_offset_in_bytes()));
|
||||
if (Universe::narrow_oop_shift() != 0) {
|
||||
assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
|
||||
if (LogMinObjAlignmentInBytes == Address::times_8) {
|
||||
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()));
|
||||
}
|
||||
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?");
|
||||
movq(dst, Address(r12_heapbase, dst, Address::times_8, Klass::prototype_header_offset()));
|
||||
} else {
|
||||
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) {
|
||||
#ifdef _LP64
|
||||
if (UseCompressedKlassPointers) {
|
||||
encode_heap_oop_not_null(src);
|
||||
encode_klass_not_null(src);
|
||||
movl(Address(dst, oopDesc::klass_offset_in_bytes()), src);
|
||||
} else
|
||||
#endif
|
||||
@ -10132,12 +10127,12 @@ void MacroAssembler::store_klass_gap(Register dst, Register src) {
|
||||
|
||||
#ifdef ASSERT
|
||||
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");
|
||||
if (CheckCompressedOops) {
|
||||
Label ok;
|
||||
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);
|
||||
STOP(msg);
|
||||
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) {
|
||||
assert (UseCompressedOops, "should only be used for compressed headers");
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
assert (UseCompressedOops, "should only be used for compressed headers");
|
||||
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);
|
||||
}
|
||||
|
||||
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() {
|
||||
if (UseCompressedOops) {
|
||||
movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_oop_base_addr()));
|
||||
if (UseCompressedOops || UseCompressedKlassPointers) {
|
||||
movptr(r12_heapbase, ExternalAddress((address)Universe::narrow_ptrs_base_addr()));
|
||||
}
|
||||
}
|
||||
#endif // _LP64
|
||||
|
@ -2083,6 +2083,15 @@ class MacroAssembler: public Assembler {
|
||||
void cmp_narrow_oop(Register 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
|
||||
void reinit_heapbase();
|
||||
|
||||
|
@ -148,7 +148,7 @@
|
||||
|
||||
static int adjust_reg_range(int range) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -340,7 +340,7 @@ int LIR_Assembler::check_icache() {
|
||||
Register receiver = FrameMap::receiver_opr->as_register();
|
||||
Register ic_klass = IC_Klass;
|
||||
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) {
|
||||
// insert some nops so that the verified entry point is aligned on CodeEntryAlignment
|
||||
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;
|
||||
|
||||
case T_ADDRESS:
|
||||
__ movptr(dest->as_register(), from_addr);
|
||||
if (UseCompressedKlassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) {
|
||||
__ movl(dest->as_register(), from_addr);
|
||||
} else {
|
||||
__ movptr(dest->as_register(), from_addr);
|
||||
}
|
||||
break;
|
||||
case T_INT:
|
||||
__ 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
|
||||
__ 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) {
|
||||
klass_RInfo = dst;
|
||||
}
|
||||
if (k->is_loaded() && !UseCompressedOops) {
|
||||
if (k->is_loaded() && !UseCompressedKlassPointers) {
|
||||
select_different_registers(obj, dst, k_RInfo, klass_RInfo);
|
||||
} else {
|
||||
Rtmp1 = op->tmp3()->as_register();
|
||||
@ -3446,7 +3456,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
|
||||
__ mov_metadata(tmp, default_type->constant_encoding());
|
||||
#ifdef _LP64
|
||||
if (UseCompressedKlassPointers) {
|
||||
__ encode_heap_oop(tmp);
|
||||
__ encode_klass_not_null(tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1166,7 +1166,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) {
|
||||
}
|
||||
LIR_Opr reg = rlock_result(x);
|
||||
LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
|
||||
if (!x->klass()->is_loaded() || UseCompressedOops) {
|
||||
if (!x->klass()->is_loaded() || UseCompressedKlassPointers) {
|
||||
tmp3 = new_register(objectType);
|
||||
}
|
||||
__ checkcast(reg, obj.result(), x->klass(),
|
||||
@ -1188,7 +1188,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) {
|
||||
}
|
||||
obj.load_item();
|
||||
LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
|
||||
if (!x->klass()->is_loaded() || UseCompressedOops) {
|
||||
if (!x->klass()->is_loaded() || UseCompressedKlassPointers) {
|
||||
tmp3 = new_register(objectType);
|
||||
}
|
||||
__ instanceof(reg, obj.result(), x->klass(),
|
||||
|
@ -159,7 +159,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
|
||||
#ifdef _LP64
|
||||
if (UseCompressedKlassPointers) { // Take care not to kill klass
|
||||
movptr(t1, klass);
|
||||
encode_heap_oop_not_null(t1);
|
||||
encode_klass_not_null(t1);
|
||||
movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1);
|
||||
} else
|
||||
#endif
|
||||
|
@ -209,8 +209,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
|
||||
Register rcx_mh = rcx; // MH receiver; dies quickly and is recycled
|
||||
Register rbx_method = rbx; // eventual target of this invocation
|
||||
|
||||
address code_start = __ pc();
|
||||
|
||||
// here's where control starts out:
|
||||
__ align(CodeEntryAlignment);
|
||||
address entry_point = __ pc();
|
||||
@ -251,23 +249,7 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
|
||||
|
||||
// rdx_first_arg_addr is live!
|
||||
|
||||
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);
|
||||
// note: stub look for mh in rcx
|
||||
trace_method_handle(_masm, qname);
|
||||
}
|
||||
trace_method_handle_interpreter_entry(_masm, iid);
|
||||
|
||||
if (iid == vmIntrinsics::_invokeBasic) {
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -55,8 +55,6 @@ public:
|
||||
Register temp2,
|
||||
bool for_compiler_entry);
|
||||
|
||||
static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN;
|
||||
|
||||
static Register saved_last_sp_register() {
|
||||
// Should be in sharedRuntime, not here.
|
||||
return LP64_ONLY(r13) NOT_LP64(rsi);
|
||||
|
@ -212,11 +212,11 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
|
||||
if (is_vtable_stub) {
|
||||
// Vtable stub size
|
||||
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 {
|
||||
// Itable stub size
|
||||
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
|
||||
// +PrintMiscellaneous and +WizardMode to see information about
|
||||
|
@ -1424,6 +1424,11 @@ bool Matcher::narrow_oop_use_complex_address() {
|
||||
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?
|
||||
// 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.
|
||||
bool is_operand_hi32_zero(Node* n) {
|
||||
int opc = n->Opcode();
|
||||
if (opc == Op_LoadUI2L) {
|
||||
return true;
|
||||
}
|
||||
if (opc == Op_AndL) {
|
||||
Node* o2 = n->in(2);
|
||||
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
|
||||
instruct loadUI2L(eRegL dst, memory mem, eFlagsReg cr) %{
|
||||
match(Set dst (LoadUI2L mem));
|
||||
instruct loadUI2L(eRegL dst, memory mem, immL_32bits mask, eFlagsReg cr) %{
|
||||
match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
|
||||
effect(KILL cr);
|
||||
|
||||
ins_cost(250);
|
||||
|
@ -1409,10 +1409,10 @@ uint reloc_java_to_interp()
|
||||
#ifndef PRODUCT
|
||||
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");
|
||||
if (Universe::narrow_oop_shift() != 0) {
|
||||
st->print_cr("\tdecode_heap_oop_not_null rscratch1, rscratch1");
|
||||
if (Universe::narrow_klass_shift() != 0) {
|
||||
st->print_cr("\tdecode_klass_not_null rscratch1, rscratch1");
|
||||
}
|
||||
st->print_cr("\tcmpq rax, rscratch1\t # Inline cache check");
|
||||
} else {
|
||||
@ -1428,7 +1428,7 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const
|
||||
{
|
||||
MacroAssembler masm(&cbuf);
|
||||
uint insts_size = cbuf.insts_size();
|
||||
if (UseCompressedOops) {
|
||||
if (UseCompressedKlassPointers) {
|
||||
masm.load_klass(rscratch1, j_rarg0);
|
||||
masm.cmpptr(rax, rscratch1);
|
||||
} else {
|
||||
@ -1576,6 +1576,11 @@ bool Matcher::narrow_oop_use_complex_address() {
|
||||
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
|
||||
// memory? Intel can load a float constant from a direct address,
|
||||
// requiring no extra registers. Most RISCs will have to materialize
|
||||
@ -3139,6 +3144,14 @@ operand immN() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
operand immNKlass() %{
|
||||
match(ConNKlass);
|
||||
|
||||
op_cost(10);
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// NULL Pointer Immediate
|
||||
operand immN0() %{
|
||||
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--------------------------------------------
|
||||
// Stack Slot Operand - This operand is used for loading and storing temporary
|
||||
@ -4209,7 +4361,11 @@ opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex,
|
||||
indCompressedOopOffset,
|
||||
indirectNarrow, indOffset8Narrow, indOffset32Narrow,
|
||||
indIndexOffsetNarrow, indIndexNarrow, indIndexScaleNarrow,
|
||||
indIndexScaleOffsetNarrow, indPosIndexScaleOffsetNarrow);
|
||||
indIndexScaleOffsetNarrow, indPosIndexScaleOffsetNarrow,
|
||||
indCompressedKlassOffset,
|
||||
indirectNarrowKlass, indOffset8NarrowKlass, indOffset32NarrowKlass,
|
||||
indIndexOffsetNarrowKlass, indIndexNarrowKlass, indIndexScaleNarrowKlass,
|
||||
indIndexScaleOffsetNarrowKlass, indPosIndexScaleOffsetNarrowKlass);
|
||||
|
||||
//----------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
|
||||
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);
|
||||
format %{ "movl $dst, $mem\t# uint -> long" %}
|
||||
@ -5469,6 +5625,22 @@ instruct loadConN(rRegN dst, immN src) %{
|
||||
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)
|
||||
%{
|
||||
match(Set dst src);
|
||||
@ -5738,7 +5910,7 @@ instruct storeP(memory mem, any_RegP src)
|
||||
|
||||
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));
|
||||
|
||||
ins_cost(125); // XXX
|
||||
@ -5774,9 +5946,21 @@ instruct storeN(memory mem, rRegN src)
|
||||
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)
|
||||
%{
|
||||
predicate(Universe::narrow_oop_base() == NULL);
|
||||
predicate(Universe::narrow_oop_base() == NULL && Universe::narrow_klass_base() == NULL);
|
||||
match(Set mem (StoreN mem zero));
|
||||
|
||||
ins_cost(125); // XXX
|
||||
@ -5804,10 +5988,22 @@ instruct storeImmN(memory mem, immN src)
|
||||
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
|
||||
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));
|
||||
|
||||
ins_cost(125); // XXX
|
||||
@ -5832,7 +6028,7 @@ instruct storeImmI(memory mem, immI src)
|
||||
// Store Long Immediate
|
||||
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));
|
||||
|
||||
ins_cost(125); // XXX
|
||||
@ -5857,7 +6053,7 @@ instruct storeImmL(memory mem, immL32 src)
|
||||
// Store Short/Char Immediate
|
||||
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));
|
||||
|
||||
ins_cost(125); // XXX
|
||||
@ -5883,7 +6079,7 @@ instruct storeImmI16(memory mem, immI16 src)
|
||||
// Store Byte Immediate
|
||||
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));
|
||||
|
||||
ins_cost(125); // XXX
|
||||
@ -5908,7 +6104,7 @@ instruct storeImmB(memory mem, immI8 src)
|
||||
// Store CMS card-mark Immediate
|
||||
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));
|
||||
|
||||
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)
|
||||
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));
|
||||
|
||||
ins_cost(25); // XXX
|
||||
@ -5996,7 +6192,7 @@ instruct storeD0_imm(memory mem, immD0 src)
|
||||
|
||||
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));
|
||||
|
||||
ins_cost(25); // XXX
|
||||
@ -6482,6 +6678,32 @@ instruct decodeHeapOop_not_null(rRegP dst, rRegN src, rFlagsReg cr) %{
|
||||
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---------------------------------------------------
|
||||
// Jump
|
||||
@ -10452,7 +10674,7 @@ instruct testP_mem(rFlagsReg cr, memory op, 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));
|
||||
|
||||
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);
|
||||
%}
|
||||
|
||||
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) %{
|
||||
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)
|
||||
%{
|
||||
predicate(Universe::narrow_oop_base() == NULL);
|
||||
predicate(Universe::narrow_oop_base() == NULL && (Universe::narrow_klass_base() == NULL));
|
||||
match(Set cr (CmpN (LoadN mem) zero));
|
||||
|
||||
format %{ "cmpl R12, $mem\t# compressed ptr (R12_heapbase==0)" %}
|
||||
|
@ -267,8 +267,8 @@ int generateJvmOffsets(GEN_variant gen_variant) {
|
||||
|
||||
printf("\n");
|
||||
|
||||
GEN_OFFS(NarrowOopStruct, _base);
|
||||
GEN_OFFS(NarrowOopStruct, _shift);
|
||||
GEN_OFFS(NarrowPtrStruct, _base);
|
||||
GEN_OFFS(NarrowPtrStruct, _shift);
|
||||
printf("\n");
|
||||
|
||||
GEN_VALUE(SIZE_HeapBlockHeader, (int) sizeof(HeapBlock::Header));
|
||||
|
@ -45,10 +45,6 @@ extern pointer __JvmOffsets;
|
||||
|
||||
extern pointer __1cJCodeCacheF_heap_;
|
||||
extern pointer __1cIUniverseO_collectedHeap_;
|
||||
extern pointer __1cIUniverseL_narrow_oop_;
|
||||
#ifdef _LP64
|
||||
extern pointer UseCompressedOops;
|
||||
#endif
|
||||
|
||||
extern pointer __1cHnmethodG__vtbl_;
|
||||
extern pointer __1cNMethodG__vtbl_;
|
||||
@ -136,8 +132,8 @@ dtrace:helper:ustack:
|
||||
copyin_offset(SIZE_oopDesc);
|
||||
copyin_offset(SIZE_ConstantPool);
|
||||
|
||||
copyin_offset(OFFSET_NarrowOopStruct_base);
|
||||
copyin_offset(OFFSET_NarrowOopStruct_shift);
|
||||
copyin_offset(OFFSET_NarrowPtrStruct_base);
|
||||
copyin_offset(OFFSET_NarrowPtrStruct_shift);
|
||||
|
||||
/*
|
||||
* The PC to translate is in arg0.
|
||||
@ -159,17 +155,6 @@ dtrace:helper:ustack:
|
||||
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 +
|
||||
OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
|
||||
|
||||
|
@ -44,7 +44,7 @@ void VMError::show_message_box(char *buf, int buflen) {
|
||||
jio_snprintf(p, buflen - len,
|
||||
"\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"
|
||||
"Otherwise, press RETURN to abort...",
|
||||
os::current_process_id(), os::current_process_id(),
|
||||
|
@ -262,8 +262,8 @@ int generateJvmOffsets(GEN_variant gen_variant) {
|
||||
|
||||
printf("\n");
|
||||
|
||||
GEN_OFFS(NarrowOopStruct, _base);
|
||||
GEN_OFFS(NarrowOopStruct, _shift);
|
||||
GEN_OFFS(NarrowPtrStruct, _base);
|
||||
GEN_OFFS(NarrowPtrStruct, _shift);
|
||||
printf("\n");
|
||||
|
||||
GEN_VALUE(SIZE_HeapBlockHeader, sizeof(HeapBlock::Header));
|
||||
|
@ -45,10 +45,6 @@ extern pointer __JvmOffsets;
|
||||
|
||||
extern pointer __1cJCodeCacheF_heap_;
|
||||
extern pointer __1cIUniverseO_collectedHeap_;
|
||||
extern pointer __1cIUniverseL_narrow_oop_;
|
||||
#ifdef _LP64
|
||||
extern pointer UseCompressedOops;
|
||||
#endif
|
||||
|
||||
extern pointer __1cHnmethodG__vtbl_;
|
||||
extern pointer __1cGMethodG__vtbl_;
|
||||
@ -136,8 +132,8 @@ dtrace:helper:ustack:
|
||||
copyin_offset(SIZE_oopDesc);
|
||||
copyin_offset(SIZE_ConstantPool);
|
||||
|
||||
copyin_offset(OFFSET_NarrowOopStruct_base);
|
||||
copyin_offset(OFFSET_NarrowOopStruct_shift);
|
||||
copyin_offset(OFFSET_NarrowPtrStruct_base);
|
||||
copyin_offset(OFFSET_NarrowPtrStruct_shift);
|
||||
|
||||
/*
|
||||
* The PC to translate is in arg0.
|
||||
@ -158,18 +154,6 @@ dtrace:helper:ustack:
|
||||
|
||||
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 +
|
||||
OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
|
||||
|
||||
|
@ -1392,7 +1392,7 @@ void ADLParser::pipe_parse(void) {
|
||||
_AD.addForm(machnode);
|
||||
}
|
||||
else if (!strcmp(ident, "attributes")) {
|
||||
bool vsi_seen = false, bhds_seen = false;
|
||||
bool vsi_seen = false;
|
||||
|
||||
skipws();
|
||||
if ( (_curchar != '%')
|
||||
@ -1436,7 +1436,6 @@ void ADLParser::pipe_parse(void) {
|
||||
}
|
||||
|
||||
pipeline->_branchHasDelaySlot = true;
|
||||
bhds_seen = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1639,6 +1638,12 @@ void ADLParser::resource_parse(PipelineForm &pipeline) {
|
||||
next_char(); // Skip "(" or ","
|
||||
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) {
|
||||
parse_err(SYNERR, "keyword identifier expected at \"%c\"\n", _curchar);
|
||||
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 rparen = 0; // position of instruction at this depth
|
||||
InstructForm *inst_seen = NULL;
|
||||
InstructForm *child_seen = NULL;
|
||||
|
||||
// Walk the match tree,
|
||||
// Record <parent, position, instruction name, input position>
|
||||
@ -2437,7 +2441,7 @@ InstructForm *ADLParser::peep_match_child_parse(PeepMatch &match, int parent, in
|
||||
if (_curchar == '(') {
|
||||
++lparen;
|
||||
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
|
||||
else if (_curchar == ')') {
|
||||
@ -3154,6 +3158,9 @@ void ADLParser::constant_parse_expression(EncClass* encoding, char* ec_name) {
|
||||
|
||||
|
||||
//------------------------------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* sizeOfInstr = NULL;
|
||||
|
||||
@ -4274,7 +4281,17 @@ char *ADLParser::get_ident_common(bool do_preproc) {
|
||||
|| ((c >= '0') && (c <= '9'))
|
||||
|| ((c == '_')) || ((c == ':')) || ((c == '#')) );
|
||||
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;
|
||||
}
|
||||
else {
|
||||
|
@ -221,6 +221,7 @@ ArchDesc::ArchDesc()
|
||||
_register = NULL;
|
||||
_encode = NULL;
|
||||
_pipeline = NULL;
|
||||
_frame = NULL;
|
||||
}
|
||||
|
||||
ArchDesc::~ArchDesc() {
|
||||
@ -648,7 +649,10 @@ int ArchDesc::instructFormCount() {
|
||||
// Return the textual binding for a given CPP flag name.
|
||||
// Return NULL if there is no binding, or it has been #undef-ed.
|
||||
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;
|
||||
}
|
||||
|
||||
@ -803,7 +807,9 @@ int ArchDesc::emit_msg(int quiet, int flag, int line, const char *fmt,
|
||||
while (i++ <= 15) fputc(' ', errfile);
|
||||
fprintf(errfile, "%-8s:", pref);
|
||||
vfprintf(errfile, fmt, args);
|
||||
fprintf(errfile, "\n"); }
|
||||
fprintf(errfile, "\n");
|
||||
fflush(errfile);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -855,8 +861,14 @@ const char *ArchDesc::reg_mask(OperandForm &opForm) {
|
||||
|
||||
// Check constraints on result's register class
|
||||
const char *result_class = opForm.constrained_reg_class();
|
||||
if (!result_class) opForm.dump();
|
||||
assert( result_class, "Resulting register class was not defined for operand");
|
||||
if (result_class == NULL) {
|
||||
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 );
|
||||
|
||||
return regMask;
|
||||
@ -865,8 +877,14 @@ const char *ArchDesc::reg_mask(OperandForm &opForm) {
|
||||
// Obtain the name of the RegMask for an InstructForm
|
||||
const char *ArchDesc::reg_mask(InstructForm &inForm) {
|
||||
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
|
||||
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
|
||||
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();
|
||||
if (oper == NULL) form->dump();
|
||||
assert( oper, "Result must be an OperandForm");
|
||||
if (oper == NULL) {
|
||||
syntax_err(inForm._linenum, "Form is not an OperandForm:");
|
||||
form->dump();
|
||||
abort();
|
||||
}
|
||||
return reg_mask( *oper );
|
||||
}
|
||||
|
||||
@ -887,7 +912,13 @@ const char *ArchDesc::reg_mask(InstructForm &inForm) {
|
||||
char *ArchDesc::stack_or_reg_mask(OperandForm &opForm) {
|
||||
// name of cisc_spillable version
|
||||
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_";
|
||||
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.
|
||||
for ( int j = _last_machine_leaf+1; j < _last_opcode; ++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, "ConL") || !strcmp(ident, "Con" ) ||
|
||||
!strcmp(ident, "Bool") ) {
|
||||
|
@ -365,13 +365,14 @@ protected:
|
||||
// A derived class defines the appropriate output for a specific mapping.
|
||||
class OutputMap {
|
||||
protected:
|
||||
FILE *_hpp;
|
||||
FILE *_cpp;
|
||||
FormDict &_globals;
|
||||
ArchDesc &_AD;
|
||||
FILE *_hpp;
|
||||
FILE *_cpp;
|
||||
FormDict &_globals;
|
||||
ArchDesc &_AD;
|
||||
const char *_name;
|
||||
public:
|
||||
OutputMap (FILE *decl_file, FILE *def_file, FormDict &globals, ArchDesc &AD)
|
||||
: _hpp(decl_file), _cpp(def_file), _globals(globals), _AD(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), _name(name) {};
|
||||
// Access files used by this routine
|
||||
FILE *decl_file() { return _hpp; }
|
||||
FILE *def_file() { return _cpp; }
|
||||
|
@ -33,7 +33,7 @@
|
||||
// String hash tables
|
||||
#define MAXID 20
|
||||
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];
|
||||
|
||||
//------------------------------bucket---------------------------------------
|
||||
|
@ -31,10 +31,14 @@
|
||||
using namespace std;
|
||||
|
||||
// STRUCTURE FOR HANDLING INPUT AND OUTPUT FILES
|
||||
typedef struct {
|
||||
|
||||
class BufferedFile {
|
||||
public:
|
||||
const char *_name;
|
||||
FILE *_fp;
|
||||
} BufferedFile;
|
||||
inline BufferedFile() { _name = NULL; _fp = NULL; };
|
||||
inline ~BufferedFile() {};
|
||||
};
|
||||
|
||||
class ArchDesc;
|
||||
|
||||
|
@ -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,"ConP")==0) return Form::idealP;
|
||||
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,"ConF")==0) return Form::idealF;
|
||||
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,"LoadF")==0 ) return Form::idealF;
|
||||
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,"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_unaligned")==0 ) return Form::idealL;
|
||||
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,"StoreP")==0) return Form::idealP;
|
||||
if( strcmp(opType,"StoreN")==0) return Form::idealN;
|
||||
if( strcmp(opType,"StoreNKlass")==0) return Form::idealNKlass;
|
||||
if( strcmp(opType,"StoreVector")==0 ) return Form::idealV;
|
||||
assert( strcmp(opType,"Store") != 0, "Must type Stores" );
|
||||
return Form::none;
|
||||
|
@ -173,7 +173,8 @@ public:
|
||||
idealC = 7, // Char type
|
||||
idealS = 8, // String type
|
||||
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'
|
||||
Form::DataType ideal_to_const_type(const char *ideal_type_name) const;
|
||||
@ -448,11 +449,11 @@ public:
|
||||
// Return number of USEs + number of DEFs
|
||||
int num_operands();
|
||||
// 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
|
||||
int operand_position(const char *name);
|
||||
// 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"
|
||||
int label_position();
|
||||
// Find position for the Method when looked up for output via "format"
|
||||
|
@ -567,7 +567,7 @@ bool InstructForm::rematerialize(FormDict &globals, RegisterForm *registers ) {
|
||||
if( strcmp(rc_name,"stack_slots") ) {
|
||||
// Check for ideal_type of RegFlags
|
||||
const char *type = opform->ideal_type( globals, registers );
|
||||
if( !strcmp(type,"RegFlags") )
|
||||
if( (type != NULL) && !strcmp(type, "RegFlags") )
|
||||
rematerialize = true;
|
||||
} else
|
||||
rematerialize = false; // Do not rematerialize things target stk
|
||||
@ -746,14 +746,16 @@ int InstructForm::memory_operand(FormDict &globals) const {
|
||||
// Expected use is for pointer vs oop determination for LoadP
|
||||
bool InstructForm::captures_bottom_type(FormDict &globals) const {
|
||||
if( _matrule && _matrule->_rChild &&
|
||||
(!strcmp(_matrule->_rChild->_opType,"CastPP") || // new result type
|
||||
!strcmp(_matrule->_rChild->_opType,"CastX2P") || // new result type
|
||||
!strcmp(_matrule->_rChild->_opType,"DecodeN") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"EncodeP") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"LoadN") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"GetAndSetN") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"LoadNKlass") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"CreateEx") || // type of exception
|
||||
(!strcmp(_matrule->_rChild->_opType,"CastPP") || // new result type
|
||||
!strcmp(_matrule->_rChild->_opType,"CastX2P") || // new result type
|
||||
!strcmp(_matrule->_rChild->_opType,"DecodeN") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"EncodeP") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"DecodeNKlass") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"EncodePKlass") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"LoadN") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"GetAndSetN") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"LoadNKlass") ||
|
||||
!strcmp(_matrule->_rChild->_opType,"CreateEx") || // type of exception
|
||||
!strcmp(_matrule->_rChild->_opType,"CheckCastPP")) ) return true;
|
||||
else if ( is_ideal_load() == Form::idealP ) return true;
|
||||
else if ( is_ideal_store() != Form::none ) return true;
|
||||
@ -793,6 +795,20 @@ uint InstructForm::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.
|
||||
uint InstructForm::num_post_match_opnds() {
|
||||
uint num_post_match_opnds = _components.count();
|
||||
@ -864,6 +880,9 @@ uint InstructForm::oper_input_base(FormDict &globals) {
|
||||
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
|
||||
void InstructForm::build_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.
|
||||
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) {
|
||||
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.
|
||||
@ -1223,7 +1242,7 @@ bool InstructForm::check_branch_variant(ArchDesc &AD, InstructForm *short_branch
|
||||
if (different) {
|
||||
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);
|
||||
}
|
||||
_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
|
||||
const Form *form = _localNames[rep_var];
|
||||
if (form == NULL) {
|
||||
fprintf(stderr, "unknown replacement variable in format statement: '%s'\n", rep_var);
|
||||
assert(false, "ShouldNotReachHere()");
|
||||
globalAD->syntax_err(_linenum, "Unknown replacement variable %s in format statement of %s.",
|
||||
rep_var, _ident);
|
||||
return;
|
||||
}
|
||||
OpClassForm *opc = form->is_opclass();
|
||||
assert( opc, "replacement variable was not found in local names");
|
||||
// Lookup the index position of the replacement variable
|
||||
int idx = operand_position_format(rep_var);
|
||||
if ( idx == -1 ) {
|
||||
assert( strcmp(opc->_ident,"label")==0, "Unimplemented");
|
||||
assert( false, "ShouldNotReachHere()");
|
||||
globalAD->syntax_err(_linenum, "Could not find replacement variable %s in format statement of %s.\n",
|
||||
rep_var, _ident);
|
||||
assert(strcmp(opc->_ident, "label") == 0, "Unimplemented");
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
if (oper != NULL && oper->is_bound_register()) {
|
||||
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 {
|
||||
globalAD->syntax_err(_linenum, "In %s can't find format for %s %s", _ident, opc->_ident, rep_var);
|
||||
}
|
||||
@ -1371,26 +1393,28 @@ void InstructForm::index_temps(FILE *fp, FormDict &globals, const char *prefix,
|
||||
// idx0=0 is used to indicate that info comes from this same node, not from input edge.
|
||||
// idx1 starts at oper_input_base()
|
||||
if ( cur_num_opnds >= 1 ) {
|
||||
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 %sidx1 = %d;\n", prefix, oper_input_base(globals));
|
||||
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 %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
|
||||
for ( idx = 2; idx < num_unique_opnds(); ++idx ) {
|
||||
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 );
|
||||
} 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 );
|
||||
}
|
||||
fprintf(fp," \t// %s\n", unique_opnd_ident(idx));
|
||||
}
|
||||
}
|
||||
if( *receiver != 0 ) {
|
||||
// This value is used by generate_peepreplace when copying a node.
|
||||
// Don't emit it in other cases since it can hide bugs with the
|
||||
// use invalid idx's.
|
||||
fprintf(fp," unsigned %sidx%d = %sreq(); \n", prefix, idx, receiver);
|
||||
fprintf(fp," unsigned %sidx%d = %sreq(); \n", prefix, idx, receiver);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1774,9 +1798,25 @@ static int effect_lookup(const char *name) {
|
||||
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)) {
|
||||
_ftype = Form::EFF;
|
||||
}
|
||||
|
||||
Effect::~Effect() {
|
||||
}
|
||||
|
||||
@ -2273,7 +2313,7 @@ void OperandForm::build_components() {
|
||||
}
|
||||
|
||||
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) ||
|
||||
strcmp(ideal_type(globalAD->globalNames()), "RegFlags") == 0)) {
|
||||
// !!!!! !!!!!
|
||||
fprintf(fp, "{ char reg_str[128];\n");
|
||||
fprintf(fp," ra->dump_register(node,reg_str);\n");
|
||||
fprintf(fp," tty->print(\"%cs\",reg_str);\n",'%');
|
||||
fprintf(fp," }\n");
|
||||
fprintf(fp," { char reg_str[128];\n");
|
||||
fprintf(fp," ra->dump_register(node,reg_str);\n");
|
||||
fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');
|
||||
fprintf(fp," }\n");
|
||||
} else if (_matrule && (dtype = _matrule->is_base_constant(globals)) != Form::none) {
|
||||
format_constant( fp, index, dtype );
|
||||
} else if (ideal_to_sReg_type(_ident) != Form::none) {
|
||||
// Special format for Stack Slot Register
|
||||
fprintf(fp, "{ char reg_str[128];\n");
|
||||
fprintf(fp," ra->dump_register(node,reg_str);\n");
|
||||
fprintf(fp," tty->print(\"%cs\",reg_str);\n",'%');
|
||||
fprintf(fp," }\n");
|
||||
fprintf(fp," { char reg_str[128];\n");
|
||||
fprintf(fp," ra->dump_register(node,reg_str);\n");
|
||||
fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');
|
||||
fprintf(fp," }\n");
|
||||
} 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);
|
||||
fprintf(stderr,"No format defined for %s\n", _ident);
|
||||
dump();
|
||||
@ -2426,36 +2466,37 @@ void OperandForm::ext_format(FILE *fp, FormDict &globals, uint index) {
|
||||
Form::DataType dtype;
|
||||
if (_matrule && (_matrule->is_base_register(globals) ||
|
||||
strcmp(ideal_type(globalAD->globalNames()), "RegFlags") == 0)) {
|
||||
fprintf(fp, "{ char reg_str[128];\n");
|
||||
fprintf(fp," ra->dump_register(node->in(idx");
|
||||
if ( index != 0 ) fprintf(fp, "+%d",index);
|
||||
fprintf(fp, "),reg_str);\n");
|
||||
fprintf(fp," tty->print(\"%cs\",reg_str);\n",'%');
|
||||
fprintf(fp," }\n");
|
||||
fprintf(fp," { char reg_str[128];\n");
|
||||
fprintf(fp," ra->dump_register(node->in(idx");
|
||||
if ( index != 0 ) fprintf(fp, "+%d",index);
|
||||
fprintf(fp, "),reg_str);\n");
|
||||
fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');
|
||||
fprintf(fp," }\n");
|
||||
} else if (_matrule && (dtype = _matrule->is_base_constant(globals)) != Form::none) {
|
||||
format_constant( fp, index, dtype );
|
||||
} else if (ideal_to_sReg_type(_ident) != Form::none) {
|
||||
// Special format for Stack Slot Register
|
||||
fprintf(fp, "{ char reg_str[128];\n");
|
||||
fprintf(fp," ra->dump_register(node->in(idx");
|
||||
fprintf(fp," { char reg_str[128];\n");
|
||||
fprintf(fp," ra->dump_register(node->in(idx");
|
||||
if ( index != 0 ) fprintf(fp, "+%d",index);
|
||||
fprintf(fp, "),reg_str);\n");
|
||||
fprintf(fp," tty->print(\"%cs\",reg_str);\n",'%');
|
||||
fprintf(fp," }\n");
|
||||
fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');
|
||||
fprintf(fp," }\n");
|
||||
} 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");
|
||||
}
|
||||
}
|
||||
|
||||
void OperandForm::format_constant(FILE *fp, uint const_index, uint const_type) {
|
||||
switch(const_type) {
|
||||
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::idealN: fprintf(fp,"_c%d->dump_on(st);\n", const_index); break;
|
||||
case Form::idealL: fprintf(fp,"st->print(\"#%%lld\", _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;
|
||||
case Form::idealI: fprintf(fp," st->print(\"#%%d\", _c%d);\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::idealNKlass:
|
||||
case Form::idealN: fprintf(fp," if (_c%d) _c%d->dump_on(st);\n", const_index, const_index); break;
|
||||
case Form::idealL: fprintf(fp," st->print(\"#%%lld\", _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:
|
||||
assert( false, "ShouldNotReachHere()");
|
||||
}
|
||||
@ -2825,17 +2866,8 @@ void Component::output(FILE *fp) {
|
||||
fprintf(fp,"Component:"); // Write to output files
|
||||
fprintf(fp, " name = %s", _name);
|
||||
fprintf(fp, ", type = %s", _type);
|
||||
const char * usedef = "Undefined Use/Def info";
|
||||
switch (_usedef) {
|
||||
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);
|
||||
assert(_usedef != 0, "unknown effect");
|
||||
fprintf(fp, ", use/def = %s\n", getUsedefName());
|
||||
}
|
||||
|
||||
|
||||
@ -2927,9 +2959,9 @@ int ComponentList::num_operands() {
|
||||
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, ...
|
||||
int ComponentList::operand_position(const char *name, int usedef) {
|
||||
int ComponentList::operand_position(const char *name, int usedef, Form *fm) {
|
||||
PreserveIter pi(this);
|
||||
int position = 0;
|
||||
int num_opnds = num_operands();
|
||||
@ -2952,10 +2984,18 @@ int ComponentList::operand_position(const char *name, int usedef) {
|
||||
return position+1;
|
||||
} else {
|
||||
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 ) {
|
||||
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");
|
||||
return position;
|
||||
@ -3001,10 +3041,10 @@ int ComponentList::operand_position(const char *name) {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
@ -3267,8 +3307,8 @@ const char *MatchNode::reduce_right(FormDict &globals) const {
|
||||
|
||||
// If we are a "Set", start from the right child.
|
||||
const MatchNode *const mnode = sets_result() ?
|
||||
(const MatchNode *const)this->_rChild :
|
||||
(const MatchNode *const)this;
|
||||
(const MatchNode *)this->_rChild :
|
||||
(const MatchNode *)this;
|
||||
|
||||
// If our right child exists, it is the right reduction
|
||||
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.
|
||||
const MatchNode *const mnode = sets_result() ?
|
||||
(const MatchNode *const)this->_rChild :
|
||||
(const MatchNode *const)this;
|
||||
(const MatchNode *)this->_rChild :
|
||||
(const MatchNode *)this;
|
||||
|
||||
// If our left child exists, it is the left reduction
|
||||
if ( mnode->_lChild ) {
|
||||
@ -3390,9 +3430,9 @@ void MatchNode::output(FILE *fp) {
|
||||
|
||||
int MatchNode::needs_ideal_memory_edge(FormDict &globals) const {
|
||||
static const char *needs_ideal_memory_list[] = {
|
||||
"StoreI","StoreL","StoreP","StoreN","StoreD","StoreF" ,
|
||||
"StoreI","StoreL","StoreP","StoreN","StoreNKlass","StoreD","StoreF" ,
|
||||
"StoreB","StoreC","Store" ,"StoreFP",
|
||||
"LoadI", "LoadUI2L", "LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" ,
|
||||
"LoadI", "LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" ,
|
||||
"LoadB" , "LoadUB", "LoadUS" ,"LoadS" ,"Load" ,
|
||||
"StoreVector", "LoadVector",
|
||||
"LoadRange", "LoadKlass", "LoadNKlass", "LoadL_unaligned", "LoadD_unaligned",
|
||||
@ -3947,6 +3987,8 @@ int MatchRule::is_expensive() const {
|
||||
strcmp(opType,"ConvL2I")==0 ||
|
||||
strcmp(opType,"DecodeN")==0 ||
|
||||
strcmp(opType,"EncodeP")==0 ||
|
||||
strcmp(opType,"EncodePKlass")==0 ||
|
||||
strcmp(opType,"DecodeNKlass")==0 ||
|
||||
strcmp(opType,"RoundDouble")==0 ||
|
||||
strcmp(opType,"RoundFloat")==0 ||
|
||||
strcmp(opType,"ReverseBytesI")==0 ||
|
||||
@ -4108,12 +4150,17 @@ void MatchRule::dump() {
|
||||
output(stderr);
|
||||
}
|
||||
|
||||
void MatchRule::output(FILE *fp) {
|
||||
// Write just one line.
|
||||
void MatchRule::output_short(FILE *fp) {
|
||||
fprintf(fp,"MatchRule: ( %s",_name);
|
||||
if (_lChild) _lChild->output(fp);
|
||||
if (_rChild) _rChild->output(fp);
|
||||
fprintf(fp," )\n");
|
||||
fprintf(fp," nesting depth = %d\n", _depth);
|
||||
fprintf(fp," )");
|
||||
}
|
||||
|
||||
void MatchRule::output(FILE *fp) {
|
||||
output_short(fp);
|
||||
fprintf(fp,"\n nesting depth = %d\n", _depth);
|
||||
if (_result) fprintf(fp," Result Type = %s", _result);
|
||||
fprintf(fp,"\n");
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ class InstructForm : public Form {
|
||||
private:
|
||||
bool _ideal_only; // Not a user-defined instruction
|
||||
// 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; }
|
||||
bool _is_cisc_alternate;
|
||||
InstructForm *_cisc_spill_alternate;// cisc possible replacement
|
||||
@ -103,7 +103,7 @@ public:
|
||||
RewriteRule *_rewrule; // Rewrite rule for this instruction
|
||||
FormatRule *_format; // Format for assembly generation
|
||||
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
|
||||
int _uniq_idx_length; // Length of _uniq_idx array
|
||||
@ -198,6 +198,7 @@ public:
|
||||
|
||||
virtual const char *cost(); // Access ins_cost attribute
|
||||
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_consts(FormDict &globals) const;// Constants in match rule
|
||||
// Constants in match rule with specified type
|
||||
@ -228,6 +229,7 @@ public:
|
||||
// Return number of relocation entries needed for this instruction.
|
||||
virtual uint reloc(FormDict &globals);
|
||||
|
||||
const char *opnd_ident(int idx); // Name of operand #idx.
|
||||
const char *reduce_result();
|
||||
// Return the name of the operand on the right hand side of the binary match
|
||||
// Return NULL if there is no right hand side
|
||||
@ -240,7 +242,7 @@ public:
|
||||
// Check if this instruction can cisc-spill to 'alternate'
|
||||
bool cisc_spills_to(ArchDesc &AD, InstructForm *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; }
|
||||
void set_cisc_alternate(bool val) { _is_cisc_alternate = val; }
|
||||
const char *cisc_reg_mask_name() const { return _cisc_reg_mask_name; }
|
||||
@ -277,6 +279,7 @@ public:
|
||||
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
|
||||
// require special handling in some cases. Their position in this
|
||||
@ -889,6 +892,7 @@ public:
|
||||
|
||||
void dump(); // Debug printer
|
||||
void output(FILE *fp); // Write to output files
|
||||
const char* getUsedefName();
|
||||
|
||||
public:
|
||||
// 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 dump();
|
||||
void output_short(FILE *fp);
|
||||
void output(FILE *fp);
|
||||
};
|
||||
|
||||
|
@ -341,14 +341,20 @@ int main(int argc, char *argv[])
|
||||
static void usage(ArchDesc& AD)
|
||||
{
|
||||
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(" o no output produced, syntax and semantic checking only\n");
|
||||
printf(" q quiet mode, supresses all non-essential 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(" h specify HPP file name (default: %s)\n", AD._HPP_file._name);
|
||||
printf(" a specify DFA output file name\n");
|
||||
printf(" v specify adGlobals output file name\n");
|
||||
printf(" # increment ADL debug level\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@ -450,22 +456,6 @@ static char *strip_ext(char *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-------------------------------
|
||||
// New concatenated string
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------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 pointer to legal text at the beginning of AD file.
|
||||
// This code assumes that a legal text starts at the beginning of .ad files,
|
||||
|
@ -518,6 +518,14 @@ static int pipeline_res_mask_initializer(
|
||||
|
||||
int cycles = piperesource->_cycles;
|
||||
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 lower_limit = stage-1;
|
||||
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, "#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, " \"\",\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
|
||||
fprintf(fp_cpp, " bool needs_comma = false;\n\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, " };\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, " };\n");
|
||||
fprintf(fp_cpp, " uint r = resources_used();\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, " 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, " };\n");
|
||||
fprintf(fp_cpp, " tty->print(\"\\n\");\n");
|
||||
fprintf(fp_cpp, " st->print(\"\\n\");\n");
|
||||
fprintf(fp_cpp, "}\n");
|
||||
fprintf(fp_cpp, "#endif\n");
|
||||
}
|
||||
@ -1048,39 +1056,6 @@ static void defineOut_RegMask(FILE *fp, const char *node, const char *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) {
|
||||
assert( inst_position >= 0, "Instruction number less than zero");
|
||||
fprintf(fp, "block_index");
|
||||
@ -1242,7 +1217,7 @@ static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch
|
||||
if( left_op_index != 0 ) {
|
||||
assert( (left_index <= 9999) && (left_op_index <= 9999), "exceed string size");
|
||||
// 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 {
|
||||
strcpy(left_reg_index, "");
|
||||
}
|
||||
@ -1255,7 +1230,7 @@ static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch
|
||||
if( right_op_index != 0 ) {
|
||||
assert( (right_index <= 9999) && (right_op_index <= 9999), "exceed string size");
|
||||
// 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 {
|
||||
strcpy(right_reg_index, "");
|
||||
}
|
||||
@ -1645,7 +1620,7 @@ void ArchDesc::defineExpand(FILE *fp, InstructForm *node) {
|
||||
new_pos = new_inst->operand_position(parameter,Component::USE);
|
||||
exp_pos += node->num_opnds();
|
||||
// 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
|
||||
fprintf(fp," n%d->set_opnd_array(%d, op%d->clone(C)); // %s\n",
|
||||
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
|
||||
fprintf(fp," unsigned num0 = 0;\n");
|
||||
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
|
||||
fprintf(fp," unsigned idx0 = oper_input_base();\n");
|
||||
@ -1934,6 +1910,7 @@ public:
|
||||
}
|
||||
|
||||
// Track necessary state when identifying a replacement variable
|
||||
// @arg rep_var: The formal parameter of the encoding.
|
||||
void update_state(const char *rep_var) {
|
||||
// A replacement variable or one of its subfields
|
||||
// Obtain replacement variable from list
|
||||
@ -1955,7 +1932,7 @@ public:
|
||||
}
|
||||
}
|
||||
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);
|
||||
if ( param_no == -1 ) {
|
||||
_AD.syntax_err( _encoding._linenum,
|
||||
@ -1964,6 +1941,7 @@ public:
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (inst_rep_var == NULL) {
|
||||
_AD.syntax_err( _ins_encode._linenum,
|
||||
@ -2329,6 +2307,7 @@ private:
|
||||
// Add parameter for index position, if not result operand
|
||||
if( _operand_idx != 0 ) fprintf(_fp,",idx%d", _operand_idx);
|
||||
fprintf(_fp,")");
|
||||
fprintf(_fp, "/* %s */", _operand_name);
|
||||
}
|
||||
} else {
|
||||
assert( _reg_status == LITERAL_OUTPUT, "should have output register literal in emit_rep_var");
|
||||
@ -2368,7 +2347,7 @@ private:
|
||||
}
|
||||
} else {
|
||||
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 ) {
|
||||
@ -2387,6 +2366,8 @@ private:
|
||||
}
|
||||
else {
|
||||
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()");
|
||||
}
|
||||
}
|
||||
@ -2484,14 +2465,14 @@ void ArchDesc::defineSize(FILE *fp, InstructForm &inst) {
|
||||
|
||||
//(1)
|
||||
// Output instruction's emit prototype
|
||||
fprintf(fp,"uint %sNode::size(PhaseRegAlloc *ra_) const {\n",
|
||||
fprintf(fp,"uint %sNode::size(PhaseRegAlloc *ra_) const {\n",
|
||||
inst._ident);
|
||||
|
||||
fprintf(fp, " assert(VerifyOops || MachNode::size(ra_) <= %s, \"bad fixed size\");\n", inst._size);
|
||||
fprintf(fp, " assert(VerifyOops || MachNode::size(ra_) <= %s, \"bad fixed size\");\n", inst._size);
|
||||
|
||||
//(2)
|
||||
// Print the size
|
||||
fprintf(fp, " return (VerifyOops ? MachNode::size(ra_) : %s);\n", inst._size);
|
||||
fprintf(fp, " return (VerifyOops ? MachNode::size(ra_) : %s);\n", inst._size);
|
||||
|
||||
// (3) and (4)
|
||||
fprintf(fp,"}\n");
|
||||
@ -2579,7 +2560,7 @@ void ArchDesc::defineEmit(FILE* fp, InstructForm& inst) {
|
||||
}
|
||||
|
||||
// (3) and (4)
|
||||
fprintf(fp, "}\n");
|
||||
fprintf(fp, "}\n\n");
|
||||
}
|
||||
|
||||
// defineEvalConstant ---------------------------------------------------------
|
||||
@ -2727,12 +2708,12 @@ static void defineIn_RegMask(FILE *fp, FormDict &globals, OperandForm &oper) {
|
||||
// (2) }
|
||||
//
|
||||
static void defineClone(FILE *fp, FormDict &globalNames, OperandForm &oper) {
|
||||
fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper._ident);
|
||||
fprintf(fp,"MachOper *%sOper::clone(Compile* C) const {\n", oper._ident);
|
||||
// Check for constants that need to be copied over
|
||||
const int num_consts = oper.num_consts(globalNames);
|
||||
const bool is_ideal_bool = oper.is_ideal_bool();
|
||||
if( (num_consts > 0) ) {
|
||||
fprintf(fp," return new (C) %sOper(", oper._ident);
|
||||
fprintf(fp," return new (C) %sOper(", oper._ident);
|
||||
// generate parameters for constants
|
||||
int i = 0;
|
||||
fprintf(fp,"_c%d", i);
|
||||
@ -2744,21 +2725,12 @@ static void defineClone(FILE *fp, FormDict &globalNames, OperandForm &oper) {
|
||||
}
|
||||
else {
|
||||
assert( num_consts == 0, "Currently support zero or one constant per operand clone function");
|
||||
fprintf(fp," return new (C) %sOper();\n", oper._ident);
|
||||
fprintf(fp," return new (C) %sOper();\n", oper._ident);
|
||||
}
|
||||
// finish method
|
||||
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
|
||||
// from define_oper_interface()
|
||||
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) ) {
|
||||
fprintf(fp,"(PhaseRegAlloc *ra_, const Node *node, int idx) const { \n");
|
||||
} else {
|
||||
fprintf(fp,"() const { ");
|
||||
fprintf(fp,"() const { \n");
|
||||
}
|
||||
|
||||
// Check for hexadecimal value OR replacement variable
|
||||
if( *encoding == '$' ) {
|
||||
// Replacement variable
|
||||
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
|
||||
const Component *comp = oper._components.search(rep_var);
|
||||
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 ) {
|
||||
// StackSlot for an sReg comes either from input node or from self, when idx==0
|
||||
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," }\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");
|
||||
} else if (op->_matrule && op->_matrule->is_base_constant(globals)) {
|
||||
// Constant
|
||||
@ -2900,7 +2872,7 @@ void ArchDesc::define_oper_interface(FILE *fp, OperandForm &oper, FormDict &glob
|
||||
}
|
||||
else if( *encoding == '0' && *(encoding+1) == 'x' ) {
|
||||
// Hex value
|
||||
fprintf(fp,"return %s;", encoding);
|
||||
fprintf(fp," return %s;\n", encoding);
|
||||
} else {
|
||||
assert( false, "Do not support octal or decimal encode constants");
|
||||
}
|
||||
@ -3133,8 +3105,8 @@ void ArchDesc::defineClasses(FILE *fp) {
|
||||
// Output the definition for number of relocation entries
|
||||
uint reloc_size = instr->reloc(_globalNames);
|
||||
if ( reloc_size != 0 ) {
|
||||
fprintf(fp,"int %sNode::reloc() const {\n", instr->_ident);
|
||||
fprintf(fp, " return %d;\n", reloc_size );
|
||||
fprintf(fp,"int %sNode::reloc() const {\n", instr->_ident);
|
||||
fprintf(fp," return %d;\n", reloc_size);
|
||||
fprintf(fp,"}\n");
|
||||
fprintf(fp,"\n");
|
||||
}
|
||||
@ -3241,7 +3213,7 @@ void ArchDesc::defineClasses(FILE *fp) {
|
||||
class OutputReduceOp : public OutputMap {
|
||||
public:
|
||||
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 definition() { fprintf(_cpp, "const int reduceOp[] = {\n"); }
|
||||
@ -3276,7 +3248,7 @@ public:
|
||||
class OutputLeftOp : public OutputMap {
|
||||
public:
|
||||
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 definition() { fprintf(_cpp, "const int leftOp[] = {\n"); }
|
||||
@ -3306,7 +3278,7 @@ public:
|
||||
class OutputRightOp : public OutputMap {
|
||||
public:
|
||||
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 definition() { fprintf(_cpp, "const int rightOp[] = {\n"); }
|
||||
@ -3336,11 +3308,11 @@ public:
|
||||
class OutputRuleName : public OutputMap {
|
||||
public:
|
||||
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 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();
|
||||
}
|
||||
void map(OpClassForm &opc) { fprintf(_cpp, " \"%s\"", _AD.machOperEnum(opc._ident) ); }
|
||||
@ -3354,7 +3326,7 @@ public:
|
||||
class OutputSwallowed : public OutputMap {
|
||||
public:
|
||||
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 definition() { fprintf(_cpp, "const bool swallowed[] = {\n"); }
|
||||
@ -3375,7 +3347,7 @@ public:
|
||||
class OutputInstChainRule : public OutputMap {
|
||||
public:
|
||||
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 definition() { fprintf(_cpp, "const bool instruction_chain_rule[] = {\n"); }
|
||||
@ -3416,7 +3388,7 @@ void ArchDesc::build_map(OutputMap &map) {
|
||||
if ( op->ideal_only() ) continue;
|
||||
|
||||
// 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;
|
||||
};
|
||||
fprintf(fp_cpp, " // last operand\n");
|
||||
@ -3425,7 +3397,7 @@ void ArchDesc::build_map(OutputMap &map) {
|
||||
map.record_position(OutputMap::BEGIN_OPCLASSES, idx );
|
||||
_opclass.reset();
|
||||
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;
|
||||
};
|
||||
fprintf(fp_cpp, " // last operand class\n");
|
||||
@ -3435,7 +3407,7 @@ void ArchDesc::build_map(OutputMap &map) {
|
||||
_internalOpNames.reset();
|
||||
char *name = 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;
|
||||
};
|
||||
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->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;
|
||||
};
|
||||
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->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;
|
||||
};
|
||||
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->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;
|
||||
};
|
||||
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->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;
|
||||
};
|
||||
}
|
||||
@ -3571,7 +3543,7 @@ void ArchDesc::buildReduceMaps(FILE *fp_hpp, FILE *fp_cpp) {
|
||||
next = _register->iter_RegDefs();
|
||||
char policy = reg_save_policy(rdef->_callconv);
|
||||
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");
|
||||
|
||||
@ -3583,7 +3555,7 @@ void ArchDesc::buildReduceMaps(FILE *fp_hpp, FILE *fp_cpp) {
|
||||
next = _register->iter_RegDefs();
|
||||
char policy = reg_save_policy(rdef->_c_conv);
|
||||
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");
|
||||
|
||||
@ -3644,6 +3616,8 @@ static void path_to_constant(FILE *fp, FormDict &globals,
|
||||
fprintf(fp, "_leaf->bottom_type()->is_ptr()");
|
||||
} else if ( (strcmp(optype,"ConN") == 0) ) {
|
||||
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) ) {
|
||||
fprintf(fp, "_leaf->getf()");
|
||||
} 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
|
||||
// with the enum for the opcode that needs to be built.
|
||||
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);
|
||||
fprintf(fp_cpp, "%s node->set_opnd_array(%d, ", indent, index);
|
||||
fprintf(fp_cpp, "MachOperGenerator(%s, C));\n", opcode);
|
||||
@ -3987,7 +3961,7 @@ void ArchDesc::buildMachNodeGenerator(FILE *fp_cpp) {
|
||||
fprintf(fp_cpp, " case %s_rule:", opClass);
|
||||
|
||||
// Start local scope
|
||||
fprintf(fp_cpp, " {\n");
|
||||
fprintf(fp_cpp, " {\n");
|
||||
// Generate code to construct the new MachNode
|
||||
buildMachNode(fp_cpp, inst, " ");
|
||||
// Return result and exit scope
|
||||
@ -4137,6 +4111,9 @@ static int PrintAdlcCisc = 0;
|
||||
// Get info for the CISC_oracle and MachNode::cisc_version()
|
||||
void ArchDesc::identify_cisc_spill_instructions() {
|
||||
|
||||
if (_frame == NULL)
|
||||
return;
|
||||
|
||||
// Find the user-defined operand for cisc-spilling
|
||||
if( _frame->_cisc_spilling_operand_name != NULL ) {
|
||||
const Form *form = _globalNames[_frame->_cisc_spilling_operand_name];
|
||||
|
@ -25,6 +25,8 @@
|
||||
// output_h.cpp - Class HPP file output routines for architecture definition
|
||||
#include "adlc.hpp"
|
||||
|
||||
// The comment delimiter used in format statements after assembler instructions.
|
||||
#define commentSeperator "!"
|
||||
|
||||
// Generate the #define that describes the number of registers.
|
||||
static void defineRegCount(FILE *fp, RegisterForm *registers) {
|
||||
@ -79,10 +81,15 @@ void ArchDesc::buildMachRegisterNumbers(FILE *fp_hpp) {
|
||||
_register->reset_RegDefs();
|
||||
int i = 0;
|
||||
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
|
||||
fprintf(fp_hpp, " _last_Mach_Reg\t// %d\n", i);
|
||||
fprintf(fp_hpp, " _last_Mach_Reg // %d\n", i);
|
||||
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, "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
|
||||
_register->reset_RegDefs();
|
||||
reg_def_next = _register->iter_RegDefs();
|
||||
while( (reg_def = reg_def_next) != NULL ) {
|
||||
reg_def_next = _register->iter_RegDefs();
|
||||
fprintf(fp_hpp," %s_enc = %s%s\n",
|
||||
reg_def->_regname, reg_def->register_encode(), reg_def_next == NULL? "" : "," );
|
||||
fprintf(fp_hpp," %s_enc", reg_def->_regname);
|
||||
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
|
||||
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");
|
||||
}
|
||||
|
||||
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) {
|
||||
int i = 0;
|
||||
Component *comp;
|
||||
@ -207,6 +217,10 @@ static void declareConstStorage(FILE *fp, FormDict &globals, OperandForm *oper)
|
||||
if (i > 0) fprintf(fp,", ");
|
||||
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")) {
|
||||
if (i > 0) fprintf(fp,", ");
|
||||
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);
|
||||
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")) {
|
||||
fprintf(fp," jlong _c%d;\n", i);
|
||||
i++;
|
||||
@ -288,11 +306,12 @@ static void defineConstructor(FILE *fp, const char *name, uint num_consts,
|
||||
fprintf(fp,is_ideal_bool ? "BoolTest::mask c%d" : "int32 c%d", i);
|
||||
break;
|
||||
}
|
||||
case Form::idealN : { fprintf(fp,"const TypeNarrowOop *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::idealF : { fprintf(fp,"jfloat c%d", i); break; }
|
||||
case Form::idealD : { fprintf(fp,"jdouble 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::idealL : { fprintf(fp,"jlong c%d", i); break; }
|
||||
case Form::idealF : { fprintf(fp,"jfloat c%d", i); break; }
|
||||
case Form::idealD : { fprintf(fp,"jdouble c%d", i); break; }
|
||||
default:
|
||||
assert(!is_ideal_bool, "Non-constant operand lacks component list.");
|
||||
break;
|
||||
@ -316,6 +335,11 @@ static void defineConstructor(FILE *fp, const char *name, uint num_consts,
|
||||
fprintf(fp,"const TypePtr *c%d", 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")) {
|
||||
if (i > 0) fprintf(fp,", ");
|
||||
fprintf(fp,"jlong c%d", i);
|
||||
@ -358,18 +382,19 @@ static void defineConstructor(FILE *fp, const char *name, uint num_consts,
|
||||
static void defineCCodeDump(OperandForm* oper, FILE *fp, int i) {
|
||||
assert(oper != NULL, "what");
|
||||
CondInterface* cond = oper->_interface->is_CondInterface();
|
||||
fprintf(fp, " if( _c%d == BoolTest::eq ) st->print(\"%s\");\n",i,cond->_equal_format);
|
||||
fprintf(fp, " else if( _c%d == BoolTest::ne ) st->print(\"%s\");\n",i,cond->_not_equal_format);
|
||||
fprintf(fp, " else if( _c%d == BoolTest::le ) st->print(\"%s\");\n",i,cond->_less_equal_format);
|
||||
fprintf(fp, " else if( _c%d == BoolTest::ge ) st->print(\"%s\");\n",i,cond->_greater_equal_format);
|
||||
fprintf(fp, " else if( _c%d == BoolTest::lt ) st->print(\"%s\");\n",i,cond->_less_format);
|
||||
fprintf(fp, " else if( _c%d == BoolTest::gt ) st->print(\"%s\");\n",i,cond->_greater_format);
|
||||
fprintf(fp, " if( _c%d == BoolTest::eq ) st->print(\"%s\");\n",i,cond->_equal_format);
|
||||
fprintf(fp, " else if( _c%d == BoolTest::ne ) st->print(\"%s\");\n",i,cond->_not_equal_format);
|
||||
fprintf(fp, " else if( _c%d == BoolTest::le ) st->print(\"%s\");\n",i,cond->_less_equal_format);
|
||||
fprintf(fp, " else if( _c%d == BoolTest::ge ) st->print(\"%s\");\n",i,cond->_greater_equal_format);
|
||||
fprintf(fp, " else if( _c%d == BoolTest::lt ) st->print(\"%s\");\n",i,cond->_less_format);
|
||||
fprintf(fp, " else if( _c%d == BoolTest::gt ) st->print(\"%s\");\n",i,cond->_greater_format);
|
||||
}
|
||||
|
||||
// Output code that dumps constant values, increment "i" if type is constant
|
||||
static uint dump_spec_constant(FILE *fp, const char *ideal_type, uint i, OperandForm* oper) {
|
||||
if (!strcmp(ideal_type, "ConI")) {
|
||||
fprintf(fp," st->print(\"#%%d\", _c%d);\n", i);
|
||||
fprintf(fp," st->print(\"/0x%%08x\", _c%d);\n", i);
|
||||
++i;
|
||||
}
|
||||
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);
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(ideal_type, "ConNKlass")) {
|
||||
fprintf(fp," _c%d->dump_on(st);\n", i);
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(ideal_type, "ConL")) {
|
||||
fprintf(fp," st->print(\"#\" INT64_FORMAT, _c%d);\n", i);
|
||||
fprintf(fp," st->print(\"/\" PTR64_FORMAT, _c%d);\n", i);
|
||||
++i;
|
||||
}
|
||||
else if (!strcmp(ideal_type, "ConF")) {
|
||||
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;
|
||||
}
|
||||
else if (!strcmp(ideal_type, "ConD")) {
|
||||
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;
|
||||
}
|
||||
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
|
||||
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
|
||||
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->_strings.reset();
|
||||
while ( (string = oper._format->_strings.iter()) != NULL ) {
|
||||
fprintf(fp," ");
|
||||
|
||||
// Check if this is a standard string or a replacement variable
|
||||
if ( string != NameList::_signal ) {
|
||||
// Normal string
|
||||
// Pass through to st->print
|
||||
fprintf(fp,"st->print(\"%s\");\n", string);
|
||||
fprintf(fp," st->print(\"%s\");\n", string);
|
||||
} else {
|
||||
// Replacement variable
|
||||
const char *rep_var = oper._format->_rep_vars.iter();
|
||||
@ -455,7 +488,7 @@ void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_
|
||||
}
|
||||
|
||||
// output invocation of "$..."s format function
|
||||
if ( op != NULL ) op->int_format(fp, globals, idx);
|
||||
if ( op != NULL ) op->int_format(fp, globals, idx);
|
||||
|
||||
if ( idx == -1 ) {
|
||||
fprintf(stderr,
|
||||
@ -498,13 +531,12 @@ void gen_oper_format(FILE *fp, FormDict &globals, OperandForm &oper, bool for_c_
|
||||
oper._format->_rep_vars.reset();
|
||||
oper._format->_strings.reset();
|
||||
while ( (string = oper._format->_strings.iter()) != NULL ) {
|
||||
fprintf(fp," ");
|
||||
|
||||
// Check if this is a standard string or a replacement variable
|
||||
if ( string != NameList::_signal ) {
|
||||
// Normal string
|
||||
// Pass through to st->print
|
||||
fprintf(fp,"st->print(\"%s\");\n", string);
|
||||
fprintf(fp," st->print(\"%s\");\n", string);
|
||||
} else {
|
||||
// Replacement variable
|
||||
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);
|
||||
|
||||
// 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 ) {
|
||||
fprintf(stderr,
|
||||
"Using a name, %s, that isn't in match rule\n", rep_var);
|
||||
@ -583,7 +615,7 @@ void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &inst, bool for_c
|
||||
inst._format->_rep_vars.reset();
|
||||
inst._format->_strings.reset();
|
||||
while( (string = inst._format->_strings.iter()) != NULL ) {
|
||||
fprintf(fp," ");
|
||||
fprintf(fp," ");
|
||||
// Check if this is a standard string or a replacement variable
|
||||
if( string == NameList::_signal ) { // Replacement variable
|
||||
const char* rep_var = inst._format->_rep_vars.iter();
|
||||
@ -640,11 +672,12 @@ void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &inst, bool for_c
|
||||
if( call_type != Form::invalid_type ) {
|
||||
switch( call_type ) {
|
||||
case Form::JAVA_DYNAMIC:
|
||||
fprintf(fp," _method->print_short_name();\n");
|
||||
fprintf(fp," _method->print_short_name(st);\n");
|
||||
break;
|
||||
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 ) dump_trap_args(st);\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");
|
||||
break;
|
||||
case Form::JAVA_COMPILED:
|
||||
case Form::JAVA_INTERP:
|
||||
@ -652,52 +685,46 @@ void gen_inst_format(FILE *fp, FormDict &globals, InstructForm &inst, bool for_c
|
||||
case Form::JAVA_RUNTIME:
|
||||
case Form::JAVA_LEAF:
|
||||
case Form::JAVA_NATIVE:
|
||||
fprintf(fp," st->print(\" %%s\", _name);");
|
||||
fprintf(fp," st->print(\" %%s\", _name);");
|
||||
break;
|
||||
default:
|
||||
assert(0,"ShouldNotReacHere");
|
||||
assert(0,"ShouldNotReachHere");
|
||||
}
|
||||
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, " st->print(\" # \");\n" );
|
||||
fprintf(fp, " if( _jvms ) _oop_map->print_on(st);\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, " st->print(\" # \");\n" );
|
||||
fprintf(fp, " if( _jvms && _oop_map ) _oop_map->print_on(st);\n");
|
||||
}
|
||||
else if(inst.is_ideal_safepoint()) {
|
||||
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, " st->print(\" # \");\n" );
|
||||
fprintf(fp, " if( _jvms ) _oop_map->print_on(st);\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, " st->print(\" # \");\n" );
|
||||
fprintf(fp, " if( _jvms && _oop_map ) _oop_map->print_on(st);\n");
|
||||
}
|
||||
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" );
|
||||
}
|
||||
else if( inst.is_ideal_mem() ) {
|
||||
// Print out the field name if available to improve readability
|
||||
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, " st->print(\" ! Field: \");\n");
|
||||
fprintf(fp, " if (f->is_volatile())\n");
|
||||
fprintf(fp, " st->print(\"volatile \");\n");
|
||||
fprintf(fp, " f->holder()->name()->print_symbol_on(st);\n");
|
||||
fprintf(fp, " st->print(\".\");\n");
|
||||
fprintf(fp, " f->name()->print_symbol_on(st);\n");
|
||||
fprintf(fp, " if (f->is_constant())\n");
|
||||
fprintf(fp, " st->print(\" (constant)\");\n");
|
||||
fprintf(fp, " } else\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, " st->print(\" %s Field: \");\n", commentSeperator);
|
||||
fprintf(fp, " if (f->is_volatile())\n");
|
||||
fprintf(fp, " st->print(\"volatile \");\n");
|
||||
fprintf(fp, " f->holder()->name()->print_symbol_on(st);\n");
|
||||
fprintf(fp, " st->print(\".\");\n");
|
||||
fprintf(fp, " f->name()->print_symbol_on(st);\n");
|
||||
fprintf(fp, " if (f->is_constant())\n");
|
||||
fprintf(fp, " st->print(\" (constant)\");\n");
|
||||
fprintf(fp, " } else {\n");
|
||||
// Make sure 'Volatile' gets printed out
|
||||
fprintf(fp, " if (ra->C->alias_type(adr_type())->is_volatile())\n");
|
||||
fprintf(fp, " st->print(\" volatile!\");\n");
|
||||
fprintf(fp, " }\n");
|
||||
}
|
||||
|
||||
// Complete the definition of the format function
|
||||
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;
|
||||
fprintf(fp, "}\n#endif\n");
|
||||
}
|
||||
|
||||
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",
|
||||
_pipeline->_nopcnt);
|
||||
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, "};\n\n");
|
||||
|
||||
@ -1234,12 +1261,12 @@ void ArchDesc::declareClasses(FILE *fp) {
|
||||
unsigned int position = 0;
|
||||
const char *opret, *opname, *optype;
|
||||
oper->_matrule->base_operand(position,_globalNames,opret,opname,optype);
|
||||
fprintf(fp," virtual const Type *type() const {");
|
||||
fprintf(fp," virtual const Type *type() const {");
|
||||
const char *type = getIdealType(optype);
|
||||
if( type != NULL ) {
|
||||
Form::DataType data_type = oper->is_base_constant(_globalNames);
|
||||
// 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 *>
|
||||
fprintf(fp," return _c0;");
|
||||
} else {
|
||||
@ -1377,6 +1404,16 @@ void ArchDesc::declareClasses(FILE *fp) {
|
||||
fprintf(fp, " return _c0->get_ptrtype()->reloc();");
|
||||
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")) {
|
||||
fprintf(fp," virtual intptr_t constant() const {");
|
||||
// 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,"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," 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," MachOper *opnd_array(uint operand_index) const {\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");
|
||||
if ( instr->is_ideal_jump() ) {
|
||||
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) ) {
|
||||
fprintf(fp," const RegMask *_cisc_RegMask;\n");
|
||||
@ -1544,7 +1588,7 @@ void ArchDesc::declareClasses(FILE *fp) {
|
||||
while (attr != NULL) {
|
||||
if (strcmp(attr->_ident,"ins_cost") &&
|
||||
strcmp(attr->_ident,"ins_short_branch")) {
|
||||
fprintf(fp," int %s() const { return %s; }\n",
|
||||
fprintf(fp," int %s() const { return %s; }\n",
|
||||
attr->_ident, attr->_val);
|
||||
}
|
||||
// Check value for ins_avoid_back_to_back, and if it is true (1), set the flag
|
||||
@ -1628,12 +1672,12 @@ void ArchDesc::declareClasses(FILE *fp) {
|
||||
|
||||
// Output the declaration for number of relocation entries
|
||||
if ( instr->reloc(_globalNames) != 0 ) {
|
||||
fprintf(fp," virtual int reloc() const;\n");
|
||||
fprintf(fp," virtual int reloc() const;\n");
|
||||
}
|
||||
|
||||
if (instr->alignment() != 1) {
|
||||
fprintf(fp," virtual int alignment_required() const { return %d; }\n", instr->alignment());
|
||||
fprintf(fp," virtual int compute_padding(int current_offset) const;\n");
|
||||
fprintf(fp," virtual int alignment_required() const { return %d; }\n", instr->alignment());
|
||||
fprintf(fp," virtual int compute_padding(int current_offset) const;\n");
|
||||
}
|
||||
|
||||
// Starting point for inputs matcher wants.
|
||||
@ -1803,13 +1847,14 @@ void ArchDesc::declareClasses(FILE *fp) {
|
||||
// as is done for pointers
|
||||
//
|
||||
// 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 ) {
|
||||
case Form::idealI:
|
||||
fprintf(fp," return TypeInt::make(opnd_array(1)->constant());\n");
|
||||
break;
|
||||
case Form::idealP:
|
||||
case Form::idealN:
|
||||
case Form::idealNKlass:
|
||||
fprintf(fp," return opnd_array(1)->type();\n");
|
||||
break;
|
||||
case Form::idealD:
|
||||
@ -1833,7 +1878,7 @@ void ArchDesc::declareClasses(FILE *fp) {
|
||||
// !!!!! !!!!!
|
||||
// Provide explicit bottom type for conversions to int
|
||||
// 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, " };\n");
|
||||
}*/
|
||||
@ -1854,7 +1899,7 @@ void ArchDesc::declareClasses(FILE *fp) {
|
||||
// BoxNode provides the address of a stack slot.
|
||||
// Define its bottom type to be TypeRawPtr::BOTTOM instead of TypePtr::BOTTOM
|
||||
// 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.
|
||||
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 {
|
||||
public:
|
||||
OutputMachOperands(FILE *hpp, FILE *cpp, FormDict &globals, ArchDesc &AD)
|
||||
: OutputMap(hpp, cpp, globals, AD) {};
|
||||
: OutputMap(hpp, cpp, globals, AD, "MachOperands") {};
|
||||
|
||||
void declaration() { }
|
||||
void definition() { fprintf(_cpp, "enum MachOperands {\n"); }
|
||||
@ -2052,7 +2097,7 @@ class OutputMachOpcodes : public OutputMap {
|
||||
int end_instructions;
|
||||
public:
|
||||
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)
|
||||
{};
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "c1/c1_ValueMap.hpp"
|
||||
#include "c1/c1_ValueStack.hpp"
|
||||
#include "code/debugInfoRec.hpp"
|
||||
#include "compiler/compileLog.hpp"
|
||||
|
||||
|
||||
typedef enum {
|
||||
@ -67,10 +68,25 @@ static int totalInstructionNodes = 0;
|
||||
class PhaseTraceTime: public TraceTime {
|
||||
private:
|
||||
JavaThread* _thread;
|
||||
CompileLog* _log;
|
||||
|
||||
public:
|
||||
PhaseTraceTime(TimerName timer):
|
||||
TraceTime("", &timers[timer], CITime || CITimeEach, Verbose) {
|
||||
PhaseTraceTime(TimerName timer)
|
||||
: 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);
|
||||
install_code(frame_size);
|
||||
}
|
||||
|
||||
if (log() != NULL) // Print code cache state into compiler log
|
||||
log()->code_cache_state();
|
||||
|
||||
totalInstructionNodes += Instruction::number_of_instructions();
|
||||
}
|
||||
|
||||
@ -456,6 +476,7 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho
|
||||
int osr_bci, BufferBlob* buffer_blob)
|
||||
: _compiler(compiler)
|
||||
, _env(env)
|
||||
, _log(env->log())
|
||||
, _method(method)
|
||||
, _osr_bci(osr_bci)
|
||||
, _hir(NULL)
|
||||
|
@ -66,6 +66,7 @@ class Compilation: public StackObj {
|
||||
int _next_block_id;
|
||||
AbstractCompiler* _compiler;
|
||||
ciEnv* _env;
|
||||
CompileLog* _log;
|
||||
ciMethod* _method;
|
||||
int _osr_bci;
|
||||
IR* _hir;
|
||||
@ -123,6 +124,7 @@ class Compilation: public StackObj {
|
||||
|
||||
// accessors
|
||||
ciEnv* env() const { return _env; }
|
||||
CompileLog* log() const { return _log; }
|
||||
AbstractCompiler* compiler() const { return _compiler; }
|
||||
bool has_exception_handlers() const { return _has_exception_handlers; }
|
||||
bool has_fpu_code() const { return _has_fpu_code; }
|
||||
|
@ -1682,6 +1682,12 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
|
||||
ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(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
|
||||
// convert them directly to an invokespecial or invokestatic.
|
||||
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;
|
||||
}
|
||||
|
||||
// check if we could do inlining
|
||||
if (!PatchALot && Inline && klass->is_loaded() &&
|
||||
(klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized())
|
||||
@ -2448,6 +2455,7 @@ BlockEnd* GraphBuilder::iterate_bytecodes_for_block(int bci) {
|
||||
#endif
|
||||
_skip_block = false;
|
||||
assert(state() != NULL, "ValueStack missing!");
|
||||
CompileLog* log = compilation()->log();
|
||||
ciBytecodeStream s(method());
|
||||
s.reset_to_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())) {
|
||||
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
|
||||
if (compilation()->is_osr_compile()
|
||||
&& 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);
|
||||
default : ShouldNotReachHere(); break;
|
||||
}
|
||||
|
||||
if (log != NULL)
|
||||
log->clear_context(); // skip marker if nothing was printed
|
||||
|
||||
// save current bci to setup Goto at the end
|
||||
prev_bci = s.cur_bci();
|
||||
|
||||
}
|
||||
CHECK_BAILOUT_(NULL);
|
||||
// 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");
|
||||
}
|
||||
// printing
|
||||
print_inlining(callee, "");
|
||||
print_inlining(callee);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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;
|
||||
assert(msg != NULL, "must be");
|
||||
CompileTask::print_inlining(callee, scope()->level(), bci(), msg);
|
||||
if (success && CIPrintMethodCodes) {
|
||||
callee->print_codes();
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "c1/c1_ValueStack.hpp"
|
||||
#include "ci/ciMethodData.hpp"
|
||||
#include "ci/ciStreams.hpp"
|
||||
#include "compiler/compileLog.hpp"
|
||||
|
||||
class MemoryBuffer;
|
||||
|
||||
@ -369,7 +370,7 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
|
||||
void append_unsafe_CAS(ciMethod* callee);
|
||||
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_invocation(ciMethod* inlinee, ValueStack* state);
|
||||
|
@ -1286,7 +1286,7 @@ void LIRGenerator::do_getClass(Intrinsic* x) {
|
||||
if (x->needs_null_check()) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "c1/c1_ValueSet.hpp"
|
||||
#include "c1/c1_ValueStack.hpp"
|
||||
#include "utilities/bitMap.inline.hpp"
|
||||
#include "compiler/compileLog.hpp"
|
||||
|
||||
define_array(ValueSetArray, ValueSet*);
|
||||
define_stack(ValueSetList, ValueSetArray);
|
||||
@ -54,7 +55,18 @@ class CE_Eliminator: public BlockClosure {
|
||||
// substituted some ifops/phis, so resolve the substitution
|
||||
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 ifop_count() const { return _ifop_count; }
|
||||
|
||||
@ -306,6 +318,15 @@ class BlockMerger: public BlockClosure {
|
||||
, _merge_count(0)
|
||||
{
|
||||
_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) {
|
||||
@ -574,6 +595,15 @@ class NullCheckEliminator: public ValueVisitor {
|
||||
, _work_list(new BlockList()) {
|
||||
_visitable_instructions = new ValueSet();
|
||||
_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; }
|
||||
|
@ -1126,7 +1126,8 @@ void ciEnv::record_method_not_compilable(const char* reason, bool all_tiers) {
|
||||
if (all_tiers) {
|
||||
log()->elem("method_not_compilable");
|
||||
} else {
|
||||
log()->elem("method_not_compilable_at_tier");
|
||||
log()->elem("method_not_compilable_at_tier level='%d'",
|
||||
current()->task()->comp_level());
|
||||
}
|
||||
}
|
||||
_compilable = new_compilable;
|
||||
|
@ -146,7 +146,7 @@ void ciObjectFactory::init_shared_objects() {
|
||||
|
||||
for (int i = T_BOOLEAN; i <= T_CONFLICT; 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);
|
||||
init_ident_of(ciType::_basic_types[t]);
|
||||
}
|
||||
|
@ -816,9 +816,6 @@ Array<Klass*>* ClassFileParser::parse_interfaces(constantPoolHandle cp,
|
||||
unresolved_klass, class_loader, protection_domain,
|
||||
false, CHECK_NULL);
|
||||
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()) {
|
||||
@ -1008,40 +1005,42 @@ static FieldAllocationType _basic_type_to_atype[2 * (T_CONFLICT + 1)] = {
|
||||
BAD_ALLOCATION_TYPE, // 1
|
||||
BAD_ALLOCATION_TYPE, // 2
|
||||
BAD_ALLOCATION_TYPE, // 3
|
||||
NONSTATIC_BYTE , // T_BOOLEAN = 4,
|
||||
NONSTATIC_SHORT, // T_CHAR = 5,
|
||||
NONSTATIC_WORD, // T_FLOAT = 6,
|
||||
NONSTATIC_DOUBLE, // T_DOUBLE = 7,
|
||||
NONSTATIC_BYTE, // T_BYTE = 8,
|
||||
NONSTATIC_SHORT, // T_SHORT = 9,
|
||||
NONSTATIC_WORD, // T_INT = 10,
|
||||
NONSTATIC_DOUBLE, // T_LONG = 11,
|
||||
NONSTATIC_OOP, // T_OBJECT = 12,
|
||||
NONSTATIC_OOP, // T_ARRAY = 13,
|
||||
BAD_ALLOCATION_TYPE, // T_VOID = 14,
|
||||
BAD_ALLOCATION_TYPE, // T_ADDRESS = 15,
|
||||
BAD_ALLOCATION_TYPE, // T_NARROWOOP= 16,
|
||||
BAD_ALLOCATION_TYPE, // T_METADATA = 17,
|
||||
BAD_ALLOCATION_TYPE, // T_CONFLICT = 18,
|
||||
NONSTATIC_BYTE , // T_BOOLEAN = 4,
|
||||
NONSTATIC_SHORT, // T_CHAR = 5,
|
||||
NONSTATIC_WORD, // T_FLOAT = 6,
|
||||
NONSTATIC_DOUBLE, // T_DOUBLE = 7,
|
||||
NONSTATIC_BYTE, // T_BYTE = 8,
|
||||
NONSTATIC_SHORT, // T_SHORT = 9,
|
||||
NONSTATIC_WORD, // T_INT = 10,
|
||||
NONSTATIC_DOUBLE, // T_LONG = 11,
|
||||
NONSTATIC_OOP, // T_OBJECT = 12,
|
||||
NONSTATIC_OOP, // T_ARRAY = 13,
|
||||
BAD_ALLOCATION_TYPE, // T_VOID = 14,
|
||||
BAD_ALLOCATION_TYPE, // T_ADDRESS = 15,
|
||||
BAD_ALLOCATION_TYPE, // T_NARROWOOP = 16,
|
||||
BAD_ALLOCATION_TYPE, // T_METADATA = 17,
|
||||
BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 18,
|
||||
BAD_ALLOCATION_TYPE, // T_CONFLICT = 19,
|
||||
BAD_ALLOCATION_TYPE, // 0
|
||||
BAD_ALLOCATION_TYPE, // 1
|
||||
BAD_ALLOCATION_TYPE, // 2
|
||||
BAD_ALLOCATION_TYPE, // 3
|
||||
STATIC_BYTE , // T_BOOLEAN = 4,
|
||||
STATIC_SHORT, // T_CHAR = 5,
|
||||
STATIC_WORD, // T_FLOAT = 6,
|
||||
STATIC_DOUBLE, // T_DOUBLE = 7,
|
||||
STATIC_BYTE, // T_BYTE = 8,
|
||||
STATIC_SHORT, // T_SHORT = 9,
|
||||
STATIC_WORD, // T_INT = 10,
|
||||
STATIC_DOUBLE, // T_LONG = 11,
|
||||
STATIC_OOP, // T_OBJECT = 12,
|
||||
STATIC_OOP, // T_ARRAY = 13,
|
||||
BAD_ALLOCATION_TYPE, // T_VOID = 14,
|
||||
BAD_ALLOCATION_TYPE, // T_ADDRESS = 15,
|
||||
BAD_ALLOCATION_TYPE, // T_NARROWOOP= 16,
|
||||
BAD_ALLOCATION_TYPE, // T_METADATA = 17,
|
||||
BAD_ALLOCATION_TYPE, // T_CONFLICT = 18,
|
||||
STATIC_BYTE , // T_BOOLEAN = 4,
|
||||
STATIC_SHORT, // T_CHAR = 5,
|
||||
STATIC_WORD, // T_FLOAT = 6,
|
||||
STATIC_DOUBLE, // T_DOUBLE = 7,
|
||||
STATIC_BYTE, // T_BYTE = 8,
|
||||
STATIC_SHORT, // T_SHORT = 9,
|
||||
STATIC_WORD, // T_INT = 10,
|
||||
STATIC_DOUBLE, // T_LONG = 11,
|
||||
STATIC_OOP, // T_OBJECT = 12,
|
||||
STATIC_OOP, // T_ARRAY = 13,
|
||||
BAD_ALLOCATION_TYPE, // T_VOID = 14,
|
||||
BAD_ALLOCATION_TYPE, // T_ADDRESS = 15,
|
||||
BAD_ALLOCATION_TYPE, // T_NARROWOOP = 16,
|
||||
BAD_ALLOCATION_TYPE, // T_METADATA = 17,
|
||||
BAD_ALLOCATION_TYPE, // T_NARROWKLASS = 18,
|
||||
BAD_ALLOCATION_TYPE, // T_CONFLICT = 19,
|
||||
};
|
||||
|
||||
static FieldAllocationType basic_type_to_atype(bool is_static, BasicType type) {
|
||||
@ -3192,8 +3191,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
|
||||
KlassHandle kh (THREAD, k);
|
||||
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->is_interface()) {
|
||||
@ -3639,7 +3636,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
// has to be changed accordingly.
|
||||
this_klass->set_initial_method_idnum(methods->length());
|
||||
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
|
||||
|
||||
if (fields_annotations != NULL ||
|
||||
|
@ -344,7 +344,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
// constant pool construction, but in later versions they can.
|
||||
// %%% Let's phase out the old is_klass_reference.
|
||||
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_reference());
|
||||
}
|
||||
|
@ -291,16 +291,6 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
|
||||
Handle protection_domain,
|
||||
bool is_superclass,
|
||||
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
|
||||
// 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.
|
||||
@ -926,14 +916,6 @@ Klass* SystemDictionary::find_instance_or_array_klass(Symbol* class_name,
|
||||
Klass* k = 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)) {
|
||||
// The name refers to an array. Parse the name.
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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
|
||||
// updates no supplemental data structures.
|
||||
// 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));
|
||||
|
||||
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:
|
||||
start_id = limit_id;
|
||||
}
|
||||
|
||||
|
||||
void SystemDictionary::initialize_preloaded_classes(TRAPS) {
|
||||
assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once");
|
||||
// Preload commonly used klasses
|
||||
|
@ -92,93 +92,93 @@ class SymbolPropertyTable;
|
||||
// The order of these definitions is significant; it is the order in which
|
||||
// preloading is actually performed by initialize_preloaded_classes.
|
||||
|
||||
#define WK_KLASSES_DO(template) \
|
||||
/* well-known classes */ \
|
||||
template(Object_klass, java_lang_Object, Pre) \
|
||||
template(String_klass, java_lang_String, Pre) \
|
||||
template(Class_klass, java_lang_Class, Pre) \
|
||||
template(Cloneable_klass, java_lang_Cloneable, Pre) \
|
||||
template(ClassLoader_klass, java_lang_ClassLoader, Pre) \
|
||||
template(Serializable_klass, java_io_Serializable, Pre) \
|
||||
template(System_klass, java_lang_System, Pre) \
|
||||
template(Throwable_klass, java_lang_Throwable, Pre) \
|
||||
template(Error_klass, java_lang_Error, Pre) \
|
||||
template(ThreadDeath_klass, java_lang_ThreadDeath, Pre) \
|
||||
template(Exception_klass, java_lang_Exception, Pre) \
|
||||
template(RuntimeException_klass, java_lang_RuntimeException, Pre) \
|
||||
template(ProtectionDomain_klass, java_security_ProtectionDomain, Pre) \
|
||||
template(AccessControlContext_klass, java_security_AccessControlContext, Pre) \
|
||||
template(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre) \
|
||||
template(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre) \
|
||||
template(LinkageError_klass, java_lang_LinkageError, Pre) \
|
||||
template(ClassCastException_klass, java_lang_ClassCastException, Pre) \
|
||||
template(ArrayStoreException_klass, java_lang_ArrayStoreException, Pre) \
|
||||
template(VirtualMachineError_klass, java_lang_VirtualMachineError, Pre) \
|
||||
template(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre) \
|
||||
template(StackOverflowError_klass, java_lang_StackOverflowError, Pre) \
|
||||
template(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, Pre) \
|
||||
template(Reference_klass, java_lang_ref_Reference, Pre) \
|
||||
\
|
||||
/* Preload ref klasses and set reference types */ \
|
||||
template(SoftReference_klass, java_lang_ref_SoftReference, Pre) \
|
||||
template(WeakReference_klass, java_lang_ref_WeakReference, Pre) \
|
||||
template(FinalReference_klass, java_lang_ref_FinalReference, Pre) \
|
||||
template(PhantomReference_klass, java_lang_ref_PhantomReference, Pre) \
|
||||
template(Finalizer_klass, java_lang_ref_Finalizer, Pre) \
|
||||
\
|
||||
template(Thread_klass, java_lang_Thread, Pre) \
|
||||
template(ThreadGroup_klass, java_lang_ThreadGroup, Pre) \
|
||||
template(Properties_klass, java_util_Properties, Pre) \
|
||||
template(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre) \
|
||||
template(reflect_Field_klass, java_lang_reflect_Field, Pre) \
|
||||
template(reflect_Method_klass, java_lang_reflect_Method, Pre) \
|
||||
template(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre) \
|
||||
\
|
||||
#define WK_KLASSES_DO(do_klass) \
|
||||
/* well-known classes */ \
|
||||
do_klass(Object_klass, java_lang_Object, Pre ) \
|
||||
do_klass(String_klass, java_lang_String, Pre ) \
|
||||
do_klass(Class_klass, java_lang_Class, Pre ) \
|
||||
do_klass(Cloneable_klass, java_lang_Cloneable, Pre ) \
|
||||
do_klass(ClassLoader_klass, java_lang_ClassLoader, Pre ) \
|
||||
do_klass(Serializable_klass, java_io_Serializable, Pre ) \
|
||||
do_klass(System_klass, java_lang_System, Pre ) \
|
||||
do_klass(Throwable_klass, java_lang_Throwable, Pre ) \
|
||||
do_klass(Error_klass, java_lang_Error, Pre ) \
|
||||
do_klass(ThreadDeath_klass, java_lang_ThreadDeath, Pre ) \
|
||||
do_klass(Exception_klass, java_lang_Exception, Pre ) \
|
||||
do_klass(RuntimeException_klass, java_lang_RuntimeException, Pre ) \
|
||||
do_klass(ProtectionDomain_klass, java_security_ProtectionDomain, Pre ) \
|
||||
do_klass(AccessControlContext_klass, java_security_AccessControlContext, Pre ) \
|
||||
do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre ) \
|
||||
do_klass(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre ) \
|
||||
do_klass(LinkageError_klass, java_lang_LinkageError, Pre ) \
|
||||
do_klass(ClassCastException_klass, java_lang_ClassCastException, Pre ) \
|
||||
do_klass(ArrayStoreException_klass, java_lang_ArrayStoreException, Pre ) \
|
||||
do_klass(VirtualMachineError_klass, java_lang_VirtualMachineError, Pre ) \
|
||||
do_klass(OutOfMemoryError_klass, java_lang_OutOfMemoryError, Pre ) \
|
||||
do_klass(StackOverflowError_klass, java_lang_StackOverflowError, Pre ) \
|
||||
do_klass(IllegalMonitorStateException_klass, java_lang_IllegalMonitorStateException, Pre ) \
|
||||
do_klass(Reference_klass, java_lang_ref_Reference, Pre ) \
|
||||
\
|
||||
/* Preload ref klasses and set reference types */ \
|
||||
do_klass(SoftReference_klass, java_lang_ref_SoftReference, Pre ) \
|
||||
do_klass(WeakReference_klass, java_lang_ref_WeakReference, Pre ) \
|
||||
do_klass(FinalReference_klass, java_lang_ref_FinalReference, Pre ) \
|
||||
do_klass(PhantomReference_klass, java_lang_ref_PhantomReference, Pre ) \
|
||||
do_klass(Finalizer_klass, java_lang_ref_Finalizer, Pre ) \
|
||||
\
|
||||
do_klass(Thread_klass, java_lang_Thread, Pre ) \
|
||||
do_klass(ThreadGroup_klass, java_lang_ThreadGroup, Pre ) \
|
||||
do_klass(Properties_klass, java_util_Properties, Pre ) \
|
||||
do_klass(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre ) \
|
||||
do_klass(reflect_Field_klass, java_lang_reflect_Field, Pre ) \
|
||||
do_klass(reflect_Method_klass, java_lang_reflect_Method, 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 */ \
|
||||
/* 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. */ \
|
||||
template(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt) \
|
||||
template(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||
template(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||
template(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt) \
|
||||
template(reflect_ConstantPool_klass, sun_reflect_ConstantPool, Opt_Only_JDK15) \
|
||||
template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
|
||||
\
|
||||
/* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
|
||||
template(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre_JSR292) \
|
||||
template(MemberName_klass, java_lang_invoke_MemberName, Pre_JSR292) \
|
||||
template(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives, Pre_JSR292) \
|
||||
template(LambdaForm_klass, java_lang_invoke_LambdaForm, Opt) \
|
||||
template(MethodType_klass, java_lang_invoke_MethodType, Pre_JSR292) \
|
||||
template(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre_JSR292) \
|
||||
template(CallSite_klass, java_lang_invoke_CallSite, Pre_JSR292) \
|
||||
template(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite, Pre_JSR292) \
|
||||
template(MutableCallSite_klass, java_lang_invoke_MutableCallSite, Pre_JSR292) \
|
||||
template(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre_JSR292) \
|
||||
/* Note: MethodHandle must be first, and VolatileCallSite last in group */ \
|
||||
\
|
||||
template(StringBuffer_klass, java_lang_StringBuffer, Pre) \
|
||||
template(StringBuilder_klass, java_lang_StringBuilder, Pre) \
|
||||
\
|
||||
/* It's NULL in non-1.4 JDKs. */ \
|
||||
template(StackTraceElement_klass, java_lang_StackTraceElement, Opt) \
|
||||
/* 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. */ \
|
||||
template(nio_Buffer_klass, java_nio_Buffer, Opt) \
|
||||
\
|
||||
template(DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel) \
|
||||
\
|
||||
template(PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt) \
|
||||
\
|
||||
/* Preload boxing klasses */ \
|
||||
template(Boolean_klass, java_lang_Boolean, Pre) \
|
||||
template(Character_klass, java_lang_Character, Pre) \
|
||||
template(Float_klass, java_lang_Float, Pre) \
|
||||
template(Double_klass, java_lang_Double, Pre) \
|
||||
template(Byte_klass, java_lang_Byte, Pre) \
|
||||
template(Short_klass, java_lang_Short, Pre) \
|
||||
template(Integer_klass, java_lang_Integer, Pre) \
|
||||
template(Long_klass, java_lang_Long, Pre) \
|
||||
do_klass(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt ) \
|
||||
do_klass(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||
do_klass(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||
do_klass(reflect_DelegatingClassLoader_klass, sun_reflect_DelegatingClassLoader, Opt ) \
|
||||
do_klass(reflect_ConstantPool_klass, sun_reflect_ConstantPool, 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 */ \
|
||||
do_klass(MethodHandle_klass, java_lang_invoke_MethodHandle, Pre_JSR292 ) \
|
||||
do_klass(MemberName_klass, java_lang_invoke_MemberName, Pre_JSR292 ) \
|
||||
do_klass(MethodHandleNatives_klass, java_lang_invoke_MethodHandleNatives, Pre_JSR292 ) \
|
||||
do_klass(LambdaForm_klass, java_lang_invoke_LambdaForm, Opt ) \
|
||||
do_klass(MethodType_klass, java_lang_invoke_MethodType, Pre_JSR292 ) \
|
||||
do_klass(BootstrapMethodError_klass, java_lang_BootstrapMethodError, Pre_JSR292 ) \
|
||||
do_klass(CallSite_klass, java_lang_invoke_CallSite, Pre_JSR292 ) \
|
||||
do_klass(ConstantCallSite_klass, java_lang_invoke_ConstantCallSite, Pre_JSR292 ) \
|
||||
do_klass(MutableCallSite_klass, java_lang_invoke_MutableCallSite, Pre_JSR292 ) \
|
||||
do_klass(VolatileCallSite_klass, java_lang_invoke_VolatileCallSite, Pre_JSR292 ) \
|
||||
/* Note: MethodHandle must be first, and VolatileCallSite last in group */ \
|
||||
\
|
||||
do_klass(StringBuffer_klass, java_lang_StringBuffer, Pre ) \
|
||||
do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \
|
||||
\
|
||||
/* It's NULL in non-1.4 JDKs. */ \
|
||||
do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \
|
||||
/* 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. */ \
|
||||
do_klass(nio_Buffer_klass, java_nio_Buffer, Opt ) \
|
||||
\
|
||||
do_klass(DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel ) \
|
||||
\
|
||||
do_klass(PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt ) \
|
||||
\
|
||||
/* Preload boxing klasses */ \
|
||||
do_klass(Boolean_klass, java_lang_Boolean, Pre ) \
|
||||
do_klass(Character_klass, java_lang_Character, Pre ) \
|
||||
do_klass(Float_klass, java_lang_Float, Pre ) \
|
||||
do_klass(Double_klass, java_lang_Double, Pre ) \
|
||||
do_klass(Byte_klass, java_lang_Byte, Pre ) \
|
||||
do_klass(Short_klass, java_lang_Short, Pre ) \
|
||||
do_klass(Integer_klass, java_lang_Integer, Pre ) \
|
||||
do_klass(Long_klass, java_lang_Long, Pre ) \
|
||||
/*end*/
|
||||
|
||||
|
||||
@ -280,9 +280,6 @@ public:
|
||||
Handle protection_domain,
|
||||
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
|
||||
// either into the given class loader, or else into another class
|
||||
// loader that is constrained (via loader constraints) to produce
|
||||
@ -392,9 +389,9 @@ public:
|
||||
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_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_Only_JDK15(Klass* k) {
|
||||
assert(JDK_Version::is_gte_jdk15x_version(), "JDK 1.5 only");
|
||||
|
@ -324,24 +324,6 @@ vmIntrinsics::ID vmIntrinsics::for_raw_conversion(BasicType src, BasicType dest)
|
||||
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"
|
||||
static const char* vm_intrinsic_name_bodies =
|
||||
|
@ -1138,9 +1138,6 @@ public:
|
||||
|
||||
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:
|
||||
static ID for_boxing(BasicType type);
|
||||
static ID for_unboxing(BasicType type);
|
||||
|
@ -333,12 +333,14 @@ void Dependencies::encode_content_bytes() {
|
||||
for (int j = 0; j < stride; j++) {
|
||||
if (j == skipj) continue;
|
||||
ciBaseObject* v = deps->at(i+j);
|
||||
int idx;
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -573,8 +575,8 @@ void Dependencies::DepStream::log_dependency(Klass* witness) {
|
||||
if (type() == call_site_target_value) {
|
||||
args[j] = argument_oop(j);
|
||||
} else {
|
||||
args[j] = argument(j);
|
||||
}
|
||||
args[j] = argument(j);
|
||||
}
|
||||
}
|
||||
if (_deps != NULL && _deps->log() != NULL) {
|
||||
Dependencies::write_dependency_to(_deps->log(),
|
||||
@ -665,6 +667,14 @@ inline oop Dependencies::DepStream::recorded_oop_at(int i) {
|
||||
|
||||
Metadata* Dependencies::DepStream::argument(int 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");
|
||||
return result;
|
||||
}
|
||||
@ -680,25 +690,21 @@ Klass* Dependencies::DepStream::context_type() {
|
||||
|
||||
// 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) {
|
||||
Metadata* k = argument(ctxkj);
|
||||
if (k != NULL) { // context type was not compressed away
|
||||
assert(k->is_klass(), "type check");
|
||||
return (Klass*) k;
|
||||
}
|
||||
// recompute "default" context type
|
||||
return ctxk_encoded_as_null(_type, argument(ctxkj+1));
|
||||
assert(k != NULL && k->is_klass(), "type check");
|
||||
return (Klass*)k;
|
||||
}
|
||||
}
|
||||
|
||||
// Some dependencies are using the klass of the first object
|
||||
// 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) {
|
||||
Klass* k = argument_oop(ctxkj)->klass();
|
||||
assert(k->is_klass(), "type check");
|
||||
assert(k != NULL && k->is_klass(), "type check");
|
||||
return (Klass*) k;
|
||||
}
|
||||
}
|
||||
|
@ -1570,7 +1570,8 @@ void CompileBroker::compiler_thread_loop() {
|
||||
}
|
||||
CompileLog* log = thread->log();
|
||||
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_process_id());
|
||||
log->stamp();
|
||||
|
@ -302,3 +302,48 @@ void CompileLog::finish_log(outputStream* file) {
|
||||
char buf[4 * K];
|
||||
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("");
|
||||
}
|
||||
|
@ -62,7 +62,13 @@ class CompileLog : public xmlStream {
|
||||
|
||||
intx thread_id() { return _thread_id; }
|
||||
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; }
|
||||
void clear_context() { context()->reset(); }
|
||||
void set_context(const char* format, ...);
|
||||
|
||||
void name(ciSymbol* s); // name='s'
|
||||
void name(Symbol* s) { xmlStream::name(s); }
|
||||
@ -71,6 +77,9 @@ class CompileLog : public xmlStream {
|
||||
int identify(ciBaseObject* obj);
|
||||
void clear_identities();
|
||||
|
||||
void inline_fail (const char* reason);
|
||||
void inline_success(const char* reason);
|
||||
|
||||
// virtuals
|
||||
virtual void see_tag(const char* tag, bool push);
|
||||
virtual void pop_tag(const char* tag);
|
||||
@ -78,6 +87,9 @@ class CompileLog : public xmlStream {
|
||||
// make a provisional end of log mark
|
||||
void mark_file_end() { _file_end = out()->count(); }
|
||||
|
||||
// Print code cache statistics
|
||||
void code_cache_state();
|
||||
|
||||
// copy all logs to the given stream
|
||||
static void finish_log(outputStream* out);
|
||||
static void finish_log_on_error(outputStream* out, char *buf, int buflen);
|
||||
|
@ -222,7 +222,7 @@ ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration(
|
||||
// depends on this property.
|
||||
debug_only(
|
||||
FreeChunk* junk = NULL;
|
||||
assert(UseCompressedOops ||
|
||||
assert(UseCompressedKlassPointers ||
|
||||
junk->prev_addr() == (void*)(oop(junk)->klass_addr()),
|
||||
"Offset of FreeChunk::_prev within FreeChunk must match"
|
||||
" that of OopDesc::_klass within OopDesc");
|
||||
|
@ -135,6 +135,8 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||
MetaWord* expand_and_allocate(size_t size,
|
||||
MetadataType mdtype);
|
||||
|
||||
static bool is_initialized() { return _class_space_list != NULL; }
|
||||
|
||||
#ifndef PRODUCT
|
||||
bool contains(const void *ptr) const;
|
||||
bool contains_class(const void *ptr) const;
|
||||
|
@ -151,7 +151,9 @@ size_t Universe::_heap_used_at_last_gc = 0;
|
||||
|
||||
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*)) {
|
||||
@ -807,7 +809,7 @@ jint Universe::initialize_heap() {
|
||||
}
|
||||
if ((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) {
|
||||
// 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);
|
||||
if (verbose) {
|
||||
tty->print(", Compressed Oops with base: "PTR_FORMAT, Universe::narrow_oop_base());
|
||||
@ -838,8 +840,16 @@ jint Universe::initialize_heap() {
|
||||
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));
|
||||
}
|
||||
Universe::set_narrow_ptrs_base(Universe::narrow_oop_base());
|
||||
}
|
||||
assert(Universe::narrow_oop_base() == (Universe::heap()->base() - os::vm_page_size()) ||
|
||||
// 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");
|
||||
assert(Universe::narrow_oop_shift() == LogMinObjAlignmentInBytes ||
|
||||
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) {
|
||||
// Add in the class metaspace area so the classes in the headers can
|
||||
// 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Split the reserved space into main Java heap and a space for classes
|
||||
// so that they can be compressed using the same algorithm as compressed oops
|
||||
ReservedSpace heap_rs = total_rs.first_part(heap_size);
|
||||
ReservedSpace class_rs = total_rs.last_part(heap_size, alignment);
|
||||
// Split the reserved space into main Java heap and a space for
|
||||
// classes so that they can be compressed using the same algorithm
|
||||
// as compressed oops. If compress oops and compress klass ptrs are
|
||||
// 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -105,16 +105,16 @@ class LatestMethodOopCache : public CommonMethodOopCache {
|
||||
Method* get_Method();
|
||||
};
|
||||
|
||||
// For UseCompressedOops.
|
||||
struct NarrowOopStruct {
|
||||
// Base address for oop-within-java-object materialization.
|
||||
// NULL if using wide oops or zero based narrow oops.
|
||||
// For UseCompressedOops and UseCompressedKlassPointers.
|
||||
struct NarrowPtrStruct {
|
||||
// Base address for oop/klass-within-java-object materialization.
|
||||
// NULL if using wide oops/klasses or zero based narrow oops/klasses.
|
||||
address _base;
|
||||
// Number of shift bits for encoding/decoding narrow oops.
|
||||
// 0 if using wide oops or zero based unscaled narrow oops,
|
||||
// LogMinObjAlignmentInBytes otherwise.
|
||||
// Number of shift bits for encoding/decoding narrow ptrs.
|
||||
// 0 if using wide ptrs or zero based unscaled narrow ptrs,
|
||||
// LogMinObjAlignmentInBytes/LogKlassAlignmentInBytes otherwise.
|
||||
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;
|
||||
};
|
||||
|
||||
@ -206,7 +206,10 @@ class Universe: AllStatic {
|
||||
static CollectedHeap* _collectedHeap;
|
||||
|
||||
// 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
|
||||
debug_only(static objArrayOop _fullgc_alot_dummy_array;)
|
||||
@ -259,8 +262,21 @@ class Universe: AllStatic {
|
||||
HeapBasedNarrowOop = 2
|
||||
};
|
||||
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 void set_narrow_oop_use_implicit_null_checks(bool use) { _narrow_oop._use_implicit_null_checks = use; }
|
||||
static char* preferred_metaspace_base(size_t heap_size, NARROW_OOP_MODE mode);
|
||||
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
|
||||
static int _verify_count; // number of verifies done
|
||||
@ -354,14 +370,30 @@ class Universe: AllStatic {
|
||||
static CollectedHeap* heap() { return _collectedHeap; }
|
||||
|
||||
// For UseCompressedOops
|
||||
static address* narrow_oop_base_addr() { 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 int narrow_oop_shift() { return _narrow_oop._shift; }
|
||||
static bool narrow_oop_use_implicit_null_checks() { return _narrow_oop._use_implicit_null_checks; }
|
||||
static address narrow_oop_base() { return _narrow_oop._base; }
|
||||
static bool is_narrow_oop_base(void* addr) { return (narrow_oop_base() == (address)addr); }
|
||||
static int narrow_oop_shift() { return _narrow_oop._shift; }
|
||||
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)
|
||||
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
|
||||
static ReservedSpace reserve_heap(size_t heap_size, size_t alignment);
|
||||
|
@ -37,7 +37,9 @@ class instanceOopDesc : public oopDesc {
|
||||
|
||||
// If compressed, the offset of the fields of the instance may not be aligned.
|
||||
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() :
|
||||
sizeof(instanceOopDesc);
|
||||
}
|
||||
|
@ -712,7 +712,8 @@ void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report)
|
||||
}
|
||||
if ((TraceDeoptimization || LogCompilation) && (xtty != NULL)) {
|
||||
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->stamp();
|
||||
xtty->end_elem();
|
||||
|
@ -185,8 +185,8 @@ inline bool oopDesc::is_null(narrowOop obj) { return obj == 0; }
|
||||
inline bool check_obj_alignment(oop obj) {
|
||||
return (intptr_t)obj % MinObjAlignmentInBytes == 0;
|
||||
}
|
||||
inline bool check_obj_alignment(Klass* obj) {
|
||||
return (intptr_t)obj % MinObjAlignmentInBytes == 0;
|
||||
inline bool check_klass_alignment(Klass* obj) {
|
||||
return (intptr_t)obj % KlassAlignmentInBytes == 0;
|
||||
}
|
||||
|
||||
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) {
|
||||
assert(!is_null(v), "oop value can never be zero");
|
||||
assert(check_obj_alignment(v), "Address not aligned");
|
||||
address base = Universe::narrow_oop_base();
|
||||
int shift = Universe::narrow_oop_shift();
|
||||
assert(check_klass_alignment(v), "Address not aligned");
|
||||
address base = Universe::narrow_klass_base();
|
||||
int shift = Universe::narrow_klass_shift();
|
||||
uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1));
|
||||
assert(OopEncodingHeapMax > pd, "change encoding max if new encoding");
|
||||
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) {
|
||||
assert(!is_null(v), "narrow oop value can never be zero");
|
||||
address base = Universe::narrow_oop_base();
|
||||
int shift = Universe::narrow_oop_shift();
|
||||
address base = Universe::narrow_klass_base();
|
||||
int shift = Universe::narrow_klass_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;
|
||||
}
|
||||
|
||||
|
@ -439,9 +439,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
|
||||
WarmCallInfo wci = *(initial_wci);
|
||||
failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci);
|
||||
if (failure_msg != NULL && C->log() != NULL) {
|
||||
C->log()->begin_elem("inline_fail reason='");
|
||||
C->log()->text("%s", failure_msg);
|
||||
C->log()->end_elem("'");
|
||||
C->log()->inline_fail(failure_msg);
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
@ -1386,7 +1386,7 @@ static Node* split_flow_path(PhaseGVN *phase, PhiNode *phi) {
|
||||
Node *n = phi->in(i);
|
||||
if( !n ) 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;
|
||||
}
|
||||
if( i >= phi->req() ) // Only split for constants
|
||||
@ -1875,17 +1875,19 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
}
|
||||
|
||||
#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.
|
||||
if (UseCompressedOops && can_reshape && progress == NULL) {
|
||||
if ((UseCompressedOops || UseCompressedKlassPointers) && can_reshape && progress == NULL) {
|
||||
bool may_push = true;
|
||||
bool has_decodeN = false;
|
||||
bool is_decodeN = false;
|
||||
for (uint i=1; i<req(); ++i) {// For all paths in
|
||||
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.
|
||||
if (ii->in(1)->bottom_type() != Type::TOP) {
|
||||
has_decodeN = true;
|
||||
is_decodeN = ii->is_DecodeN();
|
||||
}
|
||||
} else if (!ii->is_Phi()) {
|
||||
may_push = false;
|
||||
@ -1895,13 +1897,18 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
if (has_decodeN && may_push) {
|
||||
PhaseIterGVN *igvn = phase->is_IterGVN();
|
||||
// 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);
|
||||
uint orig_cnt = req();
|
||||
for (uint i=1; i<req(); ++i) {// For all paths in
|
||||
Node *ii = in(i);
|
||||
Node* new_ii = NULL;
|
||||
if (ii->is_DecodeN()) {
|
||||
if (ii->is_DecodeNarrowPtr()) {
|
||||
assert(ii->bottom_type() == bottom_type(), "sanity");
|
||||
new_ii = ii->in(1);
|
||||
} else {
|
||||
@ -1909,14 +1916,22 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
if (ii->as_Phi() == this) {
|
||||
new_ii = new_phi;
|
||||
} else {
|
||||
new_ii = new (phase->C) EncodePNode(ii, narrow_t);
|
||||
if (is_decodeN) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
new_phi->set_req(i, new_ii);
|
||||
}
|
||||
igvn->register_new_node_with_optimizer(new_phi, this);
|
||||
progress = new (phase->C) DecodeNNode(new_phi, bottom_type());
|
||||
if (is_decodeN) {
|
||||
progress = new (phase->C) DecodeNNode(new_phi, bottom_type());
|
||||
} else {
|
||||
progress = new (phase->C) DecodeNKlassNode(new_phi, bottom_type());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -91,6 +91,7 @@ macro(GetAndSetP)
|
||||
macro(GetAndSetN)
|
||||
macro(Con)
|
||||
macro(ConN)
|
||||
macro(ConNKlass)
|
||||
macro(ConD)
|
||||
macro(ConF)
|
||||
macro(ConI)
|
||||
@ -118,6 +119,7 @@ macro(CountTrailingZerosI)
|
||||
macro(CountTrailingZerosL)
|
||||
macro(CreateEx)
|
||||
macro(DecodeN)
|
||||
macro(DecodeNKlass)
|
||||
macro(DivD)
|
||||
macro(DivF)
|
||||
macro(DivI)
|
||||
@ -126,6 +128,7 @@ macro(DivMod)
|
||||
macro(DivModI)
|
||||
macro(DivModL)
|
||||
macro(EncodeP)
|
||||
macro(EncodePKlass)
|
||||
macro(ExpD)
|
||||
macro(FastLock)
|
||||
macro(FastUnlock)
|
||||
@ -147,7 +150,6 @@ macro(LoadD)
|
||||
macro(LoadD_unaligned)
|
||||
macro(LoadF)
|
||||
macro(LoadI)
|
||||
macro(LoadUI2L)
|
||||
macro(LoadKlass)
|
||||
macro(LoadNKlass)
|
||||
macro(LoadL)
|
||||
@ -233,6 +235,7 @@ macro(StoreI)
|
||||
macro(StoreL)
|
||||
macro(StoreP)
|
||||
macro(StoreN)
|
||||
macro(StoreNKlass)
|
||||
macro(StrComp)
|
||||
macro(StrEquals)
|
||||
macro(StrIndexOf)
|
||||
|
@ -828,6 +828,9 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
has_unsafe_access(),
|
||||
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_CheckCastPP &&
|
||||
nop != Op_DecodeN &&
|
||||
nop != Op_DecodeNKlass &&
|
||||
!n->is_Mem() ) {
|
||||
Node *x = n->clone();
|
||||
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_StoreP:
|
||||
case Op_StoreN:
|
||||
case Op_StoreNKlass:
|
||||
case Op_LoadB:
|
||||
case Op_LoadUB:
|
||||
case Op_LoadUS:
|
||||
case Op_LoadI:
|
||||
case Op_LoadUI2L:
|
||||
case Op_LoadKlass:
|
||||
case Op_LoadNKlass:
|
||||
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),
|
||||
"Base pointers must match" );
|
||||
#ifdef _LP64
|
||||
if (UseCompressedOops &&
|
||||
if ((UseCompressedOops || UseCompressedKlassPointers) &&
|
||||
addp->Opcode() == Op_ConP &&
|
||||
addp == n->in(AddPNode::Base) &&
|
||||
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).
|
||||
// Do this transformation here since IGVN will convert ConN back to ConP.
|
||||
const Type* t = addp->bottom_type();
|
||||
if (t->isa_oopptr()) {
|
||||
if (t->isa_oopptr() || t->isa_klassptr()) {
|
||||
Node* nn = NULL;
|
||||
|
||||
int op = t->isa_oopptr() ? Op_ConN : Op_ConNKlass;
|
||||
|
||||
// Look for existing ConN node of the same exact type.
|
||||
Compile* C = Compile::current();
|
||||
Node* r = C->root();
|
||||
uint cnt = r->outcnt();
|
||||
for (uint i = 0; i < cnt; 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) {
|
||||
nn = m;
|
||||
break;
|
||||
@ -2345,7 +2351,11 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
|
||||
if (nn != NULL) {
|
||||
// Decode a narrow oop to match address
|
||||
// [R12 + narrow_oop_reg<<3 + offset]
|
||||
nn = new (C) DecodeNNode(nn, t);
|
||||
if (t->isa_oopptr()) {
|
||||
nn = new (C) DecodeNNode(nn, t);
|
||||
} else {
|
||||
nn = new (C) DecodeNKlassNode(nn, t);
|
||||
}
|
||||
n->set_req(AddPNode::Base, nn);
|
||||
n->set_req(AddPNode::Address, nn);
|
||||
if (addp->outcnt() == 0) {
|
||||
@ -2400,22 +2410,24 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
|
||||
case Op_CmpP:
|
||||
// Do this transformation here to preserve CmpPNode::sub() and
|
||||
// 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* in2 = n->in(2);
|
||||
if (!in1->is_DecodeN()) {
|
||||
if (!in1->is_DecodeNarrowPtr()) {
|
||||
in2 = in1;
|
||||
in1 = n->in(2);
|
||||
}
|
||||
assert(in1->is_DecodeN(), "sanity");
|
||||
assert(in1->is_DecodeNarrowPtr(), "sanity");
|
||||
|
||||
Compile* C = Compile::current();
|
||||
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);
|
||||
} else if (in2->Opcode() == Op_ConP) {
|
||||
const Type* t = in2->bottom_type();
|
||||
if (t == TypePtr::NULL_PTR) {
|
||||
assert(in1->is_DecodeN(), "compare klass to null?");
|
||||
// Don't convert CmpP null check into CmpN if compressed
|
||||
// oops implicit null check is not generated.
|
||||
// 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()) {
|
||||
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) {
|
||||
@ -2476,23 +2490,28 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
|
||||
break;
|
||||
|
||||
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
|
||||
// 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;
|
||||
|
||||
case Op_EncodeP: {
|
||||
case Op_EncodeP:
|
||||
case Op_EncodePKlass: {
|
||||
Node* in1 = n->in(1);
|
||||
if (in1->is_DecodeN()) {
|
||||
if (in1->is_DecodeNarrowPtr()) {
|
||||
n->subsume_by(in1->in(1));
|
||||
} else if (in1->Opcode() == Op_ConP) {
|
||||
Compile* C = Compile::current();
|
||||
const Type* t = in1->bottom_type();
|
||||
if (t == TypePtr::NULL_PTR) {
|
||||
assert(t->isa_oopptr(), "null klass?");
|
||||
n->subsume_by(ConNode::make(C, TypeNarrowOop::NULL_PTR));
|
||||
} else if (t->isa_oopptr()) {
|
||||
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) {
|
||||
@ -2526,7 +2545,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
|
||||
}
|
||||
|
||||
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
|
||||
// for all paths. It is not handled well by Register Allocator.
|
||||
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.
|
||||
if (!UseCompressedOops || !Matcher::gen_narrow_oop_implicit_null_checks())
|
||||
if ((UseCompressedOops && !Matcher::gen_narrow_oop_implicit_null_checks()) ||
|
||||
(!UseCompressedOops && !UseCompressedKlassPointers))
|
||||
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
|
||||
// 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) {
|
||||
n = sfpt.pop();
|
||||
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);
|
||||
for (int j = start; j < end; j++) {
|
||||
Node* in = n->in(j);
|
||||
if (in->is_DecodeN()) {
|
||||
if (in->is_DecodeNarrowPtr()) {
|
||||
bool safe_to_skip = true;
|
||||
if (!is_uncommon ) {
|
||||
// Is it safe to skip?
|
||||
|
@ -45,16 +45,17 @@ uint ConNode::hash() const {
|
||||
//------------------------------make-------------------------------------------
|
||||
ConNode *ConNode::make( Compile* C, const Type *t ) {
|
||||
switch( t->basic_type() ) {
|
||||
case T_INT: return new (C) ConINode( t->is_int() );
|
||||
case T_LONG: return new (C) ConLNode( t->is_long() );
|
||||
case T_FLOAT: return new (C) ConFNode( t->is_float_constant() );
|
||||
case T_DOUBLE: return new (C) ConDNode( t->is_double_constant() );
|
||||
case T_VOID: return new (C) ConNode ( Type::TOP );
|
||||
case T_OBJECT: return new (C) ConPNode( t->is_ptr() );
|
||||
case T_ARRAY: return new (C) ConPNode( t->is_aryptr() );
|
||||
case T_ADDRESS: return new (C) ConPNode( t->is_ptr() );
|
||||
case T_NARROWOOP: return new (C) ConNNode( t->is_narrowoop() );
|
||||
case T_METADATA: return new (C) ConPNode( t->is_ptr() );
|
||||
case T_INT: return new (C) ConINode( t->is_int() );
|
||||
case T_LONG: return new (C) ConLNode( t->is_long() );
|
||||
case T_FLOAT: return new (C) ConFNode( t->is_float_constant() );
|
||||
case T_DOUBLE: return new (C) ConDNode( t->is_double_constant() );
|
||||
case T_VOID: return new (C) ConNode ( Type::TOP );
|
||||
case T_OBJECT: return new (C) ConPNode( t->is_ptr() );
|
||||
case T_ARRAY: return new (C) ConPNode( t->is_aryptr() );
|
||||
case T_ADDRESS: return new (C) ConPNode( t->is_ptr() );
|
||||
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() );
|
||||
// Expected cases: TypePtr::NULL_PTR, any is_rawptr()
|
||||
// Also seen: AnyPtr(TopPTR *+top); from command line:
|
||||
// r -XX:+PrintOpto -XX:CIStart=285 -XX:+CompileTheWorld -XX:CompileTheWorldStartAt=660
|
||||
@ -447,7 +448,7 @@ Node *ConstraintCastNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
|
||||
// If not converting int->oop, throw away cast after constant propagation
|
||||
Node *CastPPNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
|
||||
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 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 == 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();
|
||||
}
|
||||
|
||||
|
||||
Node *EncodePNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
|
||||
Node *EncodeNarrowPtrNode::Ideal_DU_postCCP( PhaseCCP *ccp ) {
|
||||
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---------------------------------------
|
||||
Node *Conv2BNode::Identity( PhaseTransform *phase ) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user