This commit is contained in:
J. Duke 2017-07-05 20:34:59 +02:00
commit 70c24bcc29
1340 changed files with 26344 additions and 19932 deletions

View File

@ -307,3 +307,4 @@ ea38728b4f4bdd8fd0d7a89b18069f521cf05013 jdk9-b61
105d045a69174d870b69bfe471b3f2d05a9f8ecc jdk9-b62
0b32ed628fa60e4ab99fb0b5866d648e16231f17 jdk9-b63
82cf9aab9a83e41c8194ba01af9666afdb856cbe jdk9-b64
7c31f9d7b932f7924f1258d52885b1c7c3e078c2 jdk9-b65

View File

@ -83,7 +83,6 @@ ACCEPTED_BIN_DIFF="
./bin/jcmd
./bin/jconsole
./bin/jdb
./bin/jhat
./bin/jimage
./bin/jinfo
./bin/jjs
@ -163,7 +162,6 @@ ACCEPTED_BIN_DIFF="
./bin/jcmd
./bin/jconsole
./bin/jdb
./bin/jhat
./bin/jimage
./bin/jinfo
./bin/jjs
@ -284,7 +282,6 @@ ACCEPTED_SMALL_SIZE_DIFF="
./bin/jcmd
./bin/jconsole
./bin/jdb
./bin/jhat
./bin/jimage
./bin/jinfo
./bin/jjs
@ -420,7 +417,6 @@ ACCEPTED_SMALL_SIZE_DIFF="
./bin/jcmd
./bin/jconsole
./bin/jdb
./bin/jhat
./bin/jimage
./bin/jinfo
./bin/jjs
@ -499,7 +495,6 @@ ACCEPTED_SMALL_SIZE_DIFF="
./bin/jcmd.exe
./bin/jconsole.exe
./bin/jdb.exe
./bin/jhat.exe
./bin/jimage.exe
./bin/jinfo.exe
./bin/jjs.exe
@ -579,7 +574,6 @@ ACCEPTED_BIN_DIFF="
./bin/jcmd
./bin/jconsole
./bin/jdb
./bin/jhat
./bin/jimage
./bin/jinfo
./bin/jjs

View File

@ -307,3 +307,4 @@ d690f489ca0bb95a6157d996da2fa72bcbcf02ea jdk9-b61
d27f7e0a7aca129969de23e9934408a31b4abf4c jdk9-b62
0acac6937de7a0868f8c6f88b7d036d780abeee6 jdk9-b63
0a5e5a7c3539e8bde73d9fe55750e49a49cb8dac jdk9-b64
afc1e295c4bf83f9a5dd539c29914edd4a754a3f jdk9-b65

View File

@ -6,5 +6,7 @@
^src/share/tools/IdealGraphVisualizer/[a-zA-Z0-9]*/build/
^src/share/tools/IdealGraphVisualizer/build/
^src/share/tools/IdealGraphVisualizer/dist/
^src/share/tools/IdealGraphVisualizer/nbplatform/
.igv.log
^.hgtip
.DS_Store

View File

@ -467,3 +467,4 @@ ee878f3d6732856f7725c590312bfbe2ffa52cc7 jdk9-b58
1eab877142cce6ca06e556e2ad0af688f993f00b jdk9-b62
2ac9b6b36689b50d1562627067c92d51781b5684 jdk9-b63
bf92b8db249cdfa5651ef954b6c0743a7e0ea4cd jdk9-b64
e7ae94c4f35e940ea423fc1dd260435df34a77c0 jdk9-b65

View File

@ -27,9 +27,7 @@ package sun.jvm.hotspot;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.math.*;
import javax.swing.*;
import javax.swing.tree.*;
import java.util.*;
import sun.jvm.hotspot.code.*;
@ -928,7 +926,7 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
boolean shouldSkipOopMaps = false;
if (curVFrame.isCompiledFrame()) {
CodeBlob cb = VM.getVM().getCodeCache().findBlob(curFrame.getPC());
OopMapSet maps = cb.getOopMaps();
ImmutableOopMapSet maps = cb.getOopMaps();
if ((maps == null) || (maps.getSize() == 0)) {
shouldSkipOopMaps = true;
}
@ -977,7 +975,7 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
} while (nextVFrame != null && nextFrame.equals(curFrame));
if (shouldSkipOopMaps) {
anno = anno + "\nNOTE: null or empty OopMapSet found for this CodeBlob";
anno = anno + "\nNOTE: null or empty ImmutableOopMapSet found for this CodeBlob";
}
if (curFrame.getFP() != null) {

View File

@ -171,17 +171,17 @@ public class CodeBlob extends VMObject {
public boolean isLockedByVM() { return false; }
/** OopMap for frame; can return null if none available */
public OopMapSet getOopMaps() {
public ImmutableOopMapSet getOopMaps() {
Address oopMapsAddr = oopMapsField.getValue(addr);
if (oopMapsAddr == null) {
return null;
}
return new OopMapSet(oopMapsAddr);
return new ImmutableOopMapSet(oopMapsAddr);
}
// FIXME: not yet implementable
// void set_oop_maps(OopMapSet* p);
// void set_oop_maps(ImmutableOopMapSet* p);
public OopMap getOopMapForReturnAddress(Address returnAddress, boolean debugging) {
public ImmutableOopMap getOopMapForReturnAddress(Address returnAddress, boolean debugging) {
Address pc = returnAddress;
if (Assert.ASSERTS_ENABLED) {
Assert.that(getOopMaps() != null, "nope");

View File

@ -31,15 +31,9 @@ import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
public class OopMap extends VMObject {
private static CIntegerField pcOffsetField;
private static CIntegerField omvCountField;
private static CIntegerField omvDataSizeField;
private static AddressField omvDataField;
private static AddressField compressedWriteStreamField;
// This is actually a field inside class CompressedStream
private static AddressField compressedStreamBufferField;
public class ImmutableOopMap extends VMObject {
private static CIntegerField countField;
private static long classSize;
static {
VM.registerVMInitializedObserver(new Observer() {
@ -50,52 +44,24 @@ public class OopMap extends VMObject {
}
private static void initialize(TypeDataBase db) {
Type type = db.lookupType("OopMap");
pcOffsetField = type.getCIntegerField("_pc_offset");
omvCountField = type.getCIntegerField("_omv_count");
omvDataSizeField = type.getCIntegerField("_omv_data_size");
omvDataField = type.getAddressField("_omv_data");
compressedWriteStreamField = type.getAddressField("_write_stream");
type = db.lookupType("CompressedStream");
compressedStreamBufferField = type.getAddressField("_buffer");
Type type = db.lookupType("ImmutableOopMap");
countField = type.getCIntegerField("_count");
classSize = type.getSize();
}
public OopMap(Address addr) {
public ImmutableOopMap(Address addr) {
super(addr);
}
public long getOffset() {
return pcOffsetField.getValue(addr);
}
//--------------------------------------------------------------------------------
// Internals only below this point
//
// Accessors -- package private for now
Address getOMVData() {
return omvDataField.getValue(addr);
long getCount() {
return countField.getValue(addr);
}
long getOMVDataSize() {
return omvDataSizeField.getValue(addr);
}
long getOMVCount() {
return omvCountField.getValue(addr);
}
CompressedWriteStream getWriteStream() {
Address wsAddr = compressedWriteStreamField.getValue(addr);
if (wsAddr == null) {
return null;
}
Address bufferAddr = compressedStreamBufferField.getValue(wsAddr);
if (bufferAddr == null) {
return null;
}
return new CompressedWriteStream(bufferAddr);
public Address getData() {
return addr.addOffsetTo(classSize);
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2015, 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.compiler;
import sun.jvm.hotspot.debugger.Address;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.types.CIntegerField;
import sun.jvm.hotspot.types.Type;
import sun.jvm.hotspot.types.TypeDataBase;
import java.util.Observable;
import java.util.Observer;
public class ImmutableOopMapPair {
private static CIntegerField pcField;
private static CIntegerField offsetField;
private static long classSize;
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private final Address address;
public ImmutableOopMapPair(Address address) {
this.address = address;
}
public static long classSize() {
return classSize;
}
public int getPC() {
return (int) pcField.getValue(address);
}
public int getOffset() {
return (int) offsetField.getValue(address);
}
private static void initialize(TypeDataBase db) {
Type type = db.lookupType("ImmutableOopMapPair");
pcField = type.getCIntegerField("_pc_offset");
offsetField = type.getCIntegerField("_oopmap_offset");
classSize = type.getSize();
}
}

View File

@ -32,15 +32,17 @@ import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
public class OopMapSet extends VMObject {
private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.compiler.OopMapSet.DEBUG") != null;
public class ImmutableOopMapSet extends VMObject {
private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.compiler.ImmutableOopMapSet.DEBUG") != null;
private static CIntegerField omCountField;
private static CIntegerField omSizeField;
private static AddressField omDataField;
private static CIntegerField countField;
private static CIntegerField sizeField;
private static AddressField omDataField;
private static int REG_COUNT;
private static int SAVED_ON_ENTRY_REG_COUNT;
private static int C_SAVED_ON_ENTRY_REG_COUNT;
private static long classSize;
private static class MyVisitor implements OopMapVisitor {
private AddressVisitor addressVisitor;
@ -60,7 +62,7 @@ public class OopMapSet extends VMObject {
if (VM.getVM().isClientCompiler()) {
Assert.that(false, "should not reach here");
} else if (VM.getVM().isServerCompiler() &&
VM.getVM().useDerivedPointerTable()) {
VM.getVM().useDerivedPointerTable()) {
Assert.that(false, "FIXME: add derived pointer table");
}
}
@ -75,18 +77,18 @@ public class OopMapSet extends VMObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static void initialize(TypeDataBase db) {
Type type = db.lookupType("OopMapSet");
Type type = db.lookupType("ImmutableOopMapSet");
omCountField = type.getCIntegerField("_om_count");
omSizeField = type.getCIntegerField("_om_size");
omDataField = type.getAddressField("_om_data");
countField = type.getCIntegerField("_count");
sizeField = type.getCIntegerField("_size");
classSize = type.getSize();
if (!VM.getVM().isCore()) {
REG_COUNT = db.lookupIntConstant("REG_COUNT").intValue();
@ -97,29 +99,41 @@ public class OopMapSet extends VMObject {
}
}
public OopMapSet(Address addr) {
public ImmutableOopMapSet(Address addr) {
super(addr);
}
/** Returns the number of OopMaps in this OopMapSet */
/**
* Returns the number of OopMaps in this ImmutableOopMapSet
*/
public long getSize() {
return omCountField.getValue(addr);
return countField.getValue(addr);
}
/** returns the OopMap at a given index */
public OopMap getMapAt(int index) {
public int getCount() { return (int) countField.getValue(addr); }
private Address dataStart() {
return (addr.addOffsetTo(ImmutableOopMapSet.classSize * getCount()));
}
public ImmutableOopMapPair pairAt(int index) {
Assert.that((index >= 0) && (index < getCount()), "bad index");
return new ImmutableOopMapPair(addr.addOffsetTo(index * ImmutableOopMapPair.classSize()));
}
/**
* returns the OopMap at a given index
*/
public ImmutableOopMap getMapAt(int index) {
if (Assert.ASSERTS_ENABLED) {
Assert.that((index >= 0) && (index <= getSize()),"bad index");
Assert.that((index >= 0) && (index <= getSize()), "bad index");
}
Address omDataAddr = omDataField.getValue(addr);
Address oopMapAddr = omDataAddr.getAddressAt(index * VM.getVM().getAddressSize());
if (oopMapAddr == null) {
return null;
}
return new OopMap(oopMapAddr);
ImmutableOopMapPair immutableOopMapPair = pairAt(index);
return getMap(immutableOopMapPair);
}
public OopMap findMapAtOffset(long pcOffset, boolean debugging) {
public ImmutableOopMap findMapAtOffset(long pcOffset, boolean debugging) {
int i;
int len = (int) getSize();
if (Assert.ASSERTS_ENABLED) {
@ -129,7 +143,7 @@ public class OopMapSet extends VMObject {
// Scan through oopmaps. Stop when current offset is either equal or greater
// than the one we are looking for.
for (i = 0; i < len; i++) {
if (getMapAt(i).getOffset() >= pcOffset) {
if (pairAt(i).getPC() >= pcOffset) {
break;
}
}
@ -137,7 +151,7 @@ public class OopMapSet extends VMObject {
if (!debugging) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(i < len, "oopmap not found for pcOffset = " + pcOffset + "; len = " + len);
Assert.that(getMapAt(i).getOffset() == pcOffset, "oopmap not found");
Assert.that(pairAt(i).getPC() == pcOffset, "oopmap not found");
}
} else {
if (i == len) {
@ -145,7 +159,7 @@ public class OopMapSet extends VMObject {
System.out.println("can't find oopmap at " + pcOffset);
System.out.print("Oopmap offsets are [ ");
for (i = 0; i < len; i++) {
System.out.print(getMapAt(i).getOffset());
System.out.print(pairAt(i).getPC());
}
System.out.println("]");
}
@ -154,28 +168,32 @@ public class OopMapSet extends VMObject {
}
}
OopMap m = getMapAt(i);
ImmutableOopMap m = getMapAt(i);
return m;
}
/** Visitation -- iterates through the frame for a compiled method.
This is a very generic mechanism that requires the Address to be
dereferenced by the callee. Other, more specialized, visitation
mechanisms are given below. */
/**
* Visitation -- iterates through the frame for a compiled method.
* This is a very generic mechanism that requires the Address to be
* dereferenced by the callee. Other, more specialized, visitation
* mechanisms are given below.
*/
public static void oopsDo(Frame fr, CodeBlob cb, RegisterMap regMap, AddressVisitor oopVisitor, boolean debugging) {
allDo(fr, cb, regMap, new MyVisitor(oopVisitor), debugging);
}
/** Note that there are 4 required AddressVisitors: one for oops,
one for derived oops, one for values, and one for dead values */
/**
* Note that there are 4 required AddressVisitors: one for oops,
* one for derived oops, one for values, and one for dead values
*/
public static void allDo(Frame fr, CodeBlob cb, RegisterMap regMap, OopMapVisitor visitor, boolean debugging) {
if (Assert.ASSERTS_ENABLED) {
CodeBlob tmpCB = VM.getVM().getCodeCache().findBlob(fr.getPC());
Assert.that(tmpCB != null && cb.equals(tmpCB), "wrong codeblob passed in");
}
OopMapSet maps = cb.getOopMaps();
OopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
ImmutableOopMapSet maps = cb.getOopMaps();
ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
if (Assert.ASSERTS_ENABLED) {
Assert.that(map != null, "no ptr map found");
}
@ -191,7 +209,7 @@ public class OopMapSet extends VMObject {
omv = oms.getCurrent();
Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);
if (loc != null) {
Address baseLoc = fr.oopMapRegToLocation(omv.getContentReg(), regMap);
Address baseLoc = fr.oopMapRegToLocation(omv.getContentReg(), regMap);
Address derivedLoc = loc;
visitor.visitDerivedOopLocation(baseLoc, derivedLoc);
}
@ -199,8 +217,8 @@ public class OopMapSet extends VMObject {
}
// We want narow oop, value and oop oop_types
OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[] {
OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE
OopMapValue.OopTypes[] values = new OopMapValue.OopTypes[]{
OopMapValue.OopTypes.OOP_VALUE, OopMapValue.OopTypes.VALUE_VALUE, OopMapValue.OopTypes.NARROWOOP_VALUE
};
{
@ -223,8 +241,10 @@ public class OopMapSet extends VMObject {
}
}
/** Update callee-saved register info for the following frame.
Should only be called in non-core builds. */
/**
* Update callee-saved register info for the following frame.
* Should only be called in non-core builds.
*/
public static void updateRegisterMap(Frame fr, CodeBlob cb, RegisterMap regMap, boolean debugging) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(!VM.getVM().isCore(), "non-core builds only");
@ -232,14 +252,14 @@ public class OopMapSet extends VMObject {
if (!VM.getVM().isDebugging()) {
if (Assert.ASSERTS_ENABLED) {
OopMapSet maps = cb.getOopMaps();
Assert.that((maps != null) && (maps.getSize() > 0), "found null or empty OopMapSet for CodeBlob");
ImmutableOopMapSet maps = cb.getOopMaps();
Assert.that((maps != null) && (maps.getSize() > 0), "found null or empty ImmutableOopMapSet for CodeBlob");
}
} else {
// Hack for some topmost frames that have been found with empty
// OopMapSets. (Actually have not seen the null case, but don't
// want to take any chances.) See HSDB.showThreadStackMemory().
OopMapSet maps = cb.getOopMaps();
ImmutableOopMapSet maps = cb.getOopMaps();
if ((maps == null) || (maps.getSize() == 0)) {
return;
}
@ -250,18 +270,18 @@ public class OopMapSet extends VMObject {
int nofCallee = 0;
Address[] locs = new Address[2 * REG_COUNT + 1];
VMReg [] regs = new VMReg [2 * REG_COUNT + 1];
VMReg[] regs = new VMReg[2 * REG_COUNT + 1];
// ("+1" because REG_COUNT might be zero)
// Scan through oopmap and find location of all callee-saved registers
// (we do not do update in place, since info could be overwritten)
OopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
if (Assert.ASSERTS_ENABLED) {
Assert.that(map != null, "no ptr map found");
}
OopMapValue omv = null;
for(OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); !oms.isDone(); oms.next()) {
for (OopMapStream oms = new OopMapStream(map, OopMapValue.OopTypes.CALLEE_SAVED_VALUE); !oms.isDone(); oms.next()) {
omv = oms.getCurrent();
if (Assert.ASSERTS_ENABLED) {
Assert.that(nofCallee < 2 * REG_COUNT, "overflow");
@ -276,8 +296,8 @@ public class OopMapSet extends VMObject {
if (Assert.ASSERTS_ENABLED) {
if (VM.getVM().isServerCompiler()) {
Assert.that(!cb.isRuntimeStub() ||
(nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT),
"must save all");
(nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT),
"must save all");
}
}
@ -286,4 +306,13 @@ public class OopMapSet extends VMObject {
regMap.setLocation(regs[i], locs[i]);
}
}
public ImmutableOopMapPair getPairAt(int index) {
return pairAt(index);
}
public ImmutableOopMap getMap(ImmutableOopMapPair pair) {
Assert.that(pair.getOffset() < (int) sizeField.getValue(), "boundary check");
return new ImmutableOopMap(dataStart().addOffsetTo(pair.getOffset()));
}
}

View File

@ -28,30 +28,26 @@ import sun.jvm.hotspot.code.*;
public class OopMapStream {
private CompressedReadStream stream;
private OopMap oopMap;
private ImmutableOopMap oopMap;
private int mask;
private int size;
private int position;
private OopMapValue omv;
private boolean omvValid;
public OopMapStream(OopMap oopMap) {
public OopMapStream(ImmutableOopMap oopMap) {
this(oopMap, (OopMapValue.OopTypes[]) null);
}
public OopMapStream(OopMap oopMap, OopMapValue.OopTypes type) {
public OopMapStream(ImmutableOopMap oopMap, OopMapValue.OopTypes type) {
this(oopMap, (OopMapValue.OopTypes[]) null);
mask = type.getValue();
}
public OopMapStream(OopMap oopMap, OopMapValue.OopTypes[] types) {
if (oopMap.getOMVData() == null) {
stream = new CompressedReadStream(oopMap.getWriteStream().getBuffer());
} else {
stream = new CompressedReadStream(oopMap.getOMVData());
}
public OopMapStream(ImmutableOopMap oopMap, OopMapValue.OopTypes[] types) {
stream = new CompressedReadStream(oopMap.getData());
mask = computeMask(types);
size = (int) oopMap.getOMVCount();
size = (int) oopMap.getCount();
position = 0;
omv = new OopMapValue();
omvValid = false;

View File

@ -26,14 +26,12 @@ package sun.jvm.hotspot.runtime;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.*;
import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.compiler.*;
import sun.jvm.hotspot.c1.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.interpreter.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.sparc.SPARCFrame;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
@ -626,7 +624,7 @@ public abstract class Frame implements Cloneable {
Assert.that(cb != null, "sanity check");
}
if (cb.getOopMaps() != null) {
OopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging());
ImmutableOopMapSet.oopsDo(this, cb, regMap, oopVisitor, VM.getVM().isDebugging());
// FIXME: add in traversal of argument oops (skipping this for
// now until we have the other stuff tested)

View File

@ -358,7 +358,7 @@ public class PPC64Frame extends Frame {
map.setIncludeArgumentOops(cb.callerMustGCArguments());
if (cb.getOopMaps() != null) {
OopMapSet.updateRegisterMap(this, cb, map, true);
ImmutableOopMapSet.updateRegisterMap(this, cb, map, true);
}
}

View File

@ -24,8 +24,6 @@
package sun.jvm.hotspot.runtime.sparc;
import java.util.*;
import sun.jvm.hotspot.asm.sparc.*;
import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.compiler.*;
@ -34,7 +32,6 @@ import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.runtime.posix.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
/** Specialization of and implementation of abstract methods of the
@ -592,7 +589,7 @@ public class SPARCFrame extends Frame {
map.setIncludeArgumentOops(true);
}
if (cb.getOopMaps() != null) {
OopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging());
ImmutableOopMapSet.updateRegisterMap(this, cb, map, VM.getVM().isDebugging());
}
}
}

View File

@ -385,7 +385,7 @@ public class X86Frame extends Frame {
map.setIncludeArgumentOops(cb.callerMustGCArguments());
if (cb.getOopMaps() != null) {
OopMapSet.updateRegisterMap(this, cb, map, true);
ImmutableOopMapSet.updateRegisterMap(this, cb, map, true);
}
// Since the prolog does the save and restore of EBP there is no oopmap

View File

@ -31,11 +31,9 @@ import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.compiler.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.interpreter.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.tools.jcore.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.utilities.*;
public class HTMLGenerator implements /* imports */ ClassConstants {
@ -887,7 +885,7 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
private Formatter buf;
private SymbolFinder symFinder = createSymbolFinder();
private long pc;
private OopMapSet oms;
private ImmutableOopMapSet oms;
private CodeBlob blob;
private NMethod nmethod;
@ -954,13 +952,13 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
if (oms != null) {
long base = addressToLong(blob.codeBegin());
for (int i = 0, imax = (int)oms.getSize(); i < imax; i++) {
OopMap om = oms.getMapAt(i);
long omspc = base + om.getOffset();
for (int i = 0, imax = oms.getCount(); i < imax; i++) {
ImmutableOopMapPair pair = oms.getPairAt(i);
long omspc = base + pair.getPC();
if (omspc > pc) {
if (omspc <= endPc) {
buf.br();
buf.append(genOopMapInfo(om));
buf.append(genOopMapInfo(oms.getMap(pair)));
// st.move_to(column);
// visitor.print("; ");
// om.print_on(st);
@ -1167,7 +1165,7 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
}
}
protected String genHTMLForOopMap(OopMap map) {
protected String genHTMLForOopMap(ImmutableOopMap map) {
final int stack0 = VMRegImpl.getStack0().getValue();
Formatter buf = new Formatter(genHTML);
@ -1237,11 +1235,11 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
protected String genOopMapInfo(NMethod nmethod, PCDesc pcDesc) {
OopMapSet mapSet = nmethod.getOopMaps();
ImmutableOopMapSet mapSet = nmethod.getOopMaps();
if (mapSet == null || (mapSet.getSize() <= 0))
return "";
int pcOffset = pcDesc.getPCOffset();
OopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging());
ImmutableOopMap map = mapSet.findMapAtOffset(pcOffset, VM.getVM().isDebugging());
if (map == null) {
throw new IllegalArgumentException("no oopmap at safepoint!");
}
@ -1249,7 +1247,7 @@ public class HTMLGenerator implements /* imports */ ClassConstants {
return genOopMapInfo(map);
}
protected String genOopMapInfo(OopMap map) {
protected String genOopMapInfo(ImmutableOopMap map) {
Formatter buf = new Formatter(genHTML);
buf.beginTag("pre");
buf.append("OopMap: ");

View File

@ -421,7 +421,40 @@ reg_class any_reg(
);
// Class for all non-special integer registers
reg_class no_special_reg32(
reg_class no_special_reg32_no_fp(
R0,
R1,
R2,
R3,
R4,
R5,
R6,
R7,
R10,
R11,
R12, // rmethod
R13,
R14,
R15,
R16,
R17,
R18,
R19,
R20,
R21,
R22,
R23,
R24,
R25,
R26
/* R27, */ // heapbase
/* R28, */ // thread
/* R29, */ // fp
/* R30, */ // lr
/* R31 */ // sp
);
reg_class no_special_reg32_with_fp(
R0,
R1,
R2,
@ -454,8 +487,43 @@ reg_class no_special_reg32(
/* R31 */ // sp
);
reg_class_dynamic no_special_reg32(no_special_reg32_no_fp, no_special_reg32_with_fp, %{ PreserveFramePointer %});
// Class for all non-special long integer registers
reg_class no_special_reg(
reg_class no_special_reg_no_fp(
R0, R0_H,
R1, R1_H,
R2, R2_H,
R3, R3_H,
R4, R4_H,
R5, R5_H,
R6, R6_H,
R7, R7_H,
R10, R10_H,
R11, R11_H,
R12, R12_H, // rmethod
R13, R13_H,
R14, R14_H,
R15, R15_H,
R16, R16_H,
R17, R17_H,
R18, R18_H,
R19, R19_H,
R20, R20_H,
R21, R21_H,
R22, R22_H,
R23, R23_H,
R24, R24_H,
R25, R25_H,
R26, R26_H,
/* R27, R27_H, */ // heapbase
/* R28, R28_H, */ // thread
/* R29, R29_H, */ // fp
/* R30, R30_H, */ // lr
/* R31, R31_H */ // sp
);
reg_class no_special_reg_with_fp(
R0, R0_H,
R1, R1_H,
R2, R2_H,
@ -488,6 +556,8 @@ reg_class no_special_reg(
/* R31, R31_H */ // sp
);
reg_class_dynamic no_special_reg(no_special_reg_no_fp, no_special_reg_with_fp, %{ PreserveFramePointer %});
// Class for 64 bit register r0
reg_class r0_reg(
R0, R0_H
@ -1637,12 +1707,7 @@ bool needs_releasing_store(const Node *n)
int MachCallStaticJavaNode::ret_addr_offset()
{
// call should be a simple bl
// unless this is a method handle invoke in which case it is
// mov(rfp, sp), bl, mov(sp, rfp)
int off = 4;
if (_method_handle_invoke) {
off += 4;
}
return off;
}
@ -1753,14 +1818,13 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
if (C->need_stack_bang(framesize))
st->print("# stack bang size=%d\n\t", framesize);
if (framesize == 0) {
// Is this even possible?
st->print("stp lr, rfp, [sp, #%d]!", -(2 * wordSize));
} else if (framesize < ((1 << 9) + 2 * wordSize)) {
if (framesize < ((1 << 9) + 2 * wordSize)) {
st->print("sub sp, sp, #%d\n\t", framesize);
st->print("stp rfp, lr, [sp, #%d]", framesize - 2 * wordSize);
if (PreserveFramePointer) st->print("\n\tadd rfp, sp, #%d", framesize - 2 * wordSize);
} else {
st->print("stp lr, rfp, [sp, #%d]!\n\t", -(2 * wordSize));
if (PreserveFramePointer) st->print("mov rfp, sp\n\t");
st->print("mov rscratch1, #%d\n\t", framesize - 2 * wordSize);
st->print("sub sp, sp, rscratch1");
}
@ -3517,34 +3581,6 @@ encode %{
}
%}
enc_class aarch64_enc_java_handle_call(method meth) %{
MacroAssembler _masm(&cbuf);
relocInfo::relocType reloc;
// RFP is preserved across all calls, even compiled calls.
// Use it to preserve SP.
__ mov(rfp, sp);
const int start_offset = __ offset();
address addr = (address)$meth$$method;
if (!_method) {
// A call to a runtime wrapper, e.g. new, new_typeArray_Java, uncommon_trap.
__ trampoline_call(Address(addr, relocInfo::runtime_call_type), &cbuf);
} else if (_optimized_virtual) {
__ trampoline_call(Address(addr, relocInfo::opt_virtual_call_type), &cbuf);
} else {
__ trampoline_call(Address(addr, relocInfo::static_call_type), &cbuf);
}
if (_method) {
// Emit stub for static call
CompiledStaticCall::emit_to_interp_stub(cbuf);
}
// now restore sp
__ mov(sp, rfp);
%}
enc_class aarch64_enc_java_dynamic_call(method meth) %{
MacroAssembler _masm(&cbuf);
__ ic_call((address)$meth$$method);
@ -12561,8 +12597,6 @@ instruct CallStaticJavaDirect(method meth)
effect(USE meth);
predicate(!((CallStaticJavaNode*)n)->is_method_handle_invoke());
ins_cost(CALL_COST);
format %{ "call,static $meth \t// ==> " %}
@ -12575,26 +12609,6 @@ instruct CallStaticJavaDirect(method meth)
// TO HERE
// Call Java Static Instruction (method handle version)
instruct CallStaticJavaDirectHandle(method meth, iRegP_FP reg_mh_save)
%{
match(CallStaticJava);
effect(USE meth);
predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
ins_cost(CALL_COST);
format %{ "call,static $meth \t// (methodhandle) ==> " %}
ins_encode( aarch64_enc_java_handle_call(meth),
aarch64_enc_call_epilog );
ins_pipe(pipe_class_call);
%}
// Call Java Dynamic Instruction
instruct CallDynamicJavaDirect(method meth)
%{

View File

@ -346,8 +346,7 @@ LIR_Opr FrameMap::stack_pointer() {
// JSR 292
LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
// assert(rfp == rbp_mh_SP_save, "must be same register");
return rfp_opr;
return LIR_OprFact::illegalOpr; // Not needed on aarch64
}

View File

@ -443,18 +443,8 @@ OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) {
restore_live_registers(sasm, id != handle_exception_nofpu_id);
break;
case handle_exception_from_callee_id:
// Pop the return address since we are possibly changing SP (restoring from BP).
// Pop the return address.
__ leave();
// Restore SP from FP if the exception PC is a method handle call site.
{
Label nope;
__ ldrw(rscratch1, Address(rthread, JavaThread::is_method_handle_return_offset()));
__ cbzw(rscratch1, nope);
__ mov(sp, rfp);
__ bind(nope);
}
__ ret(lr); // jump to exception handler
break;
default: ShouldNotReachHere();
@ -514,14 +504,6 @@ void Runtime1::generate_unwind_exception(StubAssembler *sasm) {
__ verify_not_null_oop(exception_oop);
{
Label foo;
__ ldrw(rscratch1, Address(rthread, JavaThread::is_method_handle_return_offset()));
__ cbzw(rscratch1, foo);
__ mov(sp, rfp);
__ bind(foo);
}
// continue at exception handler (return address removed)
// note: do *not* remove arguments when unwinding the
// activation since the caller assumes having

View File

@ -223,7 +223,8 @@ bool frame::safe_for_sender(JavaThread *thread) {
if (sender_blob->is_nmethod()) {
nmethod* nm = sender_blob->as_nmethod_or_null();
if (nm != NULL) {
if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc)) {
if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) ||
nm->method()->is_method_handle_intrinsic()) {
return false;
}
}
@ -389,10 +390,9 @@ frame frame::sender_for_entry_frame(RegisterMap* map) const {
// frame::verify_deopt_original_pc
//
// Verifies the calculated original PC of a deoptimization PC for the
// given unextended SP. The unextended SP might also be the saved SP
// for MethodHandle call sites.
// given unextended SP.
#ifdef ASSERT
void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return) {
void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp) {
frame fr;
// This is ugly but it's better than to change {get,set}_original_pc
@ -402,33 +402,23 @@ void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp, bool
address original_pc = nm->get_original_pc(&fr);
assert(nm->insts_contains(original_pc), "original PC must be in nmethod");
assert(nm->is_method_handle_return(original_pc) == is_method_handle_return, "must be");
}
#endif
//------------------------------------------------------------------------------
// frame::adjust_unextended_sp
void frame::adjust_unextended_sp() {
// If we are returning to a compiled MethodHandle call site, the
// saved_fp will in fact be a saved value of the unextended SP. The
// simplest way to tell whether we are returning to such a call site
// is as follows:
// On aarch64, sites calling method handle intrinsics and lambda forms are treated
// as any other call site. Therefore, no special action is needed when we are
// returning to any of these call sites.
nmethod* sender_nm = (_cb == NULL) ? NULL : _cb->as_nmethod_or_null();
if (sender_nm != NULL) {
// If the sender PC is a deoptimization point, get the original
// PC. For MethodHandle call site the unextended_sp is stored in
// saved_fp.
if (sender_nm->is_deopt_mh_entry(_pc)) {
DEBUG_ONLY(verify_deopt_mh_original_pc(sender_nm, _fp));
_unextended_sp = _fp;
}
else if (sender_nm->is_deopt_entry(_pc)) {
// If the sender PC is a deoptimization point, get the original PC.
if (sender_nm->is_deopt_entry(_pc) ||
sender_nm->is_deopt_mh_entry(_pc)) {
DEBUG_ONLY(verify_deopt_original_pc(sender_nm, _unextended_sp));
}
else if (sender_nm->is_method_handle_return(_pc)) {
_unextended_sp = _fp;
}
}
}

View File

@ -167,10 +167,7 @@
#ifdef ASSERT
// Used in frame::sender_for_{interpreter,compiled}_frame
static void verify_deopt_original_pc( nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return = false);
static void verify_deopt_mh_original_pc(nmethod* nm, intptr_t* unextended_sp) {
verify_deopt_original_pc(nm, unextended_sp, true);
}
static void verify_deopt_original_pc( nmethod* nm, intptr_t* unextended_sp);
#endif
public:

View File

@ -47,12 +47,6 @@ static int spin;
inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
intptr_t a = intptr_t(sp);
intptr_t b = intptr_t(fp);
#ifndef PRODUCT
if (fp)
if (sp > fp || (fp - sp > 0x100000))
for(;;)
asm("nop");
#endif
_sp = sp;
_unextended_sp = sp;
_fp = fp;

View File

@ -3788,14 +3788,14 @@ void MacroAssembler::adrp(Register reg1, const Address &dest, unsigned long &byt
}
void MacroAssembler::build_frame(int framesize) {
if (framesize == 0) {
// Is this even possible?
stp(rfp, lr, Address(pre(sp, -2 * wordSize)));
} else if (framesize < ((1 << 9) + 2 * wordSize)) {
assert(framesize > 0, "framesize must be > 0");
if (framesize < ((1 << 9) + 2 * wordSize)) {
sub(sp, sp, framesize);
stp(rfp, lr, Address(sp, framesize - 2 * wordSize));
if (PreserveFramePointer) add(rfp, sp, framesize - 2 * wordSize);
} else {
stp(rfp, lr, Address(pre(sp, -2 * wordSize)));
if (PreserveFramePointer) mov(rfp, sp);
if (framesize < ((1 << 12) + 2 * wordSize))
sub(sp, sp, framesize - 2 * wordSize);
else {
@ -3806,9 +3806,8 @@ void MacroAssembler::build_frame(int framesize) {
}
void MacroAssembler::remove_frame(int framesize) {
if (framesize == 0) {
ldp(rfp, lr, Address(post(sp, 2 * wordSize)));
} else if (framesize < ((1 << 9) + 2 * wordSize)) {
assert(framesize > 0, "framesize must be > 0");
if (framesize < ((1 << 9) + 2 * wordSize)) {
ldp(rfp, lr, Address(sp, framesize - 2 * wordSize));
add(sp, sp, framesize);
} else {

View File

@ -149,7 +149,3 @@ REGISTER_DEFINITION(Register, rthread);
REGISTER_DEFINITION(Register, rheapbase);
REGISTER_DEFINITION(Register, r31_sp);
// TODO : x86 uses rbp to save SP in method handle code
// we may need to do the same with fp
// REGISTER_DEFINITION(Register, rbp_mh_SP_save)

View File

@ -2995,21 +2995,6 @@ void OptoRuntime::generate_exception_blob() {
// r0: exception handler
// Restore SP from BP if the exception PC is a MethodHandle call site.
__ ldrw(rscratch1, Address(rthread, JavaThread::is_method_handle_return_offset()));
// n.b. Intel uses special register rbp_mh_SP_save here but we will
// just hard wire rfp
__ cmpw(rscratch1, zr);
// the obvious way to conditionally copy rfp to sp if NE
// Label skip;
// __ br(Assembler::EQ, skip);
// __ mov(sp, rfp);
// __ bind(skip);
// same but branchless
__ mov(rscratch1, sp);
__ csel(rscratch1, rfp, rscratch1, Assembler::NE);
__ mov(sp, rscratch1);
// We have a handler in r0 (could be deopt blob).
__ mov(r8, r0);

View File

@ -1891,7 +1891,7 @@ class StubGenerator: public StubCodeGenerator {
address start = __ pc();
__ enter();
__ mov(rscratch1, len_reg);
__ mov(rscratch2, len_reg);
__ ldrw(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT)));
__ ld1(v0, __ T16B, rvec);

View File

@ -629,7 +629,7 @@ void VM_Version::config_dscr() {
// Print the detection code.
if (PrintAssembly) {
ttyLocker ttyl;
tty->print_cr("Decoding dscr configuration stub at " INTPTR_FORMAT " before execution:", code);
tty->print_cr("Decoding dscr configuration stub at " INTPTR_FORMAT " before execution:", p2i(code));
Disassembler::decode((u_char*)code, (u_char*)code_end, tty);
}

File diff suppressed because it is too large Load Diff

View File

@ -438,7 +438,7 @@ class ArrayAddress VALUE_OBJ_CLASS_SPEC {
};
const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY( 512 / wordSize);
const int FPUStateSizeInWords = NOT_LP64(27) LP64_ONLY( 512*2 / wordSize);
// The Intel x86/Amd64 Assembler: Pure assembler doing NO optimizations on the instruction
// level (e.g. mov rax, 0 is not translated into xor rax, rax!); i.e., what you write
@ -503,7 +503,8 @@ class Assembler : public AbstractAssembler {
REX_WRXB = 0x4F,
VEX_3bytes = 0xC4,
VEX_2bytes = 0xC5
VEX_2bytes = 0xC5,
EVEX_4bytes = 0x62
};
enum VexPrefix {
@ -513,6 +514,14 @@ class Assembler : public AbstractAssembler {
VEX_W = 0x80
};
enum ExexPrefix {
EVEX_F = 0x04,
EVEX_V = 0x08,
EVEX_Rb = 0x10,
EVEX_X = 0x40,
EVEX_Z = 0x80
};
enum VexSimdPrefix {
VEX_SIMD_NONE = 0x0,
VEX_SIMD_66 = 0x1,
@ -527,6 +536,37 @@ class Assembler : public AbstractAssembler {
VEX_OPCODE_0F_3A = 0x3
};
enum AvxVectorLen {
AVX_128bit = 0x0,
AVX_256bit = 0x1,
AVX_512bit = 0x2,
AVX_NoVec = 0x4
};
enum EvexTupleType {
EVEX_FV = 0,
EVEX_HV = 4,
EVEX_FVM = 6,
EVEX_T1S = 7,
EVEX_T1F = 11,
EVEX_T2 = 13,
EVEX_T4 = 15,
EVEX_T8 = 17,
EVEX_HVM = 18,
EVEX_QVM = 19,
EVEX_OVM = 20,
EVEX_M128 = 21,
EVEX_DUP = 22,
EVEX_ETUP = 23
};
enum EvexInputSizeInBits {
EVEX_8bit = 0,
EVEX_16bit = 1,
EVEX_32bit = 2,
EVEX_64bit = 3
};
enum WhichOperand {
// input to locate_operand, and format code for relocations
imm_operand = 0, // embedded 32-bit|64-bit immediate operand
@ -554,6 +594,11 @@ class Assembler : public AbstractAssembler {
private:
int evex_encoding;
int input_size_in_bits;
int avx_vector_len;
int tuple_type;
bool is_evex_instruction;
// 64bit prefixes
int prefix_and_encode(int reg_enc, bool byteinst = false);
@ -580,108 +625,143 @@ private:
void vex_prefix(bool vex_r, bool vex_b, bool vex_x, bool vex_w,
int nds_enc, VexSimdPrefix pre, VexOpcode opc,
bool vector256);
int vector_len);
void evex_prefix(bool vex_r, bool vex_b, bool vex_x, bool vex_w, bool evex_r, bool evex_v,
int nds_enc, VexSimdPrefix pre, VexOpcode opc,
bool is_extended_context, bool is_merge_context,
int vector_len, bool no_mask_reg );
void vex_prefix(Address adr, int nds_enc, int xreg_enc,
VexSimdPrefix pre, VexOpcode opc,
bool vex_w, bool vector256);
bool vex_w, int vector_len,
bool legacy_mode = false, bool no_mask_reg = false);
void vex_prefix(XMMRegister dst, XMMRegister nds, Address src,
VexSimdPrefix pre, bool vector256 = false) {
VexSimdPrefix pre, int vector_len = AVX_128bit,
bool no_mask_reg = false, bool legacy_mode = false) {
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
vex_prefix(src, nds_enc, dst_enc, pre, VEX_OPCODE_0F, false, vector256);
vex_prefix(src, nds_enc, dst_enc, pre, VEX_OPCODE_0F, false, vector_len, legacy_mode, no_mask_reg);
}
void vex_prefix_0F38(Register dst, Register nds, Address src) {
void vex_prefix_q(XMMRegister dst, XMMRegister nds, Address src,
VexSimdPrefix pre, int vector_len = AVX_128bit,
bool no_mask_reg = false) {
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
vex_prefix(src, nds_enc, dst_enc, pre, VEX_OPCODE_0F, true, vector_len, false, no_mask_reg);
}
void vex_prefix_0F38(Register dst, Register nds, Address src, bool no_mask_reg = false) {
bool vex_w = false;
bool vector256 = false;
int vector_len = AVX_128bit;
vex_prefix(src, nds->encoding(), dst->encoding(),
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector256);
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w,
vector_len, no_mask_reg);
}
void vex_prefix_0F38_q(Register dst, Register nds, Address src) {
void vex_prefix_0F38_q(Register dst, Register nds, Address src, bool no_mask_reg = false) {
bool vex_w = true;
bool vector256 = false;
int vector_len = AVX_128bit;
vex_prefix(src, nds->encoding(), dst->encoding(),
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector256);
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w,
vector_len, no_mask_reg);
}
int vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc,
VexSimdPrefix pre, VexOpcode opc,
bool vex_w, bool vector256);
bool vex_w, int vector_len,
bool legacy_mode, bool no_mask_reg);
int vex_prefix_0F38_and_encode(Register dst, Register nds, Register src) {
int vex_prefix_0F38_and_encode(Register dst, Register nds, Register src, bool no_mask_reg = false) {
bool vex_w = false;
bool vector256 = false;
int vector_len = AVX_128bit;
return vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(),
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector256);
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector_len,
false, no_mask_reg);
}
int vex_prefix_0F38_and_encode_q(Register dst, Register nds, Register src) {
int vex_prefix_0F38_and_encode_q(Register dst, Register nds, Register src, bool no_mask_reg = false) {
bool vex_w = true;
bool vector256 = false;
int vector_len = AVX_128bit;
return vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(),
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector256);
VEX_SIMD_NONE, VEX_OPCODE_0F_38, vex_w, vector_len,
false, no_mask_reg);
}
int vex_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src,
VexSimdPrefix pre, bool vector256 = false,
VexOpcode opc = VEX_OPCODE_0F) {
VexSimdPrefix pre, int vector_len = AVX_128bit,
VexOpcode opc = VEX_OPCODE_0F, bool legacy_mode = false,
bool no_mask_reg = false) {
int src_enc = src->encoding();
int dst_enc = dst->encoding();
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
return vex_prefix_and_encode(dst_enc, nds_enc, src_enc, pre, opc, false, vector256);
return vex_prefix_and_encode(dst_enc, nds_enc, src_enc, pre, opc, false, vector_len, legacy_mode, no_mask_reg);
}
void simd_prefix(XMMRegister xreg, XMMRegister nds, Address adr,
VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F,
bool rex_w = false, bool vector256 = false);
VexSimdPrefix pre, bool no_mask_reg, VexOpcode opc = VEX_OPCODE_0F,
bool rex_w = false, int vector_len = AVX_128bit, bool legacy_mode = false);
void simd_prefix(XMMRegister dst, Address src,
VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F) {
simd_prefix(dst, xnoreg, src, pre, opc);
void simd_prefix(XMMRegister dst, Address src, VexSimdPrefix pre,
bool no_mask_reg, VexOpcode opc = VEX_OPCODE_0F) {
simd_prefix(dst, xnoreg, src, pre, no_mask_reg, opc);
}
void simd_prefix(Address dst, XMMRegister src, VexSimdPrefix pre) {
simd_prefix(src, dst, pre);
void simd_prefix(Address dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg) {
simd_prefix(src, dst, pre, no_mask_reg);
}
void simd_prefix_q(XMMRegister dst, XMMRegister nds, Address src,
VexSimdPrefix pre) {
VexSimdPrefix pre, bool no_mask_reg = false) {
bool rex_w = true;
simd_prefix(dst, nds, src, pre, VEX_OPCODE_0F, rex_w);
simd_prefix(dst, nds, src, pre, no_mask_reg, VEX_OPCODE_0F, rex_w);
}
int simd_prefix_and_encode(XMMRegister dst, XMMRegister nds, XMMRegister src,
VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F,
bool rex_w = false, bool vector256 = false);
VexSimdPrefix pre, bool no_mask_reg,
VexOpcode opc = VEX_OPCODE_0F,
bool rex_w = false, int vector_len = AVX_128bit,
bool legacy_mode = false);
int kreg_prefix_and_encode(KRegister dst, KRegister nds, KRegister src,
VexSimdPrefix pre, bool no_mask_reg,
VexOpcode opc = VEX_OPCODE_0F,
bool rex_w = false, int vector_len = AVX_128bit);
int kreg_prefix_and_encode(KRegister dst, KRegister nds, Register src,
VexSimdPrefix pre, bool no_mask_reg,
VexOpcode opc = VEX_OPCODE_0F,
bool rex_w = false, int vector_len = AVX_128bit);
// Move/convert 32-bit integer value.
int simd_prefix_and_encode(XMMRegister dst, XMMRegister nds, Register src,
VexSimdPrefix pre) {
VexSimdPrefix pre, bool no_mask_reg) {
// It is OK to cast from Register to XMMRegister to pass argument here
// since only encoding is used in simd_prefix_and_encode() and number of
// Gen and Xmm registers are the same.
return simd_prefix_and_encode(dst, nds, as_XMMRegister(src->encoding()), pre);
return simd_prefix_and_encode(dst, nds, as_XMMRegister(src->encoding()), pre, no_mask_reg, VEX_OPCODE_0F);
}
int simd_prefix_and_encode(XMMRegister dst, Register src, VexSimdPrefix pre) {
return simd_prefix_and_encode(dst, xnoreg, src, pre);
int simd_prefix_and_encode(XMMRegister dst, Register src, VexSimdPrefix pre, bool no_mask_reg) {
return simd_prefix_and_encode(dst, xnoreg, src, pre, no_mask_reg);
}
int simd_prefix_and_encode(Register dst, XMMRegister src,
VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F) {
return simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, pre, opc);
VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F,
bool no_mask_reg = false) {
return simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, pre, no_mask_reg, opc);
}
// Move/convert 64-bit integer value.
int simd_prefix_and_encode_q(XMMRegister dst, XMMRegister nds, Register src,
VexSimdPrefix pre) {
VexSimdPrefix pre, bool no_mask_reg = false) {
bool rex_w = true;
return simd_prefix_and_encode(dst, nds, as_XMMRegister(src->encoding()), pre, VEX_OPCODE_0F, rex_w);
return simd_prefix_and_encode(dst, nds, as_XMMRegister(src->encoding()), pre, no_mask_reg, VEX_OPCODE_0F, rex_w);
}
int simd_prefix_and_encode_q(XMMRegister dst, Register src, VexSimdPrefix pre) {
return simd_prefix_and_encode_q(dst, xnoreg, src, pre);
int simd_prefix_and_encode_q(XMMRegister dst, Register src, VexSimdPrefix pre, bool no_mask_reg) {
return simd_prefix_and_encode_q(dst, xnoreg, src, pre, no_mask_reg);
}
int simd_prefix_and_encode_q(Register dst, XMMRegister src,
VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F) {
VexSimdPrefix pre, VexOpcode opc = VEX_OPCODE_0F,
bool no_mask_reg = false) {
bool rex_w = true;
return simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, pre, opc, rex_w);
return simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, pre, no_mask_reg, opc, rex_w);
}
// Helper functions for groups of instructions
@ -692,14 +772,28 @@ private:
void emit_arith_imm32(int op1, int op2, Register dst, int32_t imm32);
void emit_arith(int op1, int op2, Register dst, Register src);
void emit_simd_arith(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre);
void emit_simd_arith(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre);
void emit_simd_arith_nonds(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre);
void emit_simd_arith_nonds(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre);
void emit_simd_arith(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre, bool no_mask_reg = false, bool legacy_mode = false);
void emit_simd_arith_q(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre, bool no_mask_reg = false);
void emit_simd_arith(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg = false, bool legacy_mode = false);
void emit_simd_arith_q(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg = false);
void emit_simd_arith_nonds(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre, bool no_mask_reg = false);
void emit_simd_arith_nonds_q(int opcode, XMMRegister dst, Address src, VexSimdPrefix pre, bool no_mask_reg = false);
void emit_simd_arith_nonds(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg = false, bool legacy_mode = false);
void emit_simd_arith_nonds_q(int opcode, XMMRegister dst, XMMRegister src, VexSimdPrefix pre, bool no_mask_reg = false);
void emit_vex_arith(int opcode, XMMRegister dst, XMMRegister nds,
Address src, VexSimdPrefix pre, bool vector256);
Address src, VexSimdPrefix pre, int vector_len,
bool no_mask_reg = false, bool legacy_mode = false);
void emit_vex_arith_q(int opcode, XMMRegister dst, XMMRegister nds,
Address src, VexSimdPrefix pre, int vector_len,
bool no_mask_reg = false);
void emit_vex_arith(int opcode, XMMRegister dst, XMMRegister nds,
XMMRegister src, VexSimdPrefix pre, bool vector256);
XMMRegister src, VexSimdPrefix pre, int vector_len,
bool no_mask_reg = false, bool legacy_mode = false);
void emit_vex_arith_q(int opcode, XMMRegister dst, XMMRegister nds,
XMMRegister src, VexSimdPrefix pre, int vector_len,
bool no_mask_reg = false);
bool emit_compressed_disp_byte(int &disp);
void emit_operand(Register reg,
Register base, Register index, Address::ScaleFactor scale,
@ -825,7 +919,9 @@ private:
public:
// Creation
Assembler(CodeBuffer* code) : AbstractAssembler(code) {}
Assembler(CodeBuffer* code) : AbstractAssembler(code) {
init_attributes();
}
// Decoding
static address locate_operand(address inst, WhichOperand which);
@ -833,11 +929,21 @@ private:
// Utilities
static bool is_polling_page_far() NOT_LP64({ return false;});
static bool query_compressed_disp_byte(int disp, bool is_evex_inst, int vector_len,
int cur_tuple_type, int in_size_in_bits, int cur_encoding);
// Generic instructions
// Does 32bit or 64bit as needed for the platform. In some sense these
// belong in macro assembler but there is no need for both varieties to exist
void init_attributes(void) {
evex_encoding = 0;
input_size_in_bits = 0;
avx_vector_len = AVX_NoVec;
tuple_type = EVEX_ETUP;
is_evex_instruction = false;
}
void lea(Register dst, Address src);
void mov(Register dst, Register src);
@ -1338,6 +1444,12 @@ private:
void movb(Address dst, int imm8);
void movb(Register dst, Address src);
void kmovq(KRegister dst, KRegister src);
void kmovql(KRegister dst, Register src);
void kmovdl(KRegister dst, Register src);
void kmovq(Address dst, KRegister src);
void kmovq(KRegister dst, Address src);
void movdl(XMMRegister dst, Register src);
void movdl(Register dst, XMMRegister src);
void movdl(XMMRegister dst, Address src);
@ -1361,6 +1473,11 @@ private:
void vmovdqu(XMMRegister dst, Address src);
void vmovdqu(XMMRegister dst, XMMRegister src);
// Move Unaligned 512bit Vector
void evmovdqu(Address dst, XMMRegister src, int vector_len);
void evmovdqu(XMMRegister dst, Address src, int vector_len);
void evmovdqu(XMMRegister dst, XMMRegister src, int vector_len);
// Move lower 64bit to high 64bit in 128bit register
void movlhps(XMMRegister dst, XMMRegister src);
@ -1486,10 +1603,10 @@ private:
// Pack with unsigned saturation
void packuswb(XMMRegister dst, XMMRegister src);
void packuswb(XMMRegister dst, Address src);
void vpackuswb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpackuswb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
// Pemutation of 64bit words
void vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256);
void vpermq(XMMRegister dst, XMMRegister src, int imm8, int vector_len);
void pause();
@ -1734,54 +1851,54 @@ private:
// Add Packed Floating-Point Values
void addpd(XMMRegister dst, XMMRegister src);
void addps(XMMRegister dst, XMMRegister src);
void vaddpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vaddps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vaddpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vaddps(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vaddpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vaddps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vaddpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vaddps(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Subtract Packed Floating-Point Values
void subpd(XMMRegister dst, XMMRegister src);
void subps(XMMRegister dst, XMMRegister src);
void vsubpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vsubps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vsubpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vsubps(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vsubpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vsubps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vsubpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vsubps(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Multiply Packed Floating-Point Values
void mulpd(XMMRegister dst, XMMRegister src);
void mulps(XMMRegister dst, XMMRegister src);
void vmulpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vmulps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vmulpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vmulps(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vmulpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vmulps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vmulpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vmulps(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Divide Packed Floating-Point Values
void divpd(XMMRegister dst, XMMRegister src);
void divps(XMMRegister dst, XMMRegister src);
void vdivpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vdivps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vdivpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vdivps(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vdivpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vdivps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vdivpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vdivps(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Bitwise Logical AND of Packed Floating-Point Values
void andpd(XMMRegister dst, XMMRegister src);
void andps(XMMRegister dst, XMMRegister src);
void vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vandpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vandps(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vandpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vandps(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Bitwise Logical XOR of Packed Floating-Point Values
void xorpd(XMMRegister dst, XMMRegister src);
void xorps(XMMRegister dst, XMMRegister src);
void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vxorpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vxorps(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vxorpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vxorps(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Add horizontal packed integers
void vphaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vphaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vphaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vphaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void phaddw(XMMRegister dst, XMMRegister src);
void phaddd(XMMRegister dst, XMMRegister src);
@ -1790,36 +1907,38 @@ private:
void paddw(XMMRegister dst, XMMRegister src);
void paddd(XMMRegister dst, XMMRegister src);
void paddq(XMMRegister dst, XMMRegister src);
void vpaddb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpaddq(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpaddb(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpaddw(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpaddd(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpaddq(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpaddb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpaddd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpaddq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpaddb(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vpaddw(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vpaddd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vpaddq(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Sub packed integers
void psubb(XMMRegister dst, XMMRegister src);
void psubw(XMMRegister dst, XMMRegister src);
void psubd(XMMRegister dst, XMMRegister src);
void psubq(XMMRegister dst, XMMRegister src);
void vpsubb(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpsubw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpsubd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpsubq(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpsubb(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpsubw(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpsubd(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpsubq(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpsubb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpsubw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpsubd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpsubq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpsubb(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vpsubw(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vpsubd(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vpsubq(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Multiply packed integers (only shorts and ints)
void pmullw(XMMRegister dst, XMMRegister src);
void pmulld(XMMRegister dst, XMMRegister src);
void vpmullw(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpmulld(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpmullw(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpmulld(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpmullw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpmulld(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpmullq(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpmullw(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vpmulld(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
void vpmullq(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Shift left packed integers
void psllw(XMMRegister dst, int shift);
@ -1828,12 +1947,12 @@ private:
void psllw(XMMRegister dst, XMMRegister shift);
void pslld(XMMRegister dst, XMMRegister shift);
void psllq(XMMRegister dst, XMMRegister shift);
void vpsllw(XMMRegister dst, XMMRegister src, int shift, bool vector256);
void vpslld(XMMRegister dst, XMMRegister src, int shift, bool vector256);
void vpsllq(XMMRegister dst, XMMRegister src, int shift, bool vector256);
void vpsllw(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256);
void vpslld(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256);
void vpsllq(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256);
void vpsllw(XMMRegister dst, XMMRegister src, int shift, int vector_len);
void vpslld(XMMRegister dst, XMMRegister src, int shift, int vector_len);
void vpsllq(XMMRegister dst, XMMRegister src, int shift, int vector_len);
void vpsllw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
void vpslld(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
void vpsllq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
// Logical shift right packed integers
void psrlw(XMMRegister dst, int shift);
@ -1842,42 +1961,43 @@ private:
void psrlw(XMMRegister dst, XMMRegister shift);
void psrld(XMMRegister dst, XMMRegister shift);
void psrlq(XMMRegister dst, XMMRegister shift);
void vpsrlw(XMMRegister dst, XMMRegister src, int shift, bool vector256);
void vpsrld(XMMRegister dst, XMMRegister src, int shift, bool vector256);
void vpsrlq(XMMRegister dst, XMMRegister src, int shift, bool vector256);
void vpsrlw(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256);
void vpsrld(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256);
void vpsrlq(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256);
void vpsrlw(XMMRegister dst, XMMRegister src, int shift, int vector_len);
void vpsrld(XMMRegister dst, XMMRegister src, int shift, int vector_len);
void vpsrlq(XMMRegister dst, XMMRegister src, int shift, int vector_len);
void vpsrlw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
void vpsrld(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
void vpsrlq(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
// Arithmetic shift right packed integers (only shorts and ints, no instructions for longs)
void psraw(XMMRegister dst, int shift);
void psrad(XMMRegister dst, int shift);
void psraw(XMMRegister dst, XMMRegister shift);
void psrad(XMMRegister dst, XMMRegister shift);
void vpsraw(XMMRegister dst, XMMRegister src, int shift, bool vector256);
void vpsrad(XMMRegister dst, XMMRegister src, int shift, bool vector256);
void vpsraw(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256);
void vpsrad(XMMRegister dst, XMMRegister src, XMMRegister shift, bool vector256);
void vpsraw(XMMRegister dst, XMMRegister src, int shift, int vector_len);
void vpsrad(XMMRegister dst, XMMRegister src, int shift, int vector_len);
void vpsraw(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
void vpsrad(XMMRegister dst, XMMRegister src, XMMRegister shift, int vector_len);
// And packed integers
void pand(XMMRegister dst, XMMRegister src);
void vpand(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpand(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpand(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpand(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Or packed integers
void por(XMMRegister dst, XMMRegister src);
void vpor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpor(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpor(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Xor packed integers
void pxor(XMMRegister dst, XMMRegister src);
void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256);
void vpxor(XMMRegister dst, XMMRegister nds, Address src, bool vector256);
void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpxor(XMMRegister dst, XMMRegister nds, Address src, int vector_len);
// Copy low 128bit into high 128bit of YMM registers.
void vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src);
void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src);
void vextractf128h(XMMRegister dst, XMMRegister src);
void vextracti128h(XMMRegister dst, XMMRegister src);
// Load/store high 128bit of YMM registers which does not destroy other half.
void vinsertf128h(XMMRegister dst, Address src);
@ -1885,9 +2005,25 @@ private:
void vextractf128h(Address dst, XMMRegister src);
void vextracti128h(Address dst, XMMRegister src);
// Copy low 256bit into high 256bit of ZMM registers.
void vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src);
void vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src);
void vextracti64x4h(XMMRegister dst, XMMRegister src);
void vextractf64x4h(XMMRegister dst, XMMRegister src);
void vextractf64x4h(Address dst, XMMRegister src);
void vinsertf64x4h(XMMRegister dst, Address src);
// Copy targeted 128bit segments of the ZMM registers
void vextracti64x2h(XMMRegister dst, XMMRegister src, int value);
void vextractf64x2h(XMMRegister dst, XMMRegister src, int value);
void vextractf32x4h(XMMRegister dst, XMMRegister src, int value);
// duplicate 4-bytes integer data from src into 8 locations in dest
void vpbroadcastd(XMMRegister dst, XMMRegister src);
// duplicate 4-bytes integer data from src into vector_len locations in dest
void evpbroadcastd(XMMRegister dst, XMMRegister src, int vector_len);
// Carry-Less Multiplication Quadword
void pclmulqdq(XMMRegister dst, XMMRegister src, int mask);
void vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask);

View File

@ -233,13 +233,30 @@ void FrameMap::initialize() {
_xmm_regs[13] = xmm13;
_xmm_regs[14] = xmm14;
_xmm_regs[15] = xmm15;
_xmm_regs[16] = xmm16;
_xmm_regs[17] = xmm17;
_xmm_regs[18] = xmm18;
_xmm_regs[19] = xmm19;
_xmm_regs[20] = xmm20;
_xmm_regs[21] = xmm21;
_xmm_regs[22] = xmm22;
_xmm_regs[23] = xmm23;
_xmm_regs[24] = xmm24;
_xmm_regs[25] = xmm25;
_xmm_regs[26] = xmm26;
_xmm_regs[27] = xmm27;
_xmm_regs[28] = xmm28;
_xmm_regs[29] = xmm29;
_xmm_regs[30] = xmm30;
_xmm_regs[31] = xmm31;
#endif // _LP64
for (int i = 0; i < 8; i++) {
_caller_save_fpu_regs[i] = LIR_OprFact::single_fpu(i);
}
for (int i = 0; i < nof_caller_save_xmm_regs ; i++) {
int num_caller_save_xmm_regs = get_num_caller_save_xmms();
for (int i = 0; i < num_caller_save_xmm_regs; i++) {
_caller_save_xmm_regs[i] = LIR_OprFact::single_xmm(i);
}

View File

@ -152,6 +152,16 @@
return range;
}
static int get_num_caller_save_xmms(void) {
int num_caller_save_xmm_regs = nof_caller_save_xmm_regs;
#ifdef _LP64
if (UseAVX < 3) {
num_caller_save_xmm_regs = num_caller_save_xmm_regs / 2;
}
#endif
return num_caller_save_xmm_regs;
}
static int nof_caller_save_cpu_regs() { return adjust_reg_range(pd_nof_caller_save_cpu_regs_frame_map); }
static int last_cpu_reg() { return adjust_reg_range(pd_last_cpu_reg); }
static int last_byte_reg() { return adjust_reg_range(pd_last_byte_reg); }

View File

@ -85,8 +85,9 @@ inline void LinearScan::pd_add_temps(LIR_Op* op) {
tty->print_cr("killing XMMs for trig");
}
#endif
int num_caller_save_xmm_regs = FrameMap::get_num_caller_save_xmms();
int op_id = op->id();
for (int xmm = 0; xmm < FrameMap::nof_caller_save_xmm_regs; xmm++) {
for (int xmm = 0; xmm < num_caller_save_xmm_regs; xmm++) {
LIR_Opr opr = FrameMap::caller_save_xmm_reg_at(xmm);
add_temp(reg_num(opr), op_id, noUse, T_ILLEGAL);
}
@ -100,6 +101,10 @@ inline void LinearScan::pd_add_temps(LIR_Op* op) {
// Implementation of LinearScanWalker
inline bool LinearScanWalker::pd_init_regs_for_alloc(Interval* cur) {
int last_xmm_reg = pd_last_xmm_reg;
if (UseAVX < 3) {
last_xmm_reg = pd_first_xmm_reg + (pd_nof_xmm_regs_frame_map / 2) - 1;
}
if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::byte_reg)) {
assert(cur->type() != T_FLOAT && cur->type() != T_DOUBLE, "cpu regs only");
_first_reg = pd_first_byte_reg;
@ -107,7 +112,7 @@ inline bool LinearScanWalker::pd_init_regs_for_alloc(Interval* cur) {
return true;
} else if ((UseSSE >= 1 && cur->type() == T_FLOAT) || (UseSSE >= 2 && cur->type() == T_DOUBLE)) {
_first_reg = pd_first_xmm_reg;
_last_reg = pd_last_xmm_reg;
_last_reg = last_xmm_reg;
return true;
}

View File

@ -323,7 +323,7 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,
LP64_ONLY(num_rt_args = 0);
LP64_ONLY(assert((reg_save_frame_size * VMRegImpl::stack_slot_size) % 16 == 0, "must be 16 byte aligned");)
int frame_size_in_slots = reg_save_frame_size + num_rt_args; // args + thread
sasm->set_frame_size(frame_size_in_slots / VMRegImpl::slots_per_word );
sasm->set_frame_size(frame_size_in_slots / VMRegImpl::slots_per_word);
// record saved value locations in an OopMap
// locations are offsets from sp after runtime call; num_rt_args is number of arguments in call, including thread
@ -362,6 +362,13 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,
map->set_callee_saved(VMRegImpl::stack2reg(r15H_off + num_rt_args), r15->as_VMReg()->next());
#endif // _LP64
int xmm_bypass_limit = FrameMap::nof_xmm_regs;
#ifdef _LP64
if (UseAVX < 3) {
xmm_bypass_limit = xmm_bypass_limit / 2;
}
#endif
if (save_fpu_registers) {
if (UseSSE < 2) {
int fpu_off = float_regs_as_doubles_off;
@ -380,11 +387,13 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,
if (UseSSE >= 2) {
int xmm_off = xmm_regs_as_doubles_off;
for (int n = 0; n < FrameMap::nof_xmm_regs; n++) {
VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
// %%% This is really a waste but we'll keep things as they were for now
if (true) {
map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + 1 + num_rt_args), xmm_name_0->next());
if (n < xmm_bypass_limit) {
VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
// %%% This is really a waste but we'll keep things as they were for now
if (true) {
map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + 1 + num_rt_args), xmm_name_0->next());
}
}
xmm_off += 2;
}
@ -393,8 +402,10 @@ static OopMap* generate_oop_map(StubAssembler* sasm, int num_rt_args,
} else if (UseSSE == 1) {
int xmm_off = xmm_regs_as_doubles_off;
for (int n = 0; n < FrameMap::nof_xmm_regs; n++) {
VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
if (n < xmm_bypass_limit) {
VMReg xmm_name_0 = as_XMMRegister(n)->as_VMReg();
map->set_callee_saved(VMRegImpl::stack2reg(xmm_off + num_rt_args), xmm_name_0);
}
xmm_off += 2;
}
assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers");
@ -474,6 +485,24 @@ static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args,
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104), xmm13);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112), xmm14);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120), xmm15);
if (UseAVX > 2) {
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 128), xmm16);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 136), xmm17);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 144), xmm18);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 152), xmm19);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 160), xmm20);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 168), xmm21);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 176), xmm22);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 184), xmm23);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 192), xmm24);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 200), xmm25);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 208), xmm26);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 216), xmm27);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 224), xmm28);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 232), xmm29);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 240), xmm30);
__ movdbl(Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 248), xmm31);
}
#endif // _LP64
} else if (UseSSE == 1) {
// save XMM registers as float because double not supported without SSE2
@ -516,6 +545,24 @@ static void restore_fpu(StubAssembler* sasm, bool restore_fpu_registers = true)
__ movdbl(xmm13, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 104));
__ movdbl(xmm14, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 112));
__ movdbl(xmm15, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 120));
if (UseAVX > 2) {
__ movdbl(xmm16, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 128));
__ movdbl(xmm17, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 136));
__ movdbl(xmm18, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 144));
__ movdbl(xmm19, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 152));
__ movdbl(xmm20, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 160));
__ movdbl(xmm21, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 168));
__ movdbl(xmm22, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 176));
__ movdbl(xmm23, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 184));
__ movdbl(xmm24, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 192));
__ movdbl(xmm25, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 200));
__ movdbl(xmm26, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 208));
__ movdbl(xmm27, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 216));
__ movdbl(xmm28, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 224));
__ movdbl(xmm29, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 232));
__ movdbl(xmm30, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 240));
__ movdbl(xmm31, Address(rsp, xmm_regs_as_doubles_off * VMRegImpl::stack_slot_size + 248));
}
#endif // _LP64
} else if (UseSSE == 1) {
// restore XMM registers
@ -1631,36 +1678,22 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
NOT_LP64(__ get_thread(thread);)
Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
PtrQueue::byte_offset_of_active()));
Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
PtrQueue::byte_offset_of_index()));
Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
PtrQueue::byte_offset_of_buf()));
Label done;
Label runtime;
// Can we store original value in the thread's buffer?
#ifdef _LP64
__ movslq(tmp, queue_index);
__ cmpq(tmp, 0);
#else
__ cmpl(queue_index, 0);
#endif
__ jcc(Assembler::equal, runtime);
#ifdef _LP64
__ subq(tmp, wordSize);
__ movl(queue_index, tmp);
__ addq(tmp, buffer);
#else
__ subl(queue_index, wordSize);
__ movl(tmp, buffer);
__ addl(tmp, queue_index);
#endif
__ movptr(tmp, queue_index);
__ testptr(tmp, tmp);
__ jcc(Assembler::zero, runtime);
__ subptr(tmp, wordSize);
__ movptr(queue_index, tmp);
__ addptr(tmp, buffer);
// prev_val (rax)
f.load_argument(0, pre_val);
@ -1713,6 +1746,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
Label done;
Label enqueued;
Label runtime;
// At this point we know new_value is non-NULL and the new_value crosses regions.
@ -1752,28 +1786,19 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ movb(Address(card_addr, 0), (int)CardTableModRefBS::dirty_card_val());
__ cmpl(queue_index, 0);
__ jcc(Assembler::equal, runtime);
__ subl(queue_index, wordSize);
const Register tmp = rdx;
__ push(rdx);
const Register buffer_addr = rbx;
__ push(rbx);
__ movptr(buffer_addr, buffer);
#ifdef _LP64
__ movslq(rscratch1, queue_index);
__ addptr(buffer_addr, rscratch1);
#else
__ addptr(buffer_addr, queue_index);
#endif
__ movptr(Address(buffer_addr, 0), card_addr);
__ pop(rbx);
__ jmp(done);
__ movptr(tmp, queue_index);
__ testptr(tmp, tmp);
__ jcc(Assembler::zero, runtime);
__ subptr(tmp, wordSize);
__ movptr(queue_index, tmp);
__ addptr(tmp, buffer);
__ movptr(Address(tmp, 0), card_addr);
__ jmp(enqueued);
__ bind(runtime);
__ push(rdx);
#ifdef _LP64
__ push(r8);
__ push(r9);
@ -1795,12 +1820,12 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) {
__ pop(r9);
__ pop(r8);
#endif
__ bind(enqueued);
__ pop(rdx);
__ bind(done);
__ bind(done);
__ pop(rcx);
__ pop(rax);
}
break;
#endif // INCLUDE_ALL_GCS

View File

@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "opto/compile.hpp"
#include "opto/node.hpp"
#include "opto/optoreg.hpp"
// processor dependent initialization for i486
@ -37,4 +38,24 @@ void Compile::pd_compiler2_init() {
ConditionalMoveLimit = 0;
}
#endif // AMD64
if (UseAVX < 3) {
int delta = XMMRegisterImpl::max_slots_per_register * XMMRegisterImpl::number_of_registers;
int bottom = ConcreteRegisterImpl::max_fpr;
int top = bottom + delta;
int middle = bottom + (delta / 2);
int xmm_slots = XMMRegisterImpl::max_slots_per_register;
int lower = xmm_slots / 2;
// mark bad every register that we cannot get to if AVX less than 3, we have all slots in the array
// Note: vm2opto is allocated to ConcreteRegisterImpl::number_of_registers
for (int i = bottom; i < middle; i += xmm_slots) {
for (OptoReg::Name j = OptoReg::Name(i + lower); j<OptoReg::Name(i + xmm_slots); j = OptoReg::add(j, 1)) {
OptoReg::invalidate(j);
}
}
// mark the upper zmm bank bad and all the mask registers bad in this case
for (OptoReg::Name i = OptoReg::Name(middle); i<OptoReg::Name(_last_Mach_Reg - 1); i = OptoReg::add(i, 1)) {
OptoReg::invalidate(i);
}
}
}

View File

@ -125,7 +125,7 @@
// Entry frames
#ifdef AMD64
#ifdef _WIN64
entry_frame_after_call_words = 28,
entry_frame_after_call_words = 60,
entry_frame_call_wrapper_offset = 2,
arg_reg_save_area_bytes = 32 // Register argument save area

View File

@ -3996,21 +3996,21 @@ void MacroAssembler::vaddss(XMMRegister dst, XMMRegister nds, AddressLiteral src
}
}
void MacroAssembler::vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) {
void MacroAssembler::vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) {
if (reachable(src)) {
vandpd(dst, nds, as_Address(src), vector256);
vandpd(dst, nds, as_Address(src), vector_len);
} else {
lea(rscratch1, src);
vandpd(dst, nds, Address(rscratch1, 0), vector256);
vandpd(dst, nds, Address(rscratch1, 0), vector_len);
}
}
void MacroAssembler::vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) {
void MacroAssembler::vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) {
if (reachable(src)) {
vandps(dst, nds, as_Address(src), vector256);
vandps(dst, nds, as_Address(src), vector_len);
} else {
lea(rscratch1, src);
vandps(dst, nds, Address(rscratch1, 0), vector256);
vandps(dst, nds, Address(rscratch1, 0), vector_len);
}
}
@ -4068,21 +4068,21 @@ void MacroAssembler::vsubss(XMMRegister dst, XMMRegister nds, AddressLiteral src
}
}
void MacroAssembler::vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) {
void MacroAssembler::vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) {
if (reachable(src)) {
vxorpd(dst, nds, as_Address(src), vector256);
vxorpd(dst, nds, as_Address(src), vector_len);
} else {
lea(rscratch1, src);
vxorpd(dst, nds, Address(rscratch1, 0), vector256);
vxorpd(dst, nds, Address(rscratch1, 0), vector_len);
}
}
void MacroAssembler::vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256) {
void MacroAssembler::vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len) {
if (reachable(src)) {
vxorps(dst, nds, as_Address(src), vector256);
vxorps(dst, nds, as_Address(src), vector_len);
} else {
lea(rscratch1, src);
vxorps(dst, nds, Address(rscratch1, 0), vector256);
vxorps(dst, nds, Address(rscratch1, 0), vector_len);
}
}
@ -4561,6 +4561,14 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int
movflt(Address(rsp,off++*sizeof(jdouble)),xmm6);
movflt(Address(rsp,off++*sizeof(jdouble)),xmm7);
} else if (UseSSE >= 2) {
if (UseAVX > 2) {
movl(rbx, 0xffff);
#ifdef _LP64
kmovql(k1, rbx);
#else
kmovdl(k1, rbx);
#endif
}
#ifdef COMPILER2
if (MaxVectorSize > 16) {
assert(UseAVX > 0, "256bit vectors are supported only with AVX");
@ -7063,8 +7071,39 @@ void MacroAssembler::generate_fill(BasicType t, bool aligned,
{
assert( UseSSE >= 2, "supported cpu only" );
Label L_fill_32_bytes_loop, L_check_fill_8_bytes, L_fill_8_bytes_loop, L_fill_8_bytes;
if (UseAVX > 2) {
movl(rtmp, 0xffff);
#ifdef _LP64
kmovql(k1, rtmp);
#else
kmovdl(k1, rtmp);
#endif
}
movdl(xtmp, value);
if (UseAVX >= 2 && UseUnalignedLoadStores) {
if (UseAVX > 2 && UseUnalignedLoadStores) {
// Fill 64-byte chunks
Label L_fill_64_bytes_loop, L_check_fill_32_bytes;
evpbroadcastd(xtmp, xtmp, Assembler::AVX_512bit);
subl(count, 16 << shift);
jcc(Assembler::less, L_check_fill_32_bytes);
align(16);
BIND(L_fill_64_bytes_loop);
evmovdqu(Address(to, 0), xtmp, Assembler::AVX_512bit);
addptr(to, 64);
subl(count, 16 << shift);
jcc(Assembler::greaterEqual, L_fill_64_bytes_loop);
BIND(L_check_fill_32_bytes);
addl(count, 8 << shift);
jccb(Assembler::less, L_check_fill_8_bytes);
evmovdqu(Address(to, 0), xtmp, Assembler::AVX_256bit);
addptr(to, 32);
subl(count, 8 << shift);
BIND(L_check_fill_8_bytes);
} else if (UseAVX == 2 && UseUnalignedLoadStores) {
// Fill 64-byte chunks
Label L_fill_64_bytes_loop, L_check_fill_32_bytes;
vpbroadcastd(xtmp, xtmp);
@ -7200,11 +7239,11 @@ void MacroAssembler::encode_iso_array(Register src, Register dst, Register len,
bind(L_copy_32_chars);
vmovdqu(tmp3Reg, Address(src, len, Address::times_2, -64));
vmovdqu(tmp4Reg, Address(src, len, Address::times_2, -32));
vpor(tmp2Reg, tmp3Reg, tmp4Reg, /* vector256 */ true);
vpor(tmp2Reg, tmp3Reg, tmp4Reg, /* vector_len */ 1);
vptest(tmp2Reg, tmp1Reg); // check for Unicode chars in vector
jccb(Assembler::notZero, L_copy_32_chars_exit);
vpackuswb(tmp3Reg, tmp3Reg, tmp4Reg, /* vector256 */ true);
vpermq(tmp4Reg, tmp3Reg, 0xD8, /* vector256 */ true);
vpackuswb(tmp3Reg, tmp3Reg, tmp4Reg, /* vector_len */ 1);
vpermq(tmp4Reg, tmp3Reg, 0xD8, /* vector_len */ 1);
vmovdqu(Address(dst, len, Address::times_1, -32), tmp4Reg);
bind(L_chars_32_check);
@ -7227,13 +7266,13 @@ void MacroAssembler::encode_iso_array(Register src, Register dst, Register len,
vmovdqu(tmp2Reg, Address(src, len, Address::times_2, -32));
vptest(tmp2Reg, tmp1Reg);
jccb(Assembler::notZero, L_copy_16_chars_exit);
vpackuswb(tmp2Reg, tmp2Reg, tmp1Reg, /* vector256 */ true);
vpermq(tmp3Reg, tmp2Reg, 0xD8, /* vector256 */ true);
vpackuswb(tmp2Reg, tmp2Reg, tmp1Reg, /* vector_len */ 1);
vpermq(tmp3Reg, tmp2Reg, 0xD8, /* vector_len */ 1);
} else {
if (UseAVX > 0) {
movdqu(tmp3Reg, Address(src, len, Address::times_2, -32));
movdqu(tmp4Reg, Address(src, len, Address::times_2, -16));
vpor(tmp2Reg, tmp3Reg, tmp4Reg, /* vector256 */ false);
vpor(tmp2Reg, tmp3Reg, tmp4Reg, /* vector_len */ 0);
} else {
movdqu(tmp3Reg, Address(src, len, Address::times_2, -32));
por(tmp2Reg, tmp3Reg);
@ -7776,7 +7815,7 @@ void MacroAssembler::fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegi
if (UseAVX > 0) {
vpclmulhdq(xtmp, xK, xcrc); // [123:64]
vpclmulldq(xcrc, xK, xcrc); // [63:0]
vpxor(xcrc, xcrc, Address(buf, offset), false /* vector256 */);
vpxor(xcrc, xcrc, Address(buf, offset), 0 /* vector_len */);
pxor(xcrc, xtmp);
} else {
movdqa(xtmp, xcrc);
@ -7920,7 +7959,7 @@ void MacroAssembler::kernel_crc32(Register crc, Register buf, Register len, Regi
movdqu(xmm0, ExternalAddress(StubRoutines::x86::crc_by128_masks_addr()));
if (UseAVX > 0) {
vpclmulqdq(xmm2, xmm0, xmm1, 0x1);
vpand(xmm3, xmm0, xmm2, false /* vector256 */);
vpand(xmm3, xmm0, xmm2, 0 /* vector_len */);
vpclmulqdq(xmm0, xmm0, xmm3, 0x1);
} else {
movdqa(xmm2, xmm0);

View File

@ -1024,13 +1024,13 @@ public:
void vaddss(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vaddss(dst, nds, src); }
void vaddss(XMMRegister dst, XMMRegister nds, AddressLiteral src);
void vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vandpd(dst, nds, src, vector256); }
void vandpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vandpd(dst, nds, src, vector256); }
void vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256);
void vandpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vandpd(dst, nds, src, vector_len); }
void vandpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { Assembler::vandpd(dst, nds, src, vector_len); }
void vandpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len);
void vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vandps(dst, nds, src, vector256); }
void vandps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vandps(dst, nds, src, vector256); }
void vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256);
void vandps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vandps(dst, nds, src, vector_len); }
void vandps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { Assembler::vandps(dst, nds, src, vector_len); }
void vandps(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len);
void vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src) { Assembler::vdivsd(dst, nds, src); }
void vdivsd(XMMRegister dst, XMMRegister nds, Address src) { Assembler::vdivsd(dst, nds, src); }
@ -1058,25 +1058,25 @@ public:
// AVX Vector instructions
void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vxorpd(dst, nds, src, vector256); }
void vxorpd(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vxorpd(dst, nds, src, vector256); }
void vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256);
void vxorpd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vxorpd(dst, nds, src, vector_len); }
void vxorpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { Assembler::vxorpd(dst, nds, src, vector_len); }
void vxorpd(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len);
void vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) { Assembler::vxorps(dst, nds, src, vector256); }
void vxorps(XMMRegister dst, XMMRegister nds, Address src, bool vector256) { Assembler::vxorps(dst, nds, src, vector256); }
void vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, bool vector256);
void vxorps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { Assembler::vxorps(dst, nds, src, vector_len); }
void vxorps(XMMRegister dst, XMMRegister nds, Address src, int vector_len) { Assembler::vxorps(dst, nds, src, vector_len); }
void vxorps(XMMRegister dst, XMMRegister nds, AddressLiteral src, int vector_len);
void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, bool vector256) {
if (UseAVX > 1 || !vector256) // vpxor 256 bit is available only in AVX2
Assembler::vpxor(dst, nds, src, vector256);
void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
if (UseAVX > 1 || (vector_len < 1)) // vpxor 256 bit is available only in AVX2
Assembler::vpxor(dst, nds, src, vector_len);
else
Assembler::vxorpd(dst, nds, src, vector256);
Assembler::vxorpd(dst, nds, src, vector_len);
}
void vpxor(XMMRegister dst, XMMRegister nds, Address src, bool vector256) {
if (UseAVX > 1 || !vector256) // vpxor 256 bit is available only in AVX2
Assembler::vpxor(dst, nds, src, vector256);
void vpxor(XMMRegister dst, XMMRegister nds, Address src, int vector_len) {
if (UseAVX > 1 || (vector_len < 1)) // vpxor 256 bit is available only in AVX2
Assembler::vpxor(dst, nds, src, vector_len);
else
Assembler::vxorpd(dst, nds, src, vector256);
Assembler::vxorpd(dst, nds, src, vector_len);
}
// Simple version for AVX2 256bit vectors

View File

@ -68,6 +68,22 @@ REGISTER_DEFINITION(XMMRegister, xmm12);
REGISTER_DEFINITION(XMMRegister, xmm13);
REGISTER_DEFINITION(XMMRegister, xmm14);
REGISTER_DEFINITION(XMMRegister, xmm15);
REGISTER_DEFINITION(XMMRegister, xmm16);
REGISTER_DEFINITION(XMMRegister, xmm17);
REGISTER_DEFINITION(XMMRegister, xmm18);
REGISTER_DEFINITION(XMMRegister, xmm19);
REGISTER_DEFINITION(XMMRegister, xmm20);
REGISTER_DEFINITION(XMMRegister, xmm21);
REGISTER_DEFINITION(XMMRegister, xmm22);
REGISTER_DEFINITION(XMMRegister, xmm23);
REGISTER_DEFINITION(XMMRegister, xmm24);
REGISTER_DEFINITION(XMMRegister, xmm25);
REGISTER_DEFINITION(XMMRegister, xmm26);
REGISTER_DEFINITION(XMMRegister, xmm27);
REGISTER_DEFINITION(XMMRegister, xmm28);
REGISTER_DEFINITION(XMMRegister, xmm29);
REGISTER_DEFINITION(XMMRegister, xmm30);
REGISTER_DEFINITION(XMMRegister, xmm31);
REGISTER_DEFINITION(Register, c_rarg0);
REGISTER_DEFINITION(Register, c_rarg1);
@ -123,5 +139,15 @@ REGISTER_DEFINITION(MMXRegister, mmx5 );
REGISTER_DEFINITION(MMXRegister, mmx6 );
REGISTER_DEFINITION(MMXRegister, mmx7 );
REGISTER_DEFINITION(KRegister, knoreg);
REGISTER_DEFINITION(KRegister, k0);
REGISTER_DEFINITION(KRegister, k1);
REGISTER_DEFINITION(KRegister, k2);
REGISTER_DEFINITION(KRegister, k3);
REGISTER_DEFINITION(KRegister, k4);
REGISTER_DEFINITION(KRegister, k5);
REGISTER_DEFINITION(KRegister, k6);
REGISTER_DEFINITION(KRegister, k7);
// JSR 292
REGISTER_DEFINITION(Register, rbp_mh_SP_save);

View File

@ -31,11 +31,13 @@ const int ConcreteRegisterImpl::max_gpr = RegisterImpl::number_of_registers;
const int ConcreteRegisterImpl::max_gpr = RegisterImpl::number_of_registers << 1;
#endif // AMD64
const int ConcreteRegisterImpl::max_fpr = ConcreteRegisterImpl::max_gpr +
2 * FloatRegisterImpl::number_of_registers;
2 * FloatRegisterImpl::number_of_registers;
const int ConcreteRegisterImpl::max_xmm = ConcreteRegisterImpl::max_fpr +
8 * XMMRegisterImpl::number_of_registers;
XMMRegisterImpl::max_slots_per_register * XMMRegisterImpl::number_of_registers;
const int ConcreteRegisterImpl::max_kpr = ConcreteRegisterImpl::max_xmm +
KRegisterImpl::max_slots_per_register * KRegisterImpl::number_of_registers;
const char* RegisterImpl::name() const {
const char* names[number_of_registers] = {
#ifndef AMD64
@ -59,8 +61,17 @@ const char* XMMRegisterImpl::name() const {
const char* names[number_of_registers] = {
"xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7"
#ifdef AMD64
,"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
,"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
,"xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23"
,"xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
#endif // AMD64
};
return is_valid() ? names[encoding()] : "xnoreg";
}
const char* KRegisterImpl::name() const {
const char* names[number_of_registers] = {
"k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7"
};
return is_valid() ? names[encoding()] : "knoreg";
}

View File

@ -45,10 +45,12 @@ class RegisterImpl: public AbstractRegisterImpl {
enum {
#ifndef AMD64
number_of_registers = 8,
number_of_byte_registers = 4
number_of_byte_registers = 4,
max_slots_per_register = 1
#else
number_of_registers = 16,
number_of_byte_registers = 16
number_of_byte_registers = 16,
max_slots_per_register = 1
#endif // AMD64
};
@ -143,9 +145,11 @@ class XMMRegisterImpl: public AbstractRegisterImpl {
public:
enum {
#ifndef AMD64
number_of_registers = 8
number_of_registers = 8,
max_slots_per_register = 16 // 512-bit
#else
number_of_registers = 16
number_of_registers = 32,
max_slots_per_register = 16 // 512-bit
#endif // AMD64
};
@ -183,6 +187,22 @@ CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm12, (12));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm13, (13));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm14, (14));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm15, (15));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm16, (16));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm17, (17));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm18, (18));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm19, (19));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm20, (20));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm21, (21));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm22, (22));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm23, (23));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm24, (24));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm25, (25));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm26, (26));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm27, (27));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm28, (28));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm29, (29));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm30, (30));
CONSTANT_REGISTER_DECLARATION(XMMRegister, xmm31, (31));
#endif // AMD64
// Only used by the 32bit stubGenerator. These can't be described by vmreg and hence
@ -200,6 +220,46 @@ CONSTANT_REGISTER_DECLARATION(MMXRegister, mmx5 , ( 5));
CONSTANT_REGISTER_DECLARATION(MMXRegister, mmx6 , ( 6));
CONSTANT_REGISTER_DECLARATION(MMXRegister, mmx7 , ( 7));
// Use XMMRegister as shortcut
class KRegisterImpl;
typedef KRegisterImpl* KRegister;
inline KRegister as_KRegister(int encoding) {
return (KRegister)(intptr_t)encoding;
}
// The implementation of XMM registers for the IA32 architecture
class KRegisterImpl : public AbstractRegisterImpl {
public:
enum {
number_of_registers = 8,
max_slots_per_register = 1
};
// construction
friend KRegister as_KRegister(int encoding);
inline VMReg as_VMReg();
// derived registers, offsets, and addresses
KRegister successor() const { return as_KRegister(encoding() + 1); }
// accessors
int encoding() const { assert(is_valid(), err_msg("invalid register (%d)", (int)(intptr_t)this)); return (intptr_t)this; }
bool is_valid() const { return 0 <= (intptr_t)this && (intptr_t)this < number_of_registers; }
const char* name() const;
};
// The Mask registers, for AVX3 enabled and up chips
CONSTANT_REGISTER_DECLARATION(KRegister, knoreg, (-1));
CONSTANT_REGISTER_DECLARATION(KRegister, k0, (0));
CONSTANT_REGISTER_DECLARATION(KRegister, k1, (1));
CONSTANT_REGISTER_DECLARATION(KRegister, k2, (2));
CONSTANT_REGISTER_DECLARATION(KRegister, k3, (3));
CONSTANT_REGISTER_DECLARATION(KRegister, k4, (4));
CONSTANT_REGISTER_DECLARATION(KRegister, k5, (5));
CONSTANT_REGISTER_DECLARATION(KRegister, k6, (6));
CONSTANT_REGISTER_DECLARATION(KRegister, k7, (7));
// Need to know the total number of registers of all sorts for SharedInfo.
// Define a class that exports it.
@ -211,18 +271,20 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl {
// There is no requirement that any ordering here matches any ordering c2 gives
// it's optoregs.
number_of_registers = RegisterImpl::number_of_registers +
number_of_registers = RegisterImpl::number_of_registers +
#ifdef AMD64
RegisterImpl::number_of_registers + // "H" half of a 64bit register
RegisterImpl::number_of_registers + // "H" half of a 64bit register
#endif // AMD64
2 * FloatRegisterImpl::number_of_registers +
8 * XMMRegisterImpl::number_of_registers +
1 // eflags
2 * FloatRegisterImpl::number_of_registers +
XMMRegisterImpl::max_slots_per_register * XMMRegisterImpl::number_of_registers +
KRegisterImpl::number_of_registers + // mask registers
1 // eflags
};
static const int max_gpr;
static const int max_fpr;
static const int max_xmm;
static const int max_kpr;
};

View File

@ -117,9 +117,9 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
int vect_words = 0;
#ifdef COMPILER2
if (save_vectors) {
assert(UseAVX > 0, "256bit vectors are supported only with AVX");
assert(MaxVectorSize == 32, "only 256bit vectors are supported now");
// Save upper half of YMM registes
assert(UseAVX > 0, "512bit vectors are supported only with EVEX");
assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
// Save upper half of ZMM/YMM registers :
vect_words = 8 * 16 / wordSize;
additional_frame_words += vect_words;
}
@ -216,6 +216,17 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
__ vextractf128h(Address(rsp, 80),xmm5);
__ vextractf128h(Address(rsp, 96),xmm6);
__ vextractf128h(Address(rsp,112),xmm7);
if (UseAVX > 2) {
__ subptr(rsp, 256); // Save upper half of ZMM registes
__ vextractf64x4h(Address(rsp, 0), xmm0);
__ vextractf64x4h(Address(rsp, 32), xmm1);
__ vextractf64x4h(Address(rsp, 64), xmm2);
__ vextractf64x4h(Address(rsp, 96), xmm3);
__ vextractf64x4h(Address(rsp, 128), xmm4);
__ vextractf64x4h(Address(rsp, 160), xmm5);
__ vextractf64x4h(Address(rsp, 192), xmm6);
__ vextractf64x4h(Address(rsp, 224), xmm7);
}
}
// Set an oopmap for the call site. This oopmap will map all
@ -283,8 +294,8 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve
int additional_frame_bytes = 0;
#ifdef COMPILER2
if (restore_vectors) {
assert(UseAVX > 0, "256bit vectors are supported only with AVX");
assert(MaxVectorSize == 32, "only 256bit vectors are supported now");
assert(UseAVX > 0, "512bit vectors are supported only with EVEX");
assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
additional_frame_bytes = 128;
}
#else
@ -324,6 +335,18 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve
__ vinsertf128h(xmm6, Address(rsp, 96));
__ vinsertf128h(xmm7, Address(rsp,112));
__ addptr(rsp, additional_frame_bytes);
if (UseAVX > 2) {
additional_frame_bytes = 256;
__ vinsertf64x4h(xmm0, Address(rsp, 0));
__ vinsertf64x4h(xmm1, Address(rsp, 32));
__ vinsertf64x4h(xmm2, Address(rsp, 64));
__ vinsertf64x4h(xmm3, Address(rsp, 96));
__ vinsertf64x4h(xmm4, Address(rsp, 128));
__ vinsertf64x4h(xmm5, Address(rsp, 160));
__ vinsertf64x4h(xmm6, Address(rsp, 192));
__ vinsertf64x4h(xmm7, Address(rsp, 224));
__ addptr(rsp, additional_frame_bytes);
}
}
__ pop_FPU_state();
__ addptr(rsp, FPU_regs_live*wordSize); // Pop FPU registers

View File

@ -86,7 +86,23 @@ class RegisterSaver {
DEF_XMM_OFFS(13),
DEF_XMM_OFFS(14),
DEF_XMM_OFFS(15),
fpu_state_end = fpu_state_off + ((FPUStateSizeInWords-1)*wordSize / BytesPerInt),
DEF_XMM_OFFS(16),
DEF_XMM_OFFS(17),
DEF_XMM_OFFS(18),
DEF_XMM_OFFS(19),
DEF_XMM_OFFS(20),
DEF_XMM_OFFS(21),
DEF_XMM_OFFS(22),
DEF_XMM_OFFS(23),
DEF_XMM_OFFS(24),
DEF_XMM_OFFS(25),
DEF_XMM_OFFS(26),
DEF_XMM_OFFS(27),
DEF_XMM_OFFS(28),
DEF_XMM_OFFS(29),
DEF_XMM_OFFS(30),
DEF_XMM_OFFS(31),
fpu_state_end = fpu_state_off + ((FPUStateSizeInWords - 1)*wordSize / BytesPerInt),
fpu_stateH_end,
r15_off, r15H_off,
r14_off, r14H_off,
@ -136,13 +152,21 @@ class RegisterSaver {
OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) {
int vect_words = 0;
int num_xmm_regs = 16;
if (UseAVX > 2) {
num_xmm_regs = 32;
}
#ifdef COMPILER2
if (save_vectors) {
assert(UseAVX > 0, "256bit vectors are supported only with AVX");
assert(MaxVectorSize == 32, "only 256bit vectors are supported now");
// Save upper half of YMM registes
vect_words = 16 * 16 / wordSize;
assert(UseAVX > 0, "512bit vectors are supported only with EVEX");
assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
// Save upper half of YMM registers
vect_words = 16 * num_xmm_regs / wordSize;
additional_frame_words += vect_words;
if (UseAVX > 2) {
// Save upper half of ZMM registers as well
additional_frame_words += vect_words;
}
}
#else
assert(!save_vectors, "vectors are generated only by C2");
@ -150,7 +174,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
// Always make the frame size 16-byte aligned
int frame_size_in_bytes = round_to(additional_frame_words*wordSize +
reg_save_size*BytesPerInt, 16);
reg_save_size*BytesPerInt, num_xmm_regs);
// OopMap frame size is in compiler stack slots (jint's) not bytes or words
int frame_size_in_slots = frame_size_in_bytes / BytesPerInt;
// The caller will allocate additional_frame_words
@ -169,24 +193,77 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
__ push_CPU_state(); // Push a multiple of 16 bytes
if (vect_words > 0) {
assert(vect_words*wordSize == 256, "");
__ subptr(rsp, 256); // Save upper half of YMM registes
__ vextractf128h(Address(rsp, 0),xmm0);
__ vextractf128h(Address(rsp, 16),xmm1);
__ vextractf128h(Address(rsp, 32),xmm2);
__ vextractf128h(Address(rsp, 48),xmm3);
__ vextractf128h(Address(rsp, 64),xmm4);
__ vextractf128h(Address(rsp, 80),xmm5);
__ vextractf128h(Address(rsp, 96),xmm6);
__ vextractf128h(Address(rsp,112),xmm7);
__ vextractf128h(Address(rsp,128),xmm8);
__ vextractf128h(Address(rsp,144),xmm9);
__ vextractf128h(Address(rsp,160),xmm10);
__ vextractf128h(Address(rsp,176),xmm11);
__ vextractf128h(Address(rsp,192),xmm12);
__ vextractf128h(Address(rsp,208),xmm13);
__ vextractf128h(Address(rsp,224),xmm14);
__ vextractf128h(Address(rsp,240),xmm15);
assert(vect_words*wordSize >= 256, "");
__ subptr(rsp, 256); // Save upper half of YMM registes(0..15)
__ vextractf128h(Address(rsp, 0), xmm0);
__ vextractf128h(Address(rsp, 16), xmm1);
__ vextractf128h(Address(rsp, 32), xmm2);
__ vextractf128h(Address(rsp, 48), xmm3);
__ vextractf128h(Address(rsp, 64), xmm4);
__ vextractf128h(Address(rsp, 80), xmm5);
__ vextractf128h(Address(rsp, 96), xmm6);
__ vextractf128h(Address(rsp, 112), xmm7);
__ vextractf128h(Address(rsp, 128), xmm8);
__ vextractf128h(Address(rsp, 144), xmm9);
__ vextractf128h(Address(rsp, 160), xmm10);
__ vextractf128h(Address(rsp, 176), xmm11);
__ vextractf128h(Address(rsp, 192), xmm12);
__ vextractf128h(Address(rsp, 208), xmm13);
__ vextractf128h(Address(rsp, 224), xmm14);
__ vextractf128h(Address(rsp, 240), xmm15);
if (UseAVX > 2) {
__ subptr(rsp, 256); // Save upper half of YMM registes(16..31)
__ vextractf128h(Address(rsp, 0), xmm16);
__ vextractf128h(Address(rsp, 16), xmm17);
__ vextractf128h(Address(rsp, 32), xmm18);
__ vextractf128h(Address(rsp, 48), xmm19);
__ vextractf128h(Address(rsp, 64), xmm20);
__ vextractf128h(Address(rsp, 80), xmm21);
__ vextractf128h(Address(rsp, 96), xmm22);
__ vextractf128h(Address(rsp, 112), xmm23);
__ vextractf128h(Address(rsp, 128), xmm24);
__ vextractf128h(Address(rsp, 144), xmm25);
__ vextractf128h(Address(rsp, 160), xmm26);
__ vextractf128h(Address(rsp, 176), xmm27);
__ vextractf128h(Address(rsp, 192), xmm28);
__ vextractf128h(Address(rsp, 208), xmm29);
__ vextractf128h(Address(rsp, 224), xmm30);
__ vextractf128h(Address(rsp, 240), xmm31);
// Now handle the ZMM registers (0..31)
__ subptr(rsp, 1024); // Save upper half of ZMM registes
__ vextractf64x4h(Address(rsp, 0), xmm0);
__ vextractf64x4h(Address(rsp, 32), xmm1);
__ vextractf64x4h(Address(rsp, 64), xmm2);
__ vextractf64x4h(Address(rsp, 96), xmm3);
__ vextractf64x4h(Address(rsp, 128), xmm4);
__ vextractf64x4h(Address(rsp, 160), xmm5);
__ vextractf64x4h(Address(rsp, 192), xmm6);
__ vextractf64x4h(Address(rsp, 224), xmm7);
__ vextractf64x4h(Address(rsp, 256), xmm8);
__ vextractf64x4h(Address(rsp, 288), xmm9);
__ vextractf64x4h(Address(rsp, 320), xmm10);
__ vextractf64x4h(Address(rsp, 352), xmm11);
__ vextractf64x4h(Address(rsp, 384), xmm12);
__ vextractf64x4h(Address(rsp, 416), xmm13);
__ vextractf64x4h(Address(rsp, 448), xmm14);
__ vextractf64x4h(Address(rsp, 480), xmm15);
__ vextractf64x4h(Address(rsp, 512), xmm16);
__ vextractf64x4h(Address(rsp, 544), xmm17);
__ vextractf64x4h(Address(rsp, 576), xmm18);
__ vextractf64x4h(Address(rsp, 608), xmm19);
__ vextractf64x4h(Address(rsp, 640), xmm20);
__ vextractf64x4h(Address(rsp, 672), xmm21);
__ vextractf64x4h(Address(rsp, 704), xmm22);
__ vextractf64x4h(Address(rsp, 736), xmm23);
__ vextractf64x4h(Address(rsp, 768), xmm24);
__ vextractf64x4h(Address(rsp, 800), xmm25);
__ vextractf64x4h(Address(rsp, 832), xmm26);
__ vextractf64x4h(Address(rsp, 864), xmm27);
__ vextractf64x4h(Address(rsp, 896), xmm28);
__ vextractf64x4h(Address(rsp, 928), xmm29);
__ vextractf64x4h(Address(rsp, 960), xmm30);
__ vextractf64x4h(Address(rsp, 992), xmm31);
}
}
if (frame::arg_reg_save_area_bytes != 0) {
// Allocate argument register save area
@ -235,6 +312,24 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
map->set_callee_saved(STACK_OFFSET(xmm13_off), xmm13->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm14_off), xmm14->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm15_off), xmm15->as_VMReg());
if (UseAVX > 2) {
map->set_callee_saved(STACK_OFFSET(xmm16_off), xmm16->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm17_off), xmm17->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm18_off), xmm18->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm19_off), xmm19->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm20_off), xmm20->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm21_off), xmm21->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm22_off), xmm22->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm23_off), xmm23->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm24_off), xmm24->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm25_off), xmm25->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm26_off), xmm26->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm27_off), xmm27->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm28_off), xmm28->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm29_off), xmm29->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm30_off), xmm30->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm31_off), xmm31->as_VMReg());
}
// %%% These should all be a waste but we'll keep things as they were for now
if (true) {
@ -269,6 +364,24 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
map->set_callee_saved(STACK_OFFSET(xmm13H_off), xmm13->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm14H_off), xmm14->as_VMReg()->next());
map->set_callee_saved(STACK_OFFSET(xmm15H_off), xmm15->as_VMReg()->next());
if (UseAVX > 2) {
map->set_callee_saved(STACK_OFFSET(xmm16H_off), xmm16->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm17H_off), xmm17->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm18H_off), xmm18->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm19H_off), xmm19->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm20H_off), xmm20->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm21H_off), xmm21->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm22H_off), xmm22->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm23H_off), xmm23->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm24H_off), xmm24->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm25H_off), xmm25->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm26H_off), xmm26->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm27H_off), xmm27->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm28H_off), xmm28->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm29H_off), xmm29->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm30H_off), xmm30->as_VMReg());
map->set_callee_saved(STACK_OFFSET(xmm31H_off), xmm31->as_VMReg());
}
}
return map;
@ -281,9 +394,9 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve
}
#ifdef COMPILER2
if (restore_vectors) {
// Restore upper half of YMM registes.
assert(UseAVX > 0, "256bit vectors are supported only with AVX");
assert(MaxVectorSize == 32, "only 256bit vectors are supported now");
// Restore upper half of YMM registes (0..15)
assert(UseAVX > 0, "512bit vectors are supported only with AVX");
assert(MaxVectorSize == 64, "only 512bit vectors are supported now");
__ vinsertf128h(xmm0, Address(rsp, 0));
__ vinsertf128h(xmm1, Address(rsp, 16));
__ vinsertf128h(xmm2, Address(rsp, 32));
@ -301,6 +414,60 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve
__ vinsertf128h(xmm14, Address(rsp,224));
__ vinsertf128h(xmm15, Address(rsp,240));
__ addptr(rsp, 256);
if (UseAVX > 2) {
// Restore upper half of YMM registes (16..31)
__ vinsertf128h(xmm16, Address(rsp, 0));
__ vinsertf128h(xmm17, Address(rsp, 16));
__ vinsertf128h(xmm18, Address(rsp, 32));
__ vinsertf128h(xmm19, Address(rsp, 48));
__ vinsertf128h(xmm20, Address(rsp, 64));
__ vinsertf128h(xmm21, Address(rsp, 80));
__ vinsertf128h(xmm22, Address(rsp, 96));
__ vinsertf128h(xmm23, Address(rsp,112));
__ vinsertf128h(xmm24, Address(rsp,128));
__ vinsertf128h(xmm25, Address(rsp,144));
__ vinsertf128h(xmm26, Address(rsp,160));
__ vinsertf128h(xmm27, Address(rsp,176));
__ vinsertf128h(xmm28, Address(rsp,192));
__ vinsertf128h(xmm29, Address(rsp,208));
__ vinsertf128h(xmm30, Address(rsp,224));
__ vinsertf128h(xmm31, Address(rsp,240));
__ addptr(rsp, 256);
// Restore upper half of ZMM registes.
__ vinsertf64x4h(xmm0, Address(rsp, 0));
__ vinsertf64x4h(xmm1, Address(rsp, 32));
__ vinsertf64x4h(xmm2, Address(rsp, 64));
__ vinsertf64x4h(xmm3, Address(rsp, 96));
__ vinsertf64x4h(xmm4, Address(rsp, 128));
__ vinsertf64x4h(xmm5, Address(rsp, 160));
__ vinsertf64x4h(xmm6, Address(rsp, 192));
__ vinsertf64x4h(xmm7, Address(rsp, 224));
__ vinsertf64x4h(xmm8, Address(rsp, 256));
__ vinsertf64x4h(xmm9, Address(rsp, 288));
__ vinsertf64x4h(xmm10, Address(rsp, 320));
__ vinsertf64x4h(xmm11, Address(rsp, 352));
__ vinsertf64x4h(xmm12, Address(rsp, 384));
__ vinsertf64x4h(xmm13, Address(rsp, 416));
__ vinsertf64x4h(xmm14, Address(rsp, 448));
__ vinsertf64x4h(xmm15, Address(rsp, 480));
__ vinsertf64x4h(xmm16, Address(rsp, 512));
__ vinsertf64x4h(xmm17, Address(rsp, 544));
__ vinsertf64x4h(xmm18, Address(rsp, 576));
__ vinsertf64x4h(xmm19, Address(rsp, 608));
__ vinsertf64x4h(xmm20, Address(rsp, 640));
__ vinsertf64x4h(xmm21, Address(rsp, 672));
__ vinsertf64x4h(xmm22, Address(rsp, 704));
__ vinsertf64x4h(xmm23, Address(rsp, 736));
__ vinsertf64x4h(xmm24, Address(rsp, 768));
__ vinsertf64x4h(xmm25, Address(rsp, 800));
__ vinsertf64x4h(xmm26, Address(rsp, 832));
__ vinsertf64x4h(xmm27, Address(rsp, 864));
__ vinsertf64x4h(xmm28, Address(rsp, 896));
__ vinsertf64x4h(xmm29, Address(rsp, 928));
__ vinsertf64x4h(xmm30, Address(rsp, 960));
__ vinsertf64x4h(xmm31, Address(rsp, 992));
__ subptr(rsp, 1024);
}
}
#else
assert(!restore_vectors, "vectors are generated only by C2");

View File

@ -166,6 +166,13 @@ class StubGenerator: public StubCodeGenerator {
__ movptr(saved_rdi, rdi);
__ movptr(saved_rsi, rsi);
__ movptr(saved_rbx, rbx);
// provide initial value for required masks
if (UseAVX > 2) {
__ movl(rbx, 0xffff);
__ kmovdl(k1, rbx);
}
// save and initialize %mxcsr
if (sse_save) {
Label skip_ldmx;
@ -794,7 +801,10 @@ class StubGenerator: public StubCodeGenerator {
__ BIND(L_copy_64_bytes_loop);
if (UseUnalignedLoadStores) {
if (UseAVX >= 2) {
if (UseAVX > 2) {
__ evmovdqu(xmm0, Address(from, 0), Assembler::AVX_512bit);
__ evmovdqu(Address(from, to_from, Address::times_1, 0), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(from, 0));
__ vmovdqu(Address(from, to_from, Address::times_1, 0), xmm0);
__ vmovdqu(xmm1, Address(from, 32));
@ -833,7 +843,7 @@ class StubGenerator: public StubCodeGenerator {
__ subl(qword_count, 8);
__ jcc(Assembler::greaterEqual, L_copy_64_bytes_loop);
if (UseUnalignedLoadStores && (UseAVX >= 2)) {
if (UseUnalignedLoadStores && (UseAVX == 2)) {
// clean upper bits of YMM registers
__ vpxor(xmm0, xmm0);
__ vpxor(xmm1, xmm1);

View File

@ -137,8 +137,10 @@ class StubGenerator: public StubCodeGenerator {
// [ return_from_Java ] <--- rsp
// [ argument word n ]
// ...
// -28 [ argument word 1 ]
// -27 [ saved xmm15 ] <--- rsp_after_call
// -60 [ argument word 1 ]
// -59 [ saved xmm31 ] <--- rsp after_call
// [ saved xmm16-xmm30 ] (EVEX enabled, else the space is blank)
// -27 [ saved xmm15 ]
// [ saved xmm7-xmm14 ]
// -9 [ saved xmm6 ] (each xmm register takes 2 slots)
// -7 [ saved r15 ]
@ -166,7 +168,7 @@ class StubGenerator: public StubCodeGenerator {
enum call_stub_layout {
#ifdef _WIN64
xmm_save_first = 6, // save from xmm6
xmm_save_last = 15, // to xmm15
xmm_save_last = 31, // to xmm31
xmm_save_base = -9,
rsp_after_call_off = xmm_save_base - 2 * (xmm_save_last - xmm_save_first), // -27
r15_off = -7,
@ -262,9 +264,19 @@ class StubGenerator: public StubCodeGenerator {
__ movptr(r13_save, r13);
__ movptr(r14_save, r14);
__ movptr(r15_save, r15);
if (UseAVX > 2) {
__ movl(rbx, 0xffff);
__ kmovql(k1, rbx);
}
#ifdef _WIN64
for (int i = 6; i <= 15; i++) {
__ movdqu(xmm_save(i), as_XMMRegister(i));
if (UseAVX > 2) {
for (int i = 6; i <= 31; i++) {
__ movdqu(xmm_save(i), as_XMMRegister(i));
}
} else {
for (int i = 6; i <= 15; i++) {
__ movdqu(xmm_save(i), as_XMMRegister(i));
}
}
const Address rdi_save(rbp, rdi_off * wordSize);
@ -1318,7 +1330,10 @@ class StubGenerator: public StubCodeGenerator {
Label L_end;
// Copy 64-bytes per iteration
__ BIND(L_loop);
if (UseAVX >= 2) {
if (UseAVX > 2) {
__ evmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56), Assembler::AVX_512bit);
__ evmovdqu(Address(end_to, qword_count, Address::times_8, -56), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(end_from, qword_count, Address::times_8, -56));
__ vmovdqu(Address(end_to, qword_count, Address::times_8, -56), xmm0);
__ vmovdqu(xmm1, Address(end_from, qword_count, Address::times_8, -24));
@ -1395,7 +1410,10 @@ class StubGenerator: public StubCodeGenerator {
Label L_end;
// Copy 64-bytes per iteration
__ BIND(L_loop);
if (UseAVX >= 2) {
if (UseAVX > 2) {
__ evmovdqu(xmm0, Address(from, qword_count, Address::times_8, 32), Assembler::AVX_512bit);
__ evmovdqu(Address(dest, qword_count, Address::times_8, 32), xmm0, Assembler::AVX_512bit);
} else if (UseAVX == 2) {
__ vmovdqu(xmm0, Address(from, qword_count, Address::times_8, 32));
__ vmovdqu(Address(dest, qword_count, Address::times_8, 32), xmm0);
__ vmovdqu(xmm1, Address(from, qword_count, Address::times_8, 0));

View File

@ -35,7 +35,7 @@
int VM_Version::_cpu;
int VM_Version::_model;
int VM_Version::_stepping;
int VM_Version::_cpuFeatures;
uint64_t VM_Version::_cpuFeatures;
const char* VM_Version::_features_str = "";
VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, };
@ -45,7 +45,7 @@ address VM_Version::_cpuinfo_segv_addr = 0;
address VM_Version::_cpuinfo_cont_addr = 0;
static BufferBlob* stub_blob;
static const int stub_size = 600;
static const int stub_size = 1000;
extern "C" {
typedef void (*get_cpu_info_stub_t)(void*);
@ -60,15 +60,16 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
address generate_get_cpu_info() {
// Flags to test CPU type.
const uint32_t HS_EFL_AC = 0x40000;
const uint32_t HS_EFL_ID = 0x200000;
const uint32_t HS_EFL_AC = 0x40000;
const uint32_t HS_EFL_ID = 0x200000;
// Values for when we don't have a CPUID instruction.
const int CPU_FAMILY_SHIFT = 8;
const uint32_t CPU_FAMILY_386 = (3 << CPU_FAMILY_SHIFT);
const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT);
const uint32_t CPU_FAMILY_386 = (3 << CPU_FAMILY_SHIFT);
const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT);
Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4;
Label sef_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7, done;
Label sef_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7, done, wrapup;
Label legacy_setup, save_restore_except, legacy_save_restore, start_simd_check;
StubCodeMark mark(this, "VM_Version", "get_cpu_info_stub");
# define __ _masm->
@ -241,53 +242,6 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movl(Address(rsi, 0), rax);
__ movl(Address(rsi, 4), rdx);
__ andl(rax, 0x6); // xcr0 bits sse | ymm
__ cmpl(rax, 0x6);
__ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
//
// Some OSs have a bug when upper 128bits of YMM
// registers are not restored after a signal processing.
// Generate SEGV here (reference through NULL)
// and check upper YMM bits after it.
//
VM_Version::set_avx_cpuFeatures(); // Enable temporary to pass asserts
intx saved_useavx = UseAVX;
intx saved_usesse = UseSSE;
UseAVX = 1;
UseSSE = 2;
// load value into all 32 bytes of ymm7 register
__ movl(rcx, VM_Version::ymm_test_value());
__ movdl(xmm0, rcx);
__ pshufd(xmm0, xmm0, 0x00);
__ vinsertf128h(xmm0, xmm0, xmm0);
__ vmovdqu(xmm7, xmm0);
#ifdef _LP64
__ vmovdqu(xmm8, xmm0);
__ vmovdqu(xmm15, xmm0);
#endif
__ xorl(rsi, rsi);
VM_Version::set_cpuinfo_segv_addr( __ pc() );
// Generate SEGV
__ movl(rax, Address(rsi, 0));
VM_Version::set_cpuinfo_cont_addr( __ pc() );
// Returns here after signal. Save xmm0 to check it later.
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset())));
__ vmovdqu(Address(rsi, 0), xmm0);
__ vmovdqu(Address(rsi, 32), xmm7);
#ifdef _LP64
__ vmovdqu(Address(rsi, 64), xmm8);
__ vmovdqu(Address(rsi, 96), xmm15);
#endif
VM_Version::clean_cpuFeatures();
UseAVX = saved_useavx;
UseSSE = saved_usesse;
//
// cpuid(0x7) Structured Extended Features
//
@ -364,9 +318,143 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movl(Address(rsi,12), rdx);
//
// return
// Check if OS has enabled XGETBV instruction to access XCR0
// (OSXSAVE feature flag) and CPU supports AVX
//
__ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset())));
__ movl(rcx, 0x18000000); // cpuid1 bits osxsave | avx
__ andl(rcx, Address(rsi, 8)); // cpuid1 bits osxsave | avx
__ cmpl(rcx, 0x18000000);
__ jccb(Assembler::notEqual, done); // jump if AVX is not supported
__ movl(rax, 0x6);
__ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm
__ cmpl(rax, 0x6);
__ jccb(Assembler::equal, start_simd_check); // return if AVX is not supported
// we need to bridge farther than imm8, so we use this island as a thunk
__ bind(done);
__ jmp(wrapup);
__ bind(start_simd_check);
//
// Some OSs have a bug when upper 128/256bits of YMM/ZMM
// registers are not restored after a signal processing.
// Generate SEGV here (reference through NULL)
// and check upper YMM/ZMM bits after it.
//
intx saved_useavx = UseAVX;
intx saved_usesse = UseSSE;
// check _cpuid_info.sef_cpuid7_ebx.bits.avx512f
__ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset())));
__ movl(rax, 0x10000);
__ andl(rax, Address(rsi, 4)); // xcr0 bits sse | ymm
__ cmpl(rax, 0x10000);
__ jccb(Assembler::notEqual, legacy_setup); // jump if EVEX is not supported
// check _cpuid_info.xem_xcr0_eax.bits.opmask
// check _cpuid_info.xem_xcr0_eax.bits.zmm512
// check _cpuid_info.xem_xcr0_eax.bits.zmm32
__ movl(rax, 0xE0);
__ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm
__ cmpl(rax, 0xE0);
__ jccb(Assembler::notEqual, legacy_setup); // jump if EVEX is not supported
// EVEX setup: run in lowest evex mode
VM_Version::set_evex_cpuFeatures(); // Enable temporary to pass asserts
UseAVX = 3;
UseSSE = 2;
// load value into all 64 bytes of zmm7 register
__ movl(rcx, VM_Version::ymm_test_value());
__ movdl(xmm0, rcx);
__ movl(rcx, 0xffff);
#ifdef _LP64
__ kmovql(k1, rcx);
#else
__ kmovdl(k1, rcx);
#endif
__ evpbroadcastd(xmm0, xmm0, Assembler::AVX_512bit);
__ evmovdqu(xmm7, xmm0, Assembler::AVX_512bit);
#ifdef _LP64
__ evmovdqu(xmm8, xmm0, Assembler::AVX_512bit);
__ evmovdqu(xmm31, xmm0, Assembler::AVX_512bit);
#endif
VM_Version::clean_cpuFeatures();
__ jmp(save_restore_except);
__ bind(legacy_setup);
// AVX setup
VM_Version::set_avx_cpuFeatures(); // Enable temporary to pass asserts
UseAVX = 1;
UseSSE = 2;
// load value into all 32 bytes of ymm7 register
__ movl(rcx, VM_Version::ymm_test_value());
__ movdl(xmm0, rcx);
__ pshufd(xmm0, xmm0, 0x00);
__ vinsertf128h(xmm0, xmm0, xmm0);
__ vmovdqu(xmm7, xmm0);
#ifdef _LP64
__ vmovdqu(xmm8, xmm0);
__ vmovdqu(xmm15, xmm0);
#endif
VM_Version::clean_cpuFeatures();
__ bind(save_restore_except);
__ xorl(rsi, rsi);
VM_Version::set_cpuinfo_segv_addr(__ pc());
// Generate SEGV
__ movl(rax, Address(rsi, 0));
VM_Version::set_cpuinfo_cont_addr(__ pc());
// Returns here after signal. Save xmm0 to check it later.
// check _cpuid_info.sef_cpuid7_ebx.bits.avx512f
__ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset())));
__ movl(rax, 0x10000);
__ andl(rax, Address(rsi, 4));
__ cmpl(rax, 0x10000);
__ jccb(Assembler::notEqual, legacy_save_restore);
// check _cpuid_info.xem_xcr0_eax.bits.opmask
// check _cpuid_info.xem_xcr0_eax.bits.zmm512
// check _cpuid_info.xem_xcr0_eax.bits.zmm32
__ movl(rax, 0xE0);
__ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm
__ cmpl(rax, 0xE0);
__ jccb(Assembler::notEqual, legacy_save_restore);
// EVEX check: run in lowest evex mode
VM_Version::set_evex_cpuFeatures(); // Enable temporary to pass asserts
UseAVX = 3;
UseSSE = 2;
__ lea(rsi, Address(rbp, in_bytes(VM_Version::zmm_save_offset())));
__ evmovdqu(Address(rsi, 0), xmm0, Assembler::AVX_512bit);
__ evmovdqu(Address(rsi, 64), xmm7, Assembler::AVX_512bit);
#ifdef _LP64
__ evmovdqu(Address(rsi, 128), xmm8, Assembler::AVX_512bit);
__ evmovdqu(Address(rsi, 192), xmm31, Assembler::AVX_512bit);
#endif
VM_Version::clean_cpuFeatures();
UseAVX = saved_useavx;
UseSSE = saved_usesse;
__ jmp(wrapup);
__ bind(legacy_save_restore);
// AVX check
VM_Version::set_avx_cpuFeatures(); // Enable temporary to pass asserts
UseAVX = 1;
UseSSE = 2;
__ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset())));
__ vmovdqu(Address(rsi, 0), xmm0);
__ vmovdqu(Address(rsi, 32), xmm7);
#ifdef _LP64
__ vmovdqu(Address(rsi, 64), xmm8);
__ vmovdqu(Address(rsi, 96), xmm15);
#endif
VM_Version::clean_cpuFeatures();
UseAVX = saved_useavx;
UseSSE = saved_usesse;
__ bind(wrapup);
__ popf();
__ pop(rsi);
__ pop(rbx);
@ -459,6 +547,29 @@ void VM_Version::get_processor_features() {
if (UseSSE < 1)
_cpuFeatures &= ~CPU_SSE;
// first try initial setting and detect what we can support
if (UseAVX > 0) {
if (UseAVX > 2 && supports_evex()) {
UseAVX = 3;
} else if (UseAVX > 1 && supports_avx2()) {
UseAVX = 2;
} else if (UseAVX > 0 && supports_avx()) {
UseAVX = 1;
} else {
UseAVX = 0;
}
} else if (UseAVX < 0) {
UseAVX = 0;
}
if (UseAVX < 3) {
_cpuFeatures &= ~CPU_AVX512F;
_cpuFeatures &= ~CPU_AVX512DQ;
_cpuFeatures &= ~CPU_AVX512CD;
_cpuFeatures &= ~CPU_AVX512BW;
_cpuFeatures &= ~CPU_AVX512VL;
}
if (UseAVX < 2)
_cpuFeatures &= ~CPU_AVX2;
@ -474,7 +585,7 @@ void VM_Version::get_processor_features() {
}
char buf[256];
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
cores_per_cpu(), threads_per_core(),
cpu_family(), _model, _stepping,
(supports_cmov() ? ", cmov" : ""),
@ -504,7 +615,8 @@ void VM_Version::get_processor_features() {
(supports_tscinv() ? ", tscinv": ""),
(supports_bmi1() ? ", bmi1" : ""),
(supports_bmi2() ? ", bmi2" : ""),
(supports_adx() ? ", adx" : ""));
(supports_adx() ? ", adx" : ""),
(supports_evex() ? ", evex" : ""));
_features_str = os::strdup(buf);
// UseSSE is set to the smaller of what hardware supports and what
@ -521,13 +633,6 @@ void VM_Version::get_processor_features() {
if (!supports_sse ()) // Drop to 0 if no SSE support
UseSSE = 0;
if (UseAVX > 2) UseAVX=2;
if (UseAVX < 0) UseAVX=0;
if (!supports_avx2()) // Drop to 1 if no AVX2 support
UseAVX = MIN2((intx)1,UseAVX);
if (!supports_avx ()) // Drop to 0 if no AVX support
UseAVX = 0;
// Use AES instructions if available.
if (supports_aes()) {
if (FLAG_IS_DEFAULT(UseAES)) {
@ -598,7 +703,8 @@ void VM_Version::get_processor_features() {
if ((_model == CPU_MODEL_HASWELL_E3) ||
(_model == CPU_MODEL_HASWELL_E7 && _stepping < 3) ||
(_model == CPU_MODEL_BROADWELL && _stepping < 4)) {
if (!UnlockExperimentalVMOptions) {
// currently a collision between SKL and HSW_E3
if (!UnlockExperimentalVMOptions && UseAVX < 3) {
vm_exit_during_initialization("UseRTMLocking is only available as experimental option on this platform. It must be enabled via -XX:+UnlockExperimentalVMOptions flag.");
} else {
warning("UseRTMLocking is only available as experimental option on this platform.");
@ -651,10 +757,10 @@ void VM_Version::get_processor_features() {
if (MaxVectorSize > 0) {
if (!is_power_of_2(MaxVectorSize)) {
warning("MaxVectorSize must be a power of 2");
FLAG_SET_DEFAULT(MaxVectorSize, 32);
FLAG_SET_DEFAULT(MaxVectorSize, 64);
}
if (MaxVectorSize > 32) {
FLAG_SET_DEFAULT(MaxVectorSize, 32);
if (MaxVectorSize > 64) {
FLAG_SET_DEFAULT(MaxVectorSize, 64);
}
if (MaxVectorSize > 16 && (UseAVX == 0 || !os_supports_avx_vectors())) {
// 32 bytes vectors (in YMM) are only supported with AVX+

View File

@ -208,20 +208,33 @@ public:
bmi2 : 1,
erms : 1,
: 1,
rtm : 1,
: 7,
adx : 1,
: 12;
rtm : 1,
: 4,
avx512f : 1,
avx512dq : 1,
: 1,
adx : 1,
: 6,
avx512pf : 1,
avx512er : 1,
avx512cd : 1,
: 1,
avx512bw : 1,
avx512vl : 1;
} bits;
};
union XemXcr0Eax {
uint32_t value;
struct {
uint32_t x87 : 1,
sse : 1,
ymm : 1,
: 29;
uint32_t x87 : 1,
sse : 1,
ymm : 1,
: 2,
opmask : 1,
zmm512 : 1,
zmm32 : 1,
: 24;
} bits;
};
@ -229,43 +242,51 @@ protected:
static int _cpu;
static int _model;
static int _stepping;
static int _cpuFeatures; // features returned by the "cpuid" instruction
// 0 if this instruction is not available
static uint64_t _cpuFeatures; // features returned by the "cpuid" instruction
// 0 if this instruction is not available
static const char* _features_str;
static address _cpuinfo_segv_addr; // address of instruction which causes SEGV
static address _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV
enum {
CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX)
CPU_CMOV = (1 << 1),
CPU_FXSR = (1 << 2),
CPU_HT = (1 << 3),
CPU_MMX = (1 << 4),
CPU_3DNOW_PREFETCH = (1 << 5), // Processor supports 3dnow prefetch and prefetchw instructions
// may not necessarily support other 3dnow instructions
CPU_SSE = (1 << 6),
CPU_SSE2 = (1 << 7),
CPU_SSE3 = (1 << 8), // SSE3 comes from cpuid 1 (ECX)
CPU_SSSE3 = (1 << 9),
CPU_SSE4A = (1 << 10),
CPU_SSE4_1 = (1 << 11),
CPU_SSE4_2 = (1 << 12),
CPU_POPCNT = (1 << 13),
CPU_LZCNT = (1 << 14),
CPU_TSC = (1 << 15),
CPU_TSCINV = (1 << 16),
CPU_AVX = (1 << 17),
CPU_AVX2 = (1 << 18),
CPU_AES = (1 << 19),
CPU_ERMS = (1 << 20), // enhanced 'rep movsb/stosb' instructions
CPU_CLMUL = (1 << 21), // carryless multiply for CRC
CPU_BMI1 = (1 << 22),
CPU_BMI2 = (1 << 23),
CPU_RTM = (1 << 24), // Restricted Transactional Memory instructions
CPU_ADX = (1 << 25)
CPU_CX8 = (1 << 0), // next bits are from cpuid 1 (EDX)
CPU_CMOV = (1 << 1),
CPU_FXSR = (1 << 2),
CPU_HT = (1 << 3),
CPU_MMX = (1 << 4),
CPU_3DNOW_PREFETCH = (1 << 5), // Processor supports 3dnow prefetch and prefetchw instructions
// may not necessarily support other 3dnow instructions
CPU_SSE = (1 << 6),
CPU_SSE2 = (1 << 7),
CPU_SSE3 = (1 << 8), // SSE3 comes from cpuid 1 (ECX)
CPU_SSSE3 = (1 << 9),
CPU_SSE4A = (1 << 10),
CPU_SSE4_1 = (1 << 11),
CPU_SSE4_2 = (1 << 12),
CPU_POPCNT = (1 << 13),
CPU_LZCNT = (1 << 14),
CPU_TSC = (1 << 15),
CPU_TSCINV = (1 << 16),
CPU_AVX = (1 << 17),
CPU_AVX2 = (1 << 18),
CPU_AES = (1 << 19),
CPU_ERMS = (1 << 20), // enhanced 'rep movsb/stosb' instructions
CPU_CLMUL = (1 << 21), // carryless multiply for CRC
CPU_BMI1 = (1 << 22),
CPU_BMI2 = (1 << 23),
CPU_RTM = (1 << 24), // Restricted Transactional Memory instructions
CPU_ADX = (1 << 25),
CPU_AVX512F = (1 << 26), // AVX 512bit foundation instructions
CPU_AVX512DQ = (1 << 27),
CPU_AVX512PF = (1 << 28),
CPU_AVX512ER = (1 << 29),
CPU_AVX512CD = (1 << 30),
CPU_AVX512BW = (1 << 31)
} cpuFeatureFlags;
#define CPU_AVX512VL 0x100000000 // EVEX instructions with smaller vector length : enums are limited to 32bit
enum {
// AMD
CPU_FAMILY_AMD_11H = 0x11,
@ -282,7 +303,8 @@ protected:
CPU_MODEL_IVYBRIDGE_EP = 0x3a,
CPU_MODEL_HASWELL_E3 = 0x3c,
CPU_MODEL_HASWELL_E7 = 0x3f,
CPU_MODEL_BROADWELL = 0x3d
CPU_MODEL_BROADWELL = 0x3d,
CPU_MODEL_SKYLAKE = CPU_MODEL_HASWELL_E3
} cpuExtendedFamily;
// cpuid information block. All info derived from executing cpuid with
@ -376,6 +398,9 @@ protected:
// Space to save ymm registers after signal handle
int ymm_save[8*4]; // Save ymm0, ymm7, ymm8, ymm15
// Space to save zmm registers after signal handle
int zmm_save[16*4]; // Save zmm0, zmm7, zmm8, zmm31
};
// The actual cpuid info block
@ -404,8 +429,8 @@ protected:
return result;
}
static uint32_t feature_flags() {
uint32_t result = 0;
static uint64_t feature_flags() {
uint64_t result = 0;
if (_cpuid_info.std_cpuid1_edx.bits.cmpxchg8 != 0)
result |= CPU_CX8;
if (_cpuid_info.std_cpuid1_edx.bits.cmov != 0)
@ -440,6 +465,24 @@ protected:
result |= CPU_AVX;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx2 != 0)
result |= CPU_AVX2;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512f != 0 &&
_cpuid_info.xem_xcr0_eax.bits.opmask != 0 &&
_cpuid_info.xem_xcr0_eax.bits.zmm512 != 0 &&
_cpuid_info.xem_xcr0_eax.bits.zmm32 != 0) {
result |= CPU_AVX512F;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512cd != 0)
result |= CPU_AVX512CD;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512dq != 0)
result |= CPU_AVX512DQ;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512pf != 0)
result |= CPU_AVX512PF;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512er != 0)
result |= CPU_AVX512ER;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512bw != 0)
result |= CPU_AVX512BW;
if (_cpuid_info.sef_cpuid7_ebx.bits.avx512vl != 0)
result |= CPU_AVX512VL;
}
}
if(_cpuid_info.sef_cpuid7_ebx.bits.bmi1 != 0)
result |= CPU_BMI1;
@ -484,18 +527,31 @@ protected:
}
static bool os_supports_avx_vectors() {
if (!supports_avx()) {
return false;
}
// Verify that OS save/restore all bits of AVX registers
// during signal processing.
int nreg = 2 LP64_ONLY(+2);
for (int i = 0; i < 8 * nreg; i++) { // 32 bytes per ymm register
if (_cpuid_info.ymm_save[i] != ymm_test_value()) {
return false;
bool retVal = false;
if (supports_evex()) {
// Verify that OS save/restore all bits of EVEX registers
// during signal processing.
int nreg = 2 LP64_ONLY(+2);
retVal = true;
for (int i = 0; i < 16 * nreg; i++) { // 64 bytes per zmm register
if (_cpuid_info.zmm_save[i] != ymm_test_value()) {
retVal = false;
break;
}
}
} else if (supports_avx()) {
// Verify that OS save/restore all bits of AVX registers
// during signal processing.
int nreg = 2 LP64_ONLY(+2);
retVal = true;
for (int i = 0; i < 8 * nreg; i++) { // 32 bytes per ymm register
if (_cpuid_info.ymm_save[i] != ymm_test_value()) {
retVal = false;
break;
}
}
}
return true;
return retVal;
}
static void get_processor_features();
@ -515,6 +571,7 @@ public:
static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); }
static ByteSize xem_xcr0_offset() { return byte_offset_of(CpuidInfo, xem_xcr0_eax); }
static ByteSize ymm_save_offset() { return byte_offset_of(CpuidInfo, ymm_save); }
static ByteSize zmm_save_offset() { return byte_offset_of(CpuidInfo, zmm_save); }
// The value used to check ymm register after signal handle
static int ymm_test_value() { return 0xCAFEBABE; }
@ -527,6 +584,7 @@ public:
static void clean_cpuFeatures() { _cpuFeatures = 0; }
static void set_avx_cpuFeatures() { _cpuFeatures = (CPU_SSE | CPU_SSE2 | CPU_AVX); }
static void set_evex_cpuFeatures() { _cpuFeatures = (CPU_AVX512F | CPU_SSE | CPU_SSE2 ); }
// Initialization
@ -636,7 +694,14 @@ public:
static bool supports_rtm() { return (_cpuFeatures & CPU_RTM) != 0; }
static bool supports_bmi1() { return (_cpuFeatures & CPU_BMI1) != 0; }
static bool supports_bmi2() { return (_cpuFeatures & CPU_BMI2) != 0; }
static bool supports_adx() { return (_cpuFeatures & CPU_ADX) != 0; }
static bool supports_adx() { return (_cpuFeatures & CPU_ADX) != 0; }
static bool supports_evex() { return (_cpuFeatures & CPU_AVX512F) != 0; }
static bool supports_avx512dq() { return (_cpuFeatures & CPU_AVX512DQ) != 0; }
static bool supports_avx512pf() { return (_cpuFeatures & CPU_AVX512PF) != 0; }
static bool supports_avx512er() { return (_cpuFeatures & CPU_AVX512ER) != 0; }
static bool supports_avx512cd() { return (_cpuFeatures & CPU_AVX512CD) != 0; }
static bool supports_avx512bw() { return (_cpuFeatures & CPU_AVX512BW) != 0; }
static bool supports_avx512vl() { return (_cpuFeatures & CPU_AVX512VL) != 0; }
// Intel features
static bool is_intel_family_core() { return is_intel() &&
extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }

View File

@ -47,13 +47,22 @@ void VMRegImpl::set_regName() {
}
XMMRegister xreg = ::as_XMMRegister(0);
for ( ; i < ConcreteRegisterImpl::max_xmm ; ) {
for (int j = 0 ; j < 8 ; j++) {
for (; i < ConcreteRegisterImpl::max_xmm;) {
for (int j = 0 ; j < XMMRegisterImpl::max_slots_per_register ; j++) {
regName[i++] = xreg->name();
}
xreg = xreg->successor();
}
KRegister kreg = ::as_KRegister(0);
for (; i < ConcreteRegisterImpl::max_kpr;) {
for (int j = 0; j < KRegisterImpl::max_slots_per_register; j++) {
regName[i++] = kreg->name();
}
kreg = kreg->successor();
}
for ( ; i < ConcreteRegisterImpl::number_of_registers ; i ++ ) {
regName[i] = "NON-GPR-FPR-XMM";
regName[i] = "NON-GPR-FPR-XMM-KREG";
}
}

View File

@ -36,7 +36,24 @@ inline bool is_FloatRegister() {
}
inline bool is_XMMRegister() {
return value() >= ConcreteRegisterImpl::max_fpr && value() < ConcreteRegisterImpl::max_xmm;
int uarch_max_xmm = ConcreteRegisterImpl::max_xmm;
#ifdef _LP64
if (UseAVX < 3) {
int half_xmm = (XMMRegisterImpl::max_slots_per_register * XMMRegisterImpl::number_of_registers) / 2;
uarch_max_xmm -= half_xmm;
}
#endif
return (value() >= ConcreteRegisterImpl::max_fpr && value() < uarch_max_xmm);
}
inline bool is_KRegister() {
if (UseAVX > 2) {
return value() >= ConcreteRegisterImpl::max_xmm && value() < ConcreteRegisterImpl::max_kpr;
} else {
return false;
}
}
inline Register as_Register() {
@ -59,7 +76,13 @@ inline FloatRegister as_FloatRegister() {
inline XMMRegister as_XMMRegister() {
assert( is_XMMRegister() && is_even(value()), "must be" );
// Yuk
return ::as_XMMRegister((value() - ConcreteRegisterImpl::max_fpr) >> 3);
return ::as_XMMRegister((value() - ConcreteRegisterImpl::max_fpr) >> 4);
}
inline KRegister as_KRegister() {
assert(is_KRegister(), "must be");
// Yuk
return ::as_KRegister((value() - ConcreteRegisterImpl::max_xmm));
}
inline bool is_concrete() {

View File

@ -39,7 +39,11 @@ inline VMReg FloatRegisterImpl::as_VMReg() {
}
inline VMReg XMMRegisterImpl::as_VMReg() {
return VMRegImpl::as_VMReg((encoding() << 3) + ConcreteRegisterImpl::max_fpr);
return VMRegImpl::as_VMReg((encoding() << 4) + ConcreteRegisterImpl::max_fpr);
}
inline VMReg KRegisterImpl::as_VMReg() {
return VMRegImpl::as_VMReg(encoding() + ConcreteRegisterImpl::max_xmm);
}
#endif // CPU_X86_VM_VMREG_X86_INLINE_HPP

File diff suppressed because it is too large Load Diff

View File

@ -101,6 +101,17 @@ reg_def FPR6L( SOC, SOC, Op_RegF, 6, as_FloatRegister(5)->as_VMReg());
reg_def FPR6H( SOC, SOC, Op_RegF, 6, as_FloatRegister(5)->as_VMReg()->next());
reg_def FPR7L( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg());
reg_def FPR7H( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next());
//
// Empty fill registers, which are never used, but supply alignment to xmm regs
//
reg_def FILL0( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(2));
reg_def FILL1( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(3));
reg_def FILL2( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(4));
reg_def FILL3( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(5));
reg_def FILL4( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(6));
reg_def FILL5( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(7));
reg_def FILL6( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(8));
reg_def FILL7( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(9));
// Specify priority of register selection within phases of register
// allocation. Highest priority is first. A useful heuristic is to
@ -112,7 +123,8 @@ reg_def FPR7H( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next());
alloc_class chunk0( ECX, EBX, EBP, EDI, EAX, EDX, ESI, ESP,
FPR0L, FPR0H, FPR1L, FPR1H, FPR2L, FPR2H,
FPR3L, FPR3H, FPR4L, FPR4H, FPR5L, FPR5H,
FPR6L, FPR6H, FPR7L, FPR7H );
FPR6L, FPR6H, FPR7L, FPR7H,
FILL0, FILL1, FILL2, FILL3, FILL4, FILL5, FILL6, FILL7);
//----------Architecture Description Register Classes--------------------------
@ -131,7 +143,7 @@ reg_class any_reg_with_ebp(EAX, EDX, EBP, EDI, ESI, ECX, EBX, ESP);
// Class for all registers (excluding EBP)
reg_class any_reg_no_ebp(EAX, EDX, EDI, ESI, ECX, EBX, ESP);
// Dynamic register class that selects at runtime between register classes
// any_reg and any_no_ebp_reg (depending on the value of the flag PreserveFramePointer).
// any_reg and any_no_ebp_reg (depending on the value of the flag PreserveFramePointer).
// Equivalent to: return PreserveFramePointer ? any_no_ebp_reg : any_reg;
reg_class_dynamic any_reg(any_reg_no_ebp, any_reg_with_ebp, %{ PreserveFramePointer %});
@ -279,7 +291,9 @@ static int pre_call_resets_size() {
size += 6; // fldcw
}
if (C->max_vector_size() > 16) {
size += 3; // vzeroupper
if(UseAVX <= 2) {
size += 3; // vzeroupper
}
}
return size;
}
@ -288,7 +302,7 @@ static int pre_call_resets_size() {
// from the start of the call to the point where the return address
// will point.
int MachCallStaticJavaNode::ret_addr_offset() {
return 5 + pre_call_resets_size(); // 5 bytes from start of call to where return address points
return 5 + pre_call_resets_size(); // 5 bytes from start of call to where return address points
}
int MachCallDynamicJavaNode::ret_addr_offset() {
@ -767,6 +781,12 @@ static int impl_helper( CodeBuffer *cbuf, bool do_size, bool is_load, int offset
// Helper for XMM registers. Extra opcode bits, limited syntax.
static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load,
int offset, int reg_lo, int reg_hi, int size, outputStream* st ) {
int in_size_in_bits = Assembler::EVEX_32bit;
int evex_encoding = 0;
if (reg_lo+1 == reg_hi) {
in_size_in_bits = Assembler::EVEX_64bit;
evex_encoding = Assembler::VEX_W;
}
if (cbuf) {
MacroAssembler _masm(cbuf);
if (reg_lo+1 == reg_hi) { // double move?
@ -799,7 +819,17 @@ static int impl_x_helper( CodeBuffer *cbuf, bool do_size, bool is_load,
}
#endif
}
int offset_size = (offset == 0) ? 0 : ((offset <= 127) ? 1 : 4);
bool is_single_byte = false;
if ((UseAVX > 2) && (offset != 0)) {
is_single_byte = Assembler::query_compressed_disp_byte(offset, true, 0, Assembler::EVEX_T1S, in_size_in_bits, evex_encoding);
}
int offset_size = 0;
if (UseAVX > 2 ) {
offset_size = (offset == 0) ? 0 : ((is_single_byte) ? 1 : 4);
} else {
offset_size = (offset == 0) ? 0 : ((offset <= 127) ? 1 : 4);
}
size += (UseAVX > 2) ? 2 : 0; // Need an additional two bytes for EVEX
// VEX_2bytes prefix is used if UseAVX > 0, so it takes the same 2 bytes as SIMD prefix.
return size+5+offset_size;
}
@ -835,8 +865,8 @@ static int impl_movx_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int dst
#endif
}
// VEX_2bytes prefix is used if UseAVX > 0, and it takes the same 2 bytes as SIMD prefix.
// Only MOVAPS SSE prefix uses 1 byte.
int sz = 4;
// Only MOVAPS SSE prefix uses 1 byte. EVEX uses an additional 2 bytes.
int sz = (UseAVX > 2) ? 6 : 4;
if (!(src_lo+1 == src_hi && dst_lo+1 == dst_hi) &&
UseXmmRegToRegMoveAll && (UseAVX == 0)) sz = 3;
return size + sz;
@ -854,7 +884,7 @@ static int impl_movgpr2x_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int
st->print("movdl %s, %s\t# spill", Matcher::regName[dst_lo], Matcher::regName[src_lo]);
#endif
}
return 4;
return (UseAVX> 2) ? 6 : 4;
}
@ -870,7 +900,7 @@ static int impl_movx2gpr_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int
st->print("movdl %s, %s\t# spill", Matcher::regName[dst_lo], Matcher::regName[src_lo]);
#endif
}
return 4;
return (UseAVX> 2) ? 6 : 4;
}
static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int size, outputStream* st ) {
@ -941,9 +971,8 @@ static int vec_stack_to_stack_helper(CodeBuffer *cbuf, bool do_size, int src_off
calc_size += 3+src_offset_size + 3+dst_offset_size;
break;
case Op_VecX:
calc_size = 6 + 6 + 5+src_offset_size + 5+dst_offset_size;
break;
case Op_VecY:
case Op_VecZ:
calc_size = 6 + 6 + 5+src_offset_size + 5+dst_offset_size;
break;
default:
@ -974,6 +1003,11 @@ static int vec_stack_to_stack_helper(CodeBuffer *cbuf, bool do_size, int src_off
__ vmovdqu(xmm0, Address(rsp, src_offset));
__ vmovdqu(Address(rsp, dst_offset), xmm0);
__ vmovdqu(xmm0, Address(rsp, -32));
case Op_VecZ:
__ evmovdqu(Address(rsp, -64), xmm0, 2);
__ evmovdqu(xmm0, Address(rsp, src_offset), 2);
__ evmovdqu(Address(rsp, dst_offset), xmm0, 2);
__ evmovdqu(xmm0, Address(rsp, -64), 2);
break;
default:
ShouldNotReachHere();
@ -1009,6 +1043,12 @@ static int vec_stack_to_stack_helper(CodeBuffer *cbuf, bool do_size, int src_off
"vmovdqu [rsp + #%d], xmm0\n\t"
"vmovdqu xmm0, [rsp - #32]",
src_offset, dst_offset);
case Op_VecZ:
st->print("vmovdqu [rsp - #64], xmm0\t# 512-bit mem-mem spill\n\t"
"vmovdqu xmm0, [rsp + #%d]\n\t"
"vmovdqu [rsp + #%d], xmm0\n\t"
"vmovdqu xmm0, [rsp - #64]",
src_offset, dst_offset);
break;
default:
ShouldNotReachHere();
@ -1042,7 +1082,7 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo
uint ireg = ideal_reg();
assert((src_first_rc != rc_int && dst_first_rc != rc_int), "sanity");
assert((src_first_rc != rc_float && dst_first_rc != rc_float), "sanity");
assert((ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY), "sanity");
assert((ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY || ireg == Op_VecZ ), "sanity");
if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) {
// mem -> mem
int src_offset = ra_->reg2offset(src_first);
@ -3998,7 +4038,7 @@ operand regFPR1(regFPR reg) %{
// XMM Float register operands
operand regF() %{
predicate( UseSSE>=1 );
constraint(ALLOC_IN_RC(float_reg));
constraint(ALLOC_IN_RC(float_reg_legacy));
match(RegF);
format %{ %}
interface(REG_INTER);
@ -4007,12 +4047,45 @@ operand regF() %{
// XMM Double register operands
operand regD() %{
predicate( UseSSE>=2 );
constraint(ALLOC_IN_RC(double_reg));
constraint(ALLOC_IN_RC(double_reg_legacy));
match(RegD);
format %{ %}
interface(REG_INTER);
%}
// Vectors : note, we use legacy registers to avoid extra (unneeded in 32-bit VM)
// runtime code generation via reg_class_dynamic.
operand vecS() %{
constraint(ALLOC_IN_RC(vectors_reg_legacy));
match(VecS);
format %{ %}
interface(REG_INTER);
%}
operand vecD() %{
constraint(ALLOC_IN_RC(vectord_reg_legacy));
match(VecD);
format %{ %}
interface(REG_INTER);
%}
operand vecX() %{
constraint(ALLOC_IN_RC(vectorx_reg_legacy));
match(VecX);
format %{ %}
interface(REG_INTER);
%}
operand vecY() %{
constraint(ALLOC_IN_RC(vectory_reg_legacy));
match(VecY);
format %{ %}
interface(REG_INTER);
%}
//----------Memory Operands----------------------------------------------------
// Direct Memory Operand
@ -5020,11 +5093,11 @@ instruct bytes_reverse_unsigned_short(rRegI dst, eFlagsReg cr) %{
match(Set dst (ReverseBytesUS dst));
effect(KILL cr);
format %{ "BSWAP $dst\n\t"
format %{ "BSWAP $dst\n\t"
"SHR $dst,16\n\t" %}
ins_encode %{
__ bswapl($dst$$Register);
__ shrl($dst$$Register, 16);
__ shrl($dst$$Register, 16);
%}
ins_pipe( ialu_reg );
%}
@ -5033,11 +5106,11 @@ instruct bytes_reverse_short(rRegI dst, eFlagsReg cr) %{
match(Set dst (ReverseBytesS dst));
effect(KILL cr);
format %{ "BSWAP $dst\n\t"
format %{ "BSWAP $dst\n\t"
"SAR $dst,16\n\t" %}
ins_encode %{
__ bswapl($dst$$Register);
__ sarl($dst$$Register, 16);
__ sarl($dst$$Register, 16);
%}
ins_pipe( ialu_reg );
%}
@ -6525,7 +6598,7 @@ instruct membar_volatile(eFlagsReg cr) %{
effect(KILL cr);
ins_cost(400);
format %{
format %{
$$template
if (os::is_MP()) {
$$emit$$"LOCK ADDL [ESP + #0], 0\t! membar_volatile"
@ -8288,10 +8361,10 @@ instruct xorI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{
// Xor Register with Immediate -1
instruct xorI_eReg_im1(rRegI dst, immI_M1 imm) %{
match(Set dst (XorI dst imm));
match(Set dst (XorI dst imm));
size(2);
format %{ "NOT $dst" %}
format %{ "NOT $dst" %}
ins_encode %{
__ notl($dst$$Register);
%}
@ -8939,7 +9012,7 @@ instruct xorl_eReg(eRegL dst, eRegL src, eFlagsReg cr) %{
// Xor Long Register with Immediate -1
instruct xorl_eReg_im1(eRegL dst, immL_M1 imm) %{
match(Set dst (XorL dst imm));
match(Set dst (XorL dst imm));
format %{ "NOT $dst.lo\n\t"
"NOT $dst.hi" %}
ins_encode %{
@ -8994,7 +9067,7 @@ instruct shlL_eReg_2(eRegL dst, immI_2 cnt, eFlagsReg cr) %{
effect(KILL cr);
ins_cost(100);
format %{ "ADD $dst.lo,$dst.lo\n\t"
"ADC $dst.hi,$dst.hi\n\t"
"ADC $dst.hi,$dst.hi\n\t"
"ADD $dst.lo,$dst.lo\n\t"
"ADC $dst.hi,$dst.hi" %}
ins_encode %{
@ -9013,9 +9086,9 @@ instruct shlL_eReg_3(eRegL dst, immI_3 cnt, eFlagsReg cr) %{
effect(KILL cr);
ins_cost(100);
format %{ "ADD $dst.lo,$dst.lo\n\t"
"ADC $dst.hi,$dst.hi\n\t"
"ADC $dst.hi,$dst.hi\n\t"
"ADD $dst.lo,$dst.lo\n\t"
"ADC $dst.hi,$dst.hi\n\t"
"ADC $dst.hi,$dst.hi\n\t"
"ADD $dst.lo,$dst.lo\n\t"
"ADC $dst.hi,$dst.hi" %}
ins_encode %{
@ -11168,7 +11241,6 @@ instruct convL2I_reg( rRegI dst, eRegL src ) %{
ins_pipe( ialu_reg_reg );
%}
instruct MoveF2I_stack_reg(rRegI dst, stackSlotF src) %{
match(Set dst (MoveF2I src));
effect( DEF dst, USE src );
@ -11400,7 +11472,7 @@ instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlag
format %{ "XOR EAX,EAX\t# ClearArray:\n\t"
"SHL ECX,1\t# Convert doublewords to words\n\t"
"REP STOS\t# store EAX into [EDI++] while ECX--" %}
ins_encode %{
ins_encode %{
__ clear_mem($base$$Register, $cnt$$Register, $zero$$Register);
%}
ins_pipe( pipe_slow );
@ -11413,7 +11485,7 @@ instruct rep_fast_stosb(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy,
format %{ "XOR EAX,EAX\t# ClearArray:\n\t"
"SHL ECX,3\t# Convert doublewords to bytes\n\t"
"REP STOSB\t# store EAX into [EDI++] while ECX--" %}
ins_encode %{
ins_encode %{
__ clear_mem($base$$Register, $cnt$$Register, $zero$$Register);
%}
ins_pipe( pipe_slow );

View File

@ -172,7 +172,7 @@ reg_class no_reg();
// Class for all pointer registers (including RSP and RBP)
reg_class any_reg_with_rbp(RAX, RAX_H,
RDX, RDX_H,
RBP, RBP_H,
RBP, RBP_H,
RDI, RDI_H,
RSI, RSI_H,
RCX, RCX_H,
@ -189,7 +189,7 @@ reg_class any_reg_with_rbp(RAX, RAX_H,
// Class for all pointer registers (including RSP, but excluding RBP)
reg_class any_reg_no_rbp(RAX, RAX_H,
RDX, RDX_H,
RDX, RDX_H,
RDI, RDI_H,
RSI, RSI_H,
RCX, RCX_H,
@ -205,10 +205,10 @@ reg_class any_reg_no_rbp(RAX, RAX_H,
R15, R15_H);
// Dynamic register class that selects at runtime between register classes
// any_reg_no_rbp and any_reg_with_rbp (depending on the value of the flag PreserveFramePointer).
// any_reg_no_rbp and any_reg_with_rbp (depending on the value of the flag PreserveFramePointer).
// Equivalent to: return PreserveFramePointer ? any_reg_no_rbp : any_reg_with_rbp;
reg_class_dynamic any_reg(any_reg_no_rbp, any_reg_with_rbp, %{ PreserveFramePointer %});
// Class for all pointer registers (excluding RSP)
reg_class ptr_reg_with_rbp(RAX, RAX_H,
RDX, RDX_H,
@ -226,7 +226,7 @@ reg_class ptr_reg_with_rbp(RAX, RAX_H,
// Class for all pointer registers (excluding RSP and RBP)
reg_class ptr_reg_no_rbp(RAX, RAX_H,
RDX, RDX_H,
RDX, RDX_H,
RDI, RDI_H,
RSI, RSI_H,
RCX, RCX_H,
@ -536,7 +536,11 @@ source %{
#define __ _masm.
static int clear_avx_size() {
return (Compile::current()->max_vector_size() > 16) ? 3 : 0; // vzeroupper
if(UseAVX > 2) {
return 0; // vzeroupper is ignored
} else {
return (Compile::current()->max_vector_size() > 16) ? 3 : 0; // vzeroupper
}
}
// !!!!! Special hack to get all types of calls to specify the byte offset
@ -545,7 +549,7 @@ static int clear_avx_size() {
int MachCallStaticJavaNode::ret_addr_offset()
{
int offset = 5; // 5 bytes from start of call to where return address points
offset += clear_avx_size();
offset += clear_avx_size();
return offset;
}
@ -860,7 +864,7 @@ void MachPrologNode::format(PhaseRegAlloc* ra_, outputStream* st) const {
st->print("subq rsp, #%d\t# Create frame",framesize);
st->print("\n\t");
framesize -= wordSize;
st->print("movq [rsp + #%d], rbp\t# Save rbp",framesize);
st->print("movq [rsp + #%d], rbp\t# Save rbp",framesize);
if (PreserveFramePointer) {
st->print("\n\t");
st->print("movq rbp, [rsp + #%d]\t# Save the caller's SP into rbp", (framesize + wordSize));
@ -1070,6 +1074,11 @@ static void vec_stack_to_stack_helper(CodeBuffer *cbuf, int src_offset,
__ vmovdqu(xmm0, Address(rsp, src_offset));
__ vmovdqu(Address(rsp, dst_offset), xmm0);
__ vmovdqu(xmm0, Address(rsp, -32));
case Op_VecZ:
__ evmovdqu(Address(rsp, -64), xmm0, 2);
__ evmovdqu(xmm0, Address(rsp, src_offset), 2);
__ evmovdqu(Address(rsp, dst_offset), xmm0, 2);
__ evmovdqu(xmm0, Address(rsp, -64), 2);
break;
default:
ShouldNotReachHere();
@ -1103,6 +1112,13 @@ static void vec_stack_to_stack_helper(CodeBuffer *cbuf, int src_offset,
"vmovdqu xmm0, [rsp - #32]",
src_offset, dst_offset);
break;
case Op_VecZ:
st->print("vmovdqu [rsp - #64], xmm0\t# 512-bit mem-mem spill\n\t"
"vmovdqu xmm0, [rsp + #%d]\n\t"
"vmovdqu [rsp + #%d], xmm0\n\t"
"vmovdqu xmm0, [rsp - #64]",
src_offset, dst_offset);
break;
default:
ShouldNotReachHere();
}
@ -1136,7 +1152,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer* cbuf,
if (bottom_type()->isa_vect() != NULL) {
uint ireg = ideal_reg();
assert((src_first_rc != rc_int && dst_first_rc != rc_int), "sanity");
assert((ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY), "sanity");
assert((ireg == Op_VecS || ireg == Op_VecD || ireg == Op_VecX || ireg == Op_VecY || ireg == Op_VecZ ), "sanity");
if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) {
// mem -> mem
int src_offset = ra_->reg2offset(src_first);
@ -1573,7 +1589,7 @@ uint MachUEPNode::size(PhaseRegAlloc* ra_) const
return MachNode::size(ra_); // too many variables; just compute it
// the hard way
}
//=============================================================================
@ -2832,7 +2848,7 @@ frame
RAX_H_num // Op_RegL
};
// Excluded flags and vector registers.
assert(ARRAY_SIZE(hi) == _last_machine_leaf - 5, "missing type");
assert(ARRAY_SIZE(hi) == _last_machine_leaf - 6, "missing type");
return OptoRegPair(hi[ideal_reg], lo[ideal_reg]);
%}
%}
@ -3335,7 +3351,7 @@ operand no_rax_rdx_RegI()
// Pointer Register
operand any_RegP()
%{
constraint(ALLOC_IN_RC(any_reg));
constraint(ALLOC_IN_RC(any_reg));
match(RegP);
match(rax_RegP);
match(rbx_RegP);
@ -3589,20 +3605,51 @@ operand rFlagsRegUCF() %{
%}
// Float register operands
operand regF()
%{
constraint(ALLOC_IN_RC(float_reg));
match(RegF);
operand regF() %{
constraint(ALLOC_IN_RC(float_reg));
match(RegF);
format %{ %}
interface(REG_INTER);
%}
// Double register operands
operand regD() %{
constraint(ALLOC_IN_RC(double_reg));
match(RegD);
format %{ %}
interface(REG_INTER);
%}
// Vectors
operand vecS() %{
constraint(ALLOC_IN_RC(vectors_reg));
match(VecS);
format %{ %}
interface(REG_INTER);
%}
// Double register operands
operand regD()
%{
constraint(ALLOC_IN_RC(double_reg));
match(RegD);
operand vecD() %{
constraint(ALLOC_IN_RC(vectord_reg));
match(VecD);
format %{ %}
interface(REG_INTER);
%}
operand vecX() %{
constraint(ALLOC_IN_RC(vectorx_reg));
match(VecX);
format %{ %}
interface(REG_INTER);
%}
operand vecY() %{
constraint(ALLOC_IN_RC(vectory_reg));
match(VecY);
format %{ %}
interface(REG_INTER);
@ -4947,7 +4994,7 @@ instruct loadI2L_immU31(rRegL dst, memory mem, immU31 mask, rFlagsReg cr) %{
%}
// Load Unsigned Integer into Long Register
instruct loadUI2L(rRegL dst, memory mem, immL_32bits mask)
instruct loadUI2L(rRegL dst, memory mem, immL_32bits mask)
%{
match(Set dst (AndL (ConvI2L (LoadI mem)) mask));
@ -10374,7 +10421,7 @@ instruct rep_stos(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy,
format %{ "xorq rax, rax\t# ClearArray:\n\t"
"rep stosq\t# Store rax to *rdi++ while rcx--" %}
ins_encode %{
ins_encode %{
__ clear_mem($base$$Register, $cnt$$Register, $zero$$Register);
%}
ins_pipe(pipe_slow);
@ -10389,7 +10436,7 @@ instruct rep_fast_stosb(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dum
format %{ "xorq rax, rax\t# ClearArray:\n\t"
"shlq rcx,3\t# Convert doublewords to bytes\n\t"
"rep stosb\t# Store rax to *rdi++ while rcx--" %}
ins_encode %{
ins_encode %{
__ clear_mem($base$$Register, $cnt$$Register, $zero$$Register);
%}
ins_pipe( pipe_slow );

View File

@ -26,6 +26,8 @@
#ifndef CPU_ZERO_VM_ENTRY_ZERO_HPP
#define CPU_ZERO_VM_ENTRY_ZERO_HPP
#include "interpreter/cppInterpreter.hpp"
class ZeroEntry {
public:
ZeroEntry() {

View File

@ -25,6 +25,8 @@
#include "precompiled.hpp"
#include "assembler_zero.inline.hpp"
#include "entry_zero.hpp"
#include "interpreter/cppInterpreter.hpp"
#include "memory/resourceArea.hpp"
#include "nativeInst_zero.hpp"
#include "oops/oop.inline.hpp"

View File

@ -3474,25 +3474,69 @@ char* os::Linux::reserve_memory_special_huge_tlbfs_only(size_t bytes,
return addr;
}
// Helper for os::Linux::reserve_memory_special_huge_tlbfs_mixed().
// Allocate (using mmap, NO_RESERVE, with small pages) at either a given request address
// (req_addr != NULL) or with a given alignment.
// - bytes shall be a multiple of alignment.
// - req_addr can be NULL. If not NULL, it must be a multiple of alignment.
// - alignment sets the alignment at which memory shall be allocated.
// It must be a multiple of allocation granularity.
// Returns address of memory or NULL. If req_addr was not NULL, will only return
// req_addr or NULL.
static char* anon_mmap_aligned(size_t bytes, size_t alignment, char* req_addr) {
size_t extra_size = bytes;
if (req_addr == NULL && alignment > 0) {
extra_size += alignment;
}
char* start = (char*) ::mmap(req_addr, extra_size, PROT_NONE,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,
-1, 0);
if (start == MAP_FAILED) {
start = NULL;
} else {
if (req_addr != NULL) {
if (start != req_addr) {
::munmap(start, extra_size);
start = NULL;
}
} else {
char* const start_aligned = (char*) align_ptr_up(start, alignment);
char* const end_aligned = start_aligned + bytes;
char* const end = start + extra_size;
if (start_aligned > start) {
::munmap(start, start_aligned - start);
}
if (end_aligned < end) {
::munmap(end_aligned, end - end_aligned);
}
start = start_aligned;
}
}
return start;
}
// Reserve memory using mmap(MAP_HUGETLB).
// - bytes shall be a multiple of alignment.
// - req_addr can be NULL. If not NULL, it must be a multiple of alignment.
// - alignment sets the alignment at which memory shall be allocated.
// It must be a multiple of allocation granularity.
// Returns address of memory or NULL. If req_addr was not NULL, will only return
// req_addr or NULL.
char* os::Linux::reserve_memory_special_huge_tlbfs_mixed(size_t bytes,
size_t alignment,
char* req_addr,
bool exec) {
size_t large_page_size = os::large_page_size();
assert(bytes >= large_page_size, "Shouldn't allocate large pages for small sizes");
// Allocate small pages.
assert(is_ptr_aligned(req_addr, alignment), "Must be");
assert(is_size_aligned(bytes, alignment), "Must be");
char* start;
if (req_addr != NULL) {
assert(is_ptr_aligned(req_addr, alignment), "Must be");
assert(is_size_aligned(bytes, alignment), "Must be");
start = os::reserve_memory(bytes, req_addr);
assert(start == NULL || start == req_addr, "Must be");
} else {
start = os::reserve_memory_aligned(bytes, alignment);
}
// First reserve - but not commit - the address range in small pages.
char* const start = anon_mmap_aligned(bytes, alignment, req_addr);
if (start == NULL) {
return NULL;
@ -3500,13 +3544,6 @@ char* os::Linux::reserve_memory_special_huge_tlbfs_mixed(size_t bytes,
assert(is_ptr_aligned(start, alignment), "Must be");
if (MemTracker::tracking_level() > NMT_minimal) {
// os::reserve_memory_special will record this memory area.
// Need to release it here to prevent overlapping reservations.
Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
tkr.record((address)start, bytes);
}
char* end = start + bytes;
// Find the regions of the allocated chunk that can be promoted to large pages.
@ -3526,9 +3563,9 @@ char* os::Linux::reserve_memory_special_huge_tlbfs_mixed(size_t bytes,
int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
void* result;
// Commit small-paged leading area.
if (start != lp_start) {
result = ::mmap(start, lp_start - start, prot,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
@ -3539,11 +3576,12 @@ char* os::Linux::reserve_memory_special_huge_tlbfs_mixed(size_t bytes,
}
}
// Commit large-paged area.
result = ::mmap(lp_start, lp_bytes, prot,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED|MAP_HUGETLB,
-1, 0);
if (result == MAP_FAILED) {
warn_on_large_pages_failure(req_addr, bytes, errno);
warn_on_large_pages_failure(lp_start, lp_bytes, errno);
// If the mmap above fails, the large pages region will be unmapped and we
// have regions before and after with small pages. Release these regions.
//
@ -3556,6 +3594,7 @@ char* os::Linux::reserve_memory_special_huge_tlbfs_mixed(size_t bytes,
return NULL;
}
// Commit small-paged trailing area.
if (lp_end != end) {
result = ::mmap(lp_end, end - lp_end, prot,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED,
@ -3575,7 +3614,7 @@ char* os::Linux::reserve_memory_special_huge_tlbfs(size_t bytes,
bool exec) {
assert(UseLargePages && UseHugeTLBFS, "only for Huge TLBFS large pages");
assert(is_ptr_aligned(req_addr, alignment), "Must be");
assert(is_power_of_2(alignment), "Must be");
assert(is_size_aligned(alignment, os::vm_allocation_granularity()), "Must be");
assert(is_power_of_2(os::large_page_size()), "Must be");
assert(bytes >= os::large_page_size(), "Shouldn't allocate large pages for small sizes");
@ -4760,8 +4799,8 @@ jint os::init_2(void) {
FLAG_IS_DEFAULT(UseSHM) &&
FLAG_IS_DEFAULT(UseHugeTLBFS)) {
UseLargePages = false;
} else {
warning("UseNUMA is not fully compatible with SHM/HugeTLBFS large pages, disabling adaptive resizing");
} else if (UseAdaptiveSizePolicy || UseAdaptiveNUMAChunkSizing) {
warning("UseNUMA is not fully compatible with SHM/HugeTLBFS large pages, disabling adaptive resizing (-XX:-UseAdaptiveSizePolicy -XX:-UseAdaptiveNUMAChunkSizing)");
UseAdaptiveSizePolicy = false;
UseAdaptiveNUMAChunkSizing = false;
}
@ -6086,47 +6125,100 @@ class TestReserveMemorySpecial : AllStatic {
}
}
static void test_reserve_memory_special_huge_tlbfs_mixed(size_t size, size_t alignment) {
if (!UseHugeTLBFS) {
return;
}
test_log("test_reserve_memory_special_huge_tlbfs_mixed(" SIZE_FORMAT ", " SIZE_FORMAT ")",
size, alignment);
assert(size >= os::large_page_size(), "Incorrect input to test");
char* addr = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, NULL, false);
if (addr != NULL) {
small_page_write(addr, size);
os::Linux::release_memory_special_huge_tlbfs(addr, size);
}
}
static void test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(size_t size) {
size_t lp = os::large_page_size();
size_t ag = os::vm_allocation_granularity();
for (size_t alignment = ag; is_size_aligned(size, alignment); alignment *= 2) {
test_reserve_memory_special_huge_tlbfs_mixed(size, alignment);
}
}
static void test_reserve_memory_special_huge_tlbfs_mixed() {
size_t lp = os::large_page_size();
size_t ag = os::vm_allocation_granularity();
test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp);
test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp + ag);
test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp + lp / 2);
test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 2);
test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 2 + ag);
test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 2 - ag);
test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 2 + lp / 2);
test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 10);
test_reserve_memory_special_huge_tlbfs_mixed_all_alignments(lp * 10 + lp / 2);
// sizes to test
const size_t sizes[] = {
lp, lp + ag, lp + lp / 2, lp * 2,
lp * 2 + ag, lp * 2 - ag, lp * 2 + lp / 2,
lp * 10, lp * 10 + lp / 2
};
const int num_sizes = sizeof(sizes) / sizeof(size_t);
// For each size/alignment combination, we test three scenarios:
// 1) with req_addr == NULL
// 2) with a non-null req_addr at which we expect to successfully allocate
// 3) with a non-null req_addr which contains a pre-existing mapping, at which we
// expect the allocation to either fail or to ignore req_addr
// Pre-allocate two areas; they shall be as large as the largest allocation
// and aligned to the largest alignment we will be testing.
const size_t mapping_size = sizes[num_sizes - 1] * 2;
char* const mapping1 = (char*) ::mmap(NULL, mapping_size,
PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,
-1, 0);
assert(mapping1 != MAP_FAILED, "should work");
char* const mapping2 = (char*) ::mmap(NULL, mapping_size,
PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE,
-1, 0);
assert(mapping2 != MAP_FAILED, "should work");
// Unmap the first mapping, but leave the second mapping intact: the first
// mapping will serve as a value for a "good" req_addr (case 2). The second
// mapping, still intact, as "bad" req_addr (case 3).
::munmap(mapping1, mapping_size);
// Case 1
test_log("%s, req_addr NULL:", __FUNCTION__);
test_log("size align result");
for (int i = 0; i < num_sizes; i++) {
const size_t size = sizes[i];
for (size_t alignment = ag; is_size_aligned(size, alignment); alignment *= 2) {
char* p = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, NULL, false);
test_log(SIZE_FORMAT_HEX " " SIZE_FORMAT_HEX " -> " PTR_FORMAT " %s",
size, alignment, p, (p != NULL ? "" : "(failed)"));
if (p != NULL) {
assert(is_ptr_aligned(p, alignment), "must be");
small_page_write(p, size);
os::Linux::release_memory_special_huge_tlbfs(p, size);
}
}
}
// Case 2
test_log("%s, req_addr non-NULL:", __FUNCTION__);
test_log("size align req_addr result");
for (int i = 0; i < num_sizes; i++) {
const size_t size = sizes[i];
for (size_t alignment = ag; is_size_aligned(size, alignment); alignment *= 2) {
char* const req_addr = (char*) align_ptr_up(mapping1, alignment);
char* p = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, req_addr, false);
test_log(SIZE_FORMAT_HEX " " SIZE_FORMAT_HEX " " PTR_FORMAT " -> " PTR_FORMAT " %s",
size, alignment, req_addr, p,
((p != NULL ? (p == req_addr ? "(exact match)" : "") : "(failed)")));
if (p != NULL) {
assert(p == req_addr, "must be");
small_page_write(p, size);
os::Linux::release_memory_special_huge_tlbfs(p, size);
}
}
}
// Case 3
test_log("%s, req_addr non-NULL with preexisting mapping:", __FUNCTION__);
test_log("size align req_addr result");
for (int i = 0; i < num_sizes; i++) {
const size_t size = sizes[i];
for (size_t alignment = ag; is_size_aligned(size, alignment); alignment *= 2) {
char* const req_addr = (char*) align_ptr_up(mapping2, alignment);
char* p = os::Linux::reserve_memory_special_huge_tlbfs_mixed(size, alignment, req_addr, false);
test_log(SIZE_FORMAT_HEX " " SIZE_FORMAT_HEX " " PTR_FORMAT " -> " PTR_FORMAT " %s",
size, alignment, req_addr, p,
((p != NULL ? "" : "(failed)")));
// as the area around req_addr contains already existing mappings, the API should always
// return NULL (as per contract, it cannot return another address)
assert(p == NULL, "must be");
}
}
::munmap(mapping2, mapping_size);
}
static void test_reserve_memory_special_huge_tlbfs() {

View File

@ -4,6 +4,13 @@
*** EDIT ../build.xml INSTEAD ***
-->
<project name="com.sun.hotspot.igv.svg-impl" basedir="..">
<fail message="Please build using Ant 1.7.1 or higher.">
<condition>
<not>
<antversion atleast="1.7.1"/>
</not>
</condition>
</fail>
<property file="nbproject/private/suite-private.properties"/>
<property file="nbproject/suite.properties"/>
<fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
@ -16,13 +23,21 @@
<property name="@{name}" value="${@{value}}"/>
</sequential>
</macrodef>
<macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
<attribute name="property"/>
<attribute name="value"/>
<sequential>
<property name="@{property}" value="@{value}"/>
</sequential>
</macrodef>
<property file="${user.properties.file}"/>
<nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<nbmproject2:property name="netbeans.dest.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<fail message="You must define 'nbplatform.${nbplatform.active}.harness.dir'">
<nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
<fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
<condition>
<not>
<available file="${harness.dir}" type="dir"/>
<contains string="${cluster.path.evaluated}" substring="platform"/>
</not>
</condition>
</fail>

View File

@ -1,8 +1,5 @@
build.xml.data.CRC32=ebcf0422
build.xml.script.CRC32=d7a2678d
build.xml.stylesheet.CRC32=79c3b980
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
nbproject/build-impl.xml.data.CRC32=ebcf0422
nbproject/build-impl.xml.script.CRC32=57997f94
nbproject/build-impl.xml.stylesheet.CRC32=deb65f65
nbproject/build-impl.xml.script.CRC32=42ef3ff6
nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1

View File

@ -1,2 +1,2 @@
javac.source=1.5
javac.compilerargs=-Xlint -Xlint:-serial
javac.source=1.7
javac.compilerargs=-Xlint -Xlint:-serial

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -25,40 +25,58 @@ package com.sun.hotspot.igv.svg;
import java.awt.Graphics2D;
import java.io.Writer;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import org.w3c.dom.DOMImplementation;
/**
*
* Utility class
* @author Thomas Wuerthinger
*/
public class BatikSVG {
private static Constructor SVGGraphics2DConstructor;
private static Method Method_stream;
private static Method Method_createDefault;
private static Method Method_getDOMImplementation;
private static Method Method_setEmbeddedFontsOn;
private BatikSVG() {
}
private static Constructor SVGGraphics2DConstructor;
private static Method streamMethod;
private static Method createDefaultMethod;
private static Method getDOMImplementationMethod;
private static Method setEmbeddedFontsOnMethod;
private static Class<?> classSVGGraphics2D;
/**
* Creates a graphics object that allows to be exported to SVG data using the {@link #printToStream(Graphics2D, Writer, boolean) printToStream} method.
* @return the newly created Graphics2D object or null if the library does not exist
*/
public static Graphics2D createGraphicsObject() {
try {
if (SVGGraphics2DConstructor == null) {
ClassLoader cl = BatikSVG.class.getClassLoader();
Class Class_GenericDOMImplementation = cl.loadClass("org.apache.batik.dom.GenericDOMImplementation");
Class Class_SVGGeneratorContext = cl.loadClass("org.apache.batik.svggen.SVGGeneratorContext");
Class Class_SVGGraphics2D = cl.loadClass("org.apache.batik.svggen.SVGGraphics2D");
Method_getDOMImplementation = Class_GenericDOMImplementation.getDeclaredMethod("getDOMImplementation", new Class[0]);
Method_createDefault = Class_SVGGeneratorContext.getDeclaredMethod("createDefault", new Class[]{org.w3c.dom.Document.class});
Method_setEmbeddedFontsOn = Class_SVGGeneratorContext.getDeclaredMethod("setEmbeddedFontsOn", new Class[]{boolean.class});
Method_stream = Class_SVGGraphics2D.getDeclaredMethod("stream", Writer.class, boolean.class);
SVGGraphics2DConstructor = Class_SVGGraphics2D.getConstructor(Class_SVGGeneratorContext, boolean.class);
String batikJar = System.getenv().get("IGV_BATIK_JAR");
if (batikJar == null) {
return null;
}
// Load batik in it's own class loader since some it's support jars interfere with the JDK
URL url = new File(batikJar).toURI().toURL();
ClassLoader cl = new URLClassLoader(new URL[] { url });
Class<?> classGenericDOMImplementation = cl.loadClass("org.apache.batik.dom.GenericDOMImplementation");
Class<?> classSVGGeneratorContext = cl.loadClass("org.apache.batik.svggen.SVGGeneratorContext");
classSVGGraphics2D = cl.loadClass("org.apache.batik.svggen.SVGGraphics2D");
getDOMImplementationMethod = classGenericDOMImplementation.getDeclaredMethod("getDOMImplementation", new Class[0]);
createDefaultMethod = classSVGGeneratorContext.getDeclaredMethod("createDefault", new Class[]{org.w3c.dom.Document.class});
setEmbeddedFontsOnMethod = classSVGGeneratorContext.getDeclaredMethod("setEmbeddedFontsOn", new Class[]{boolean.class});
streamMethod = classSVGGraphics2D.getDeclaredMethod("stream", Writer.class, boolean.class);
SVGGraphics2DConstructor = classSVGGraphics2D.getConstructor(classSVGGeneratorContext, boolean.class);
}
DOMImplementation dom = (DOMImplementation) Method_getDOMImplementation.invoke(null);
DOMImplementation dom = (DOMImplementation) getDOMImplementationMethod.invoke(null);
org.w3c.dom.Document document = dom.createDocument("http://www.w3.org/2000/svg", "svg", null);
Object ctx = Method_createDefault.invoke(null, document);
Method_setEmbeddedFontsOn.invoke(ctx, true);
Object ctx = createDefaultMethod.invoke(null, document);
setEmbeddedFontsOnMethod.invoke(ctx, true);
Graphics2D svgGenerator = (Graphics2D) SVGGraphics2DConstructor.newInstance(ctx, true);
return svgGenerator;
} catch (ClassNotFoundException e) {
@ -71,12 +89,22 @@ public class BatikSVG {
return null;
} catch (InstantiationException e) {
return null;
} catch (MalformedURLException e) {
return null;
}
}
/**
* Serializes a graphics object to a stream in SVG format.
* @param svgGenerator the graphics object. Only graphics objects created by the {@link #createGraphicsObject() createGraphicsObject} method are valid.
* @param stream the stream to which the data is written
* @param useCSS whether to use CSS styles in the SVG output
*/
public static void printToStream(Graphics2D svgGenerator, Writer stream, boolean useCSS) {
assert classSVGGraphics2D != null;
assert classSVGGraphics2D.isInstance(svgGenerator);
try {
Method_stream.invoke(svgGenerator, stream, useCSS);
streamMethod.invoke(svgGenerator, stream, useCSS);
} catch (IllegalAccessException e) {
assert false;
} catch (InvocationTargetException e) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -21,14 +21,9 @@
* questions.
*
*/
package com.sun.hotspot.igv.view;
/**
*
* @author Thomas Wuerthinger
* This package is used to proxy the SVG export functionality of the BatikSVG library. Reflection is used such that the
* library is optional and need not be present at build time.
*/
public class PreferenceConstants {
package com.sun.hotspot.igv.svg;
public static final String KEY_LINE_GENERATOR = "lineGenerator";
public static final String DEFAULT_LINE_GENERATOR = "com.sun.hotspot.igv.positioning.BasicLineGenerator";
}

View File

@ -1,6 +1,6 @@
Manifest-Version: 1.0
OpenIDE-Module: com.sun.hotspot.igv.bytecodes
OpenIDE-Module-Layer: com/sun/hotspot/igv/bytecodes/layer.xml
OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/bytecodes/Bundle.properties
OpenIDE-Module-Specification-Version: 1.0
Manifest-Version: 1.0
OpenIDE-Module: com.sun.hotspot.igv.bytecodes
OpenIDE-Module-Layer: com/sun/hotspot/igv/bytecodes/layer.xml
OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/bytecodes/Bundle.properties
OpenIDE-Module-Specification-Version: 1.0

View File

@ -1,2 +1,2 @@
javac.source=1.5
javac.compilerargs=-Xlint -Xlint:-serial
javac.source=1.7
javac.compilerargs=-Xlint -Xlint:-serial

View File

@ -14,13 +14,37 @@
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.hotspot.igv.graph</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.hotspot.igv.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.jdesktop.layout</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.4</specification-version>
<specification-version>1.16.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.awt</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.39.1</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -28,7 +52,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.11</specification-version>
<specification-version>6.34.1</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -36,7 +60,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.2.0.1</specification-version>
<specification-version>7.20.1</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -44,7 +68,15 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.9.0.1</specification-version>
<specification-version>8.14.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util.lookup</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.6.1</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -52,7 +84,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.16</specification-version>
<specification-version>6.39.1</specification-version>
</run-dependency>
</dependency>
</module-dependencies>

View File

@ -1,5 +1,5 @@
CTL_BytecodeViewAction=Open BytecodeView Window
CTL_BytecodeViewTopComponent=BytecodeView Window
CTL_BytecodeViewAction=Bytecode
CTL_BytecodeViewTopComponent=Bytecode
CTL_SelectBytecodesAction=Select nodes
HINT_BytecodeViewTopComponent=This is a BytecodeView window
HINT_BytecodeViewTopComponent=Shows the bytecode associated with the displayed graph.
OpenIDE-Module-Name=Bytecodes

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -29,14 +29,14 @@ import com.sun.hotspot.igv.data.InputNode;
import com.sun.hotspot.igv.data.Properties;
import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher;
import java.awt.Image;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.swing.Action;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.Utilities;
import org.openide.util.ImageUtilities;
/**
*
@ -49,29 +49,35 @@ public class BytecodeNode extends AbstractNode {
public BytecodeNode(InputBytecode bytecode, InputGraph graph, String bciValue) {
super(Children.LEAF);
this.setDisplayName(bytecode.getBci() + " " + bytecode.getName());
String displayName = bytecode.getBci() + " " + bytecode.getName() + " " + bytecode.getOperands();
bciValue = bytecode.getBci() + " " + bciValue;
bciValue = bciValue.trim();
Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<InputNode>(graph.getNodes());
Properties.PropertySelector<InputNode> selector = new Properties.PropertySelector<>(graph.getNodes());
StringPropertyMatcher matcher = new StringPropertyMatcher("bci", bciValue);
List<InputNode> nodeList = selector.selectMultiple(matcher);
if (nodeList.size() > 0) {
nodes = new HashSet<InputNode>();
nodes = new LinkedHashSet<>();
for (InputNode n : nodeList) {
nodes.add(n);
}
this.setDisplayName(this.getDisplayName() + " (" + nodes.size() + " nodes)");
displayName += " (" + nodes.size() + " nodes)";
}
if (bytecode.getComment() != null) {
displayName += " // " + bytecode.getComment();
}
this.setDisplayName(displayName);
}
@Override
public Image getIcon(int i) {
if (nodes != null) {
return Utilities.loadImage("com/sun/hotspot/igv/bytecodes/images/link.gif");
return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/link.png");
} else {
return Utilities.loadImage("com/sun/hotspot/igv/bytecodes/images/bytecode.gif");
return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/bytecode.png");
}
}
@ -91,6 +97,7 @@ public class BytecodeNode extends AbstractNode {
}
@Override
@SuppressWarnings("unchecked")
public <T extends Node.Cookie> T getCookie(Class<T> aClass) {
if (aClass == SelectBytecodesCookie.class && nodes != null) {
return (T) (new SelectBytecodesCookie(nodes));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -37,6 +37,7 @@ public class BytecodeViewAction extends AbstractAction {
super(NbBundle.getMessage(BytecodeViewAction.class, "CTL_BytecodeViewAction"));
}
@Override
public void actionPerformed(ActionEvent evt) {
TopComponent win = BytecodeViewTopComponent.findInstance();
win.open();

View File

@ -3,6 +3,8 @@
<Form version="1.3" maxVersion="1.3" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -26,6 +26,7 @@ package com.sun.hotspot.igv.bytecodes;
import com.sun.hotspot.igv.data.Group;
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.services.InputGraphProvider;
import com.sun.hotspot.igv.util.LookupHistory;
import java.awt.BorderLayout;
import java.io.Serializable;
import javax.swing.SwingUtilities;
@ -33,11 +34,7 @@ import org.openide.ErrorManager;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
import org.openide.explorer.view.BeanTreeView;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
import org.openide.util.*;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
@ -91,6 +88,7 @@ final class BytecodeViewTopComponent extends TopComponent implements ExplorerMan
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
/**
* Gets default instance. Do not use directly: reserved for *.settings files only,
* i.e. deserialization routines; otherwise you could get a non-deserialized instance.
@ -126,7 +124,7 @@ final class BytecodeViewTopComponent extends TopComponent implements ExplorerMan
@Override
public void componentOpened() {
Lookup.Template tpl = new Lookup.Template(Object.class);
Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<>(InputGraphProvider.class);
result = Utilities.actionsGlobalContext().lookup(tpl);
result.addLookupListener(this);
}
@ -147,23 +145,47 @@ final class BytecodeViewTopComponent extends TopComponent implements ExplorerMan
return PREFERRED_ID;
}
@Override
public ExplorerManager getExplorerManager() {
return manager;
}
@Override
public void requestActive() {
super.requestActive();
this.treeView.requestFocus();
}
@Override
public boolean requestFocus(boolean temporary) {
this.treeView.requestFocus();
return super.requestFocus(temporary);
}
@Override
protected boolean requestFocusInWindow(boolean temporary) {
this.treeView.requestFocus();
return super.requestFocusInWindow(temporary);
}
@Override
public void resultChanged(LookupEvent lookupEvent) {
final InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
if (p != null) {
final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
InputGraph graph = p.getGraph();
if (graph != null) {
Group g = graph.getGroup();
rootNode.update(graph, g.getMethod());
}
}
if (p != null) {
InputGraph graph = p.getGraph();
if (graph != null) {
Group g = graph.getGroup();
rootNode.update(graph, g.getMethod());
return;
}
}
rootNode.update(null, null);
}
});
}
}
final static class ResolvableHelper implements Serializable {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -30,7 +30,7 @@ import java.awt.Image;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.Utilities;
import org.openide.util.ImageUtilities;
/**
*
@ -38,7 +38,7 @@ import org.openide.util.Utilities;
*/
public class MethodNode extends AbstractNode {
private static class MethodNodeChildren extends Children.Keys {
private static class MethodNodeChildren extends Children.Keys<InputBytecode> {
private InputMethod method;
private InputGraph graph;
@ -50,9 +50,8 @@ public class MethodNode extends AbstractNode {
this.graph = graph;
}
protected Node[] createNodes(Object object) {
assert object instanceof InputBytecode;
InputBytecode bc = (InputBytecode) object;
@Override
protected Node[] createNodes(InputBytecode bc) {
if (bc.getInlined() == null) {
return new Node[]{new BytecodeNode(bc, graph, bciString)};
} else {
@ -84,7 +83,7 @@ public class MethodNode extends AbstractNode {
@Override
public Image getIcon(int i) {
return Utilities.loadImage("com/sun/hotspot/igv/bytecodes/images/method.gif");
return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/method.png");
}
@Override

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -24,9 +24,9 @@
package com.sun.hotspot.igv.bytecodes;
import com.sun.hotspot.igv.data.services.InputGraphProvider;
import com.sun.hotspot.igv.util.LookupHistory;
import org.openide.nodes.Node;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.actions.CookieAction;
@ -36,22 +36,26 @@ import org.openide.util.actions.CookieAction;
*/
public final class SelectBytecodesAction extends CookieAction {
@Override
protected void performAction(Node[] activatedNodes) {
SelectBytecodesCookie c = activatedNodes[0].getCookie(SelectBytecodesCookie.class);
InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
if (p != null) {
p.setSelectedNodes(c.getNodes());
}
}
@Override
protected int mode() {
return CookieAction.MODE_EXACTLY_ONE;
}
@Override
public String getName() {
return NbBundle.getMessage(SelectBytecodesAction.class, "CTL_SelectBytecodesAction");
}
@Override
protected Class[] cookieClasses() {
return new Class[]{
SelectBytecodesCookie.class
@ -64,6 +68,7 @@ public final class SelectBytecodesAction extends CookieAction {
putValue("noIconInMenu", Boolean.TRUE);
}
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
@ -73,3 +78,4 @@ public final class SelectBytecodesAction extends CookieAction {
return false;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

View File

@ -1,6 +1,6 @@
Manifest-Version: 1.0
OpenIDE-Module: com.sun.hotspot.igv.controlflow
OpenIDE-Module-Layer: com/sun/hotspot/igv/controlflow/layer.xml
OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/controlflow/Bundle.properties
OpenIDE-Module-Specification-Version: 1.0
Manifest-Version: 1.0
OpenIDE-Module: com.sun.hotspot.igv.controlflow
OpenIDE-Module-Layer: com/sun/hotspot/igv/controlflow/layer.xml
OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/controlflow/Bundle.properties
OpenIDE-Module-Specification-Version: 1.0

View File

@ -30,13 +30,21 @@
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.hotspot.igv.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.jdesktop.layout</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.4</specification-version>
<specification-version>1.16.1</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -52,7 +60,15 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.9.0.1</specification-version>
<specification-version>8.14.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util.lookup</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.6.1</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -26,7 +26,9 @@ package com.sun.hotspot.igv.controlflow;
import com.sun.hotspot.igv.data.InputBlockEdge;
import com.sun.hotspot.igv.layout.Link;
import com.sun.hotspot.igv.layout.Port;
import java.awt.BasicStroke;
import java.awt.Point;
import java.awt.Stroke;
import java.util.ArrayList;
import java.util.List;
import org.netbeans.api.visual.widget.ConnectionWidget;
@ -37,12 +39,19 @@ import org.netbeans.api.visual.widget.ConnectionWidget;
*/
public class BlockConnectionWidget extends ConnectionWidget implements Link {
private static final Stroke NORMAL_STROKE = new BasicStroke(1.0f);
private static final Stroke BOLD_STROKE = new BasicStroke(2.5f);
private static final Stroke DASHED_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[]{5, 5}, 0);
private static final Stroke BOLD_DASHED_STROKE = new BasicStroke(2.5f, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10.0f, new float[]{5, 5}, 0);
private BlockWidget from;
private BlockWidget to;
private Port inputSlot;
private Port outputSlot;
private List<Point> points;
private InputBlockEdge edge;
private boolean isDashed = false;
private boolean isBold = false;
public BlockConnectionWidget(ControlFlowScene scene, InputBlockEdge edge) {
super(scene);
@ -67,6 +76,30 @@ public class BlockConnectionWidget extends ConnectionWidget implements Link {
return outputSlot;
}
public void setBold(boolean bold) {
this.isBold = bold;
updateStroke();
}
public void setDashed(boolean dashed) {
this.isDashed = dashed;
updateStroke();
}
private void updateStroke() {
Stroke stroke = NORMAL_STROKE;
if (isBold) {
if (isDashed) {
stroke = BOLD_DASHED_STROKE;
} else {
stroke = BOLD_STROKE;
}
} else if (isDashed) {
stroke = DASHED_STROKE;
}
setStroke(stroke);
}
public void setControlPoints(List<Point> p) {
this.points = p;
}
@ -80,4 +113,9 @@ public class BlockConnectionWidget extends ConnectionWidget implements Link {
public String toString() {
return "Connection[ " + from.toString() + " - " + to.toString() + "]";
}
@Override
public boolean isVIP() {
return isBold;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -31,6 +31,7 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Point;
import java.awt.Rectangle;
import org.netbeans.api.visual.border.BorderFactory;
import org.netbeans.api.visual.model.ObjectState;
import org.netbeans.api.visual.widget.LabelWidget;
@ -41,13 +42,13 @@ import org.netbeans.api.visual.widget.LabelWidget;
*/
public class BlockWidget extends LabelWidget implements Vertex {
public static final Dimension SIZE = new Dimension(20, 20);
public static final Dimension MIN_SIZE = new Dimension(20, 20);
private InputBlock block;
private Port inputSlot;
private Port outputSlot;
private Cluster cluster;
private boolean root;
private static final Font font = new Font(Font.SERIF, Font.PLAIN, 12);
private static final Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 12);
private static final Font boldFont = font.deriveFont(Font.BOLD);
public static final Color NORMAL_FOREGROUND_COLOR = Color.BLACK;
public static final Color HOVER_FOREGROUND_COLOR = Color.BLUE;
@ -59,29 +60,24 @@ public class BlockWidget extends LabelWidget implements Vertex {
this.setLabel(block.getName());
this.setForeground(NORMAL_FOREGROUND_COLOR);
this.setBorder(BorderFactory.createLineBorder(1, NORMAL_FOREGROUND_COLOR));
this.setMinimumSize(SIZE);
this.setMaximumSize(SIZE);
this.setMinimumSize(MIN_SIZE);
this.setFont(font);
this.setAlignment(Alignment.CENTER);
final BlockWidget widget = this;
inputSlot = new Port() {
public Point getRelativePosition() {
return new Point((int) (SIZE.getWidth() / 2), (int) (SIZE.getHeight() / 2));
return new Point((int) (getSize().getWidth() / 2), (int) (getSize().getHeight() / 2));
}
public Vertex getVertex() {
return widget;
}
};
outputSlot = new Port() {
public Point getRelativePosition() {
return new Point((int) (SIZE.getWidth() / 2), (int) (SIZE.getHeight() / 2));
return new Point((int) (getSize().getWidth() / 2), (int) (getSize().getHeight() / 2));
}
public Vertex getVertex() {
return widget;
}
@ -101,7 +97,12 @@ public class BlockWidget extends LabelWidget implements Vertex {
}
public Dimension getSize() {
return SIZE;
Rectangle bounds = getBounds();
if (bounds != null) {
return bounds.getSize();
} else {
return MIN_SIZE;
}
}
public void setPosition(Point p) {

View File

@ -1,4 +1,4 @@
CTL_ControlFlowAction=Open ControlFlow Window
CTL_ControlFlowTopComponent=ControlFlow Window
HINT_ControlFlowTopComponent=This is a ControlFlow window
CTL_ControlFlowAction=Control Flow
CTL_ControlFlowTopComponent=Control Flow
HINT_ControlFlowTopComponent=Shows the blocks of the current graph.
OpenIDE-Module-Name=ControlFlow

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -23,17 +23,17 @@
*/
package com.sun.hotspot.igv.controlflow;
import com.sun.hotspot.igv.data.InputBlock;
import com.sun.hotspot.igv.data.InputBlockEdge;
import com.sun.hotspot.igv.data.InputBlock;
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.services.InputGraphProvider;
import com.sun.hotspot.igv.data.InputNode;
import com.sun.hotspot.igv.util.LookupHistory;
import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Set;
import javax.swing.BorderFactory;
import org.netbeans.api.visual.action.ActionFactory;
@ -44,15 +44,14 @@ import org.netbeans.api.visual.action.SelectProvider;
import org.netbeans.api.visual.action.WidgetAction;
import org.netbeans.api.visual.anchor.AnchorFactory;
import org.netbeans.api.visual.anchor.AnchorShape;
import org.netbeans.api.visual.layout.LayoutFactory;
import org.netbeans.api.visual.router.RouterFactory;
import org.netbeans.api.visual.widget.LayerWidget;
import org.netbeans.api.visual.widget.Widget;
import org.netbeans.api.visual.graph.GraphScene;
import org.netbeans.api.visual.graph.layout.GraphLayout;
import org.netbeans.api.visual.layout.LayoutFactory;
import org.netbeans.api.visual.layout.SceneLayout;
import org.netbeans.api.visual.widget.ConnectionWidget;
import org.openide.util.Lookup;
/**
*
@ -61,13 +60,12 @@ import org.openide.util.Lookup;
public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> implements SelectProvider, MoveProvider, RectangularSelectDecorator, RectangularSelectProvider {
private HashSet<BlockWidget> selection;
private HashMap<InputBlock, BlockWidget> blockMap;
private InputGraph oldGraph;
private LayerWidget edgeLayer;
private LayerWidget mainLayer;
private LayerWidget selectLayer;
private WidgetAction hoverAction = this.createWidgetHoverAction();
private WidgetAction selectAction = ActionFactory.createSelectAction(this);
private WidgetAction selectAction = new DoubleClickSelectAction(this);
private WidgetAction moveAction = ActionFactory.createMoveAction(null, this);
public ControlFlowScene() {
@ -111,27 +109,21 @@ public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> imp
addNode(b);
}
for (InputBlock b : g.getBlocks()) {
for (InputBlockEdge e : b.getOutputs()) {
addEdge(e);
assert g.getBlocks().contains(e.getFrom());
assert g.getBlocks().contains(e.getTo());
this.setEdgeSource(e, e.getFrom());
this.setEdgeTarget(e, e.getTo());
}
for (InputBlockEdge e : g.getBlockEdges()) {
addEdge(e);
assert g.getBlocks().contains(e.getFrom());
assert g.getBlocks().contains(e.getTo());
this.setEdgeSource(e, e.getFrom());
this.setEdgeTarget(e, e.getTo());
}
GraphLayout layout = new HierarchicalGraphLayout();//GridGraphLayout();
GraphLayout<InputBlock, InputBlockEdge> layout = new HierarchicalGraphLayout<InputBlock, InputBlockEdge>();//GridGraphLayout();
SceneLayout sceneLayout = LayoutFactory.createSceneGraphLayout(this, layout);
sceneLayout.invokeLayout();
this.validate();
}
public BlockWidget getBlockWidget(InputBlock b) {
return blockMap.get(b);
}
public void clearSelection() {
for (BlockWidget w : selection) {
w.setState(w.getState().deriveSelected(false));
@ -141,7 +133,7 @@ public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> imp
}
public void selectionChanged() {
InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
if (p != null) {
Set<InputNode> inputNodes = new HashSet<InputNode>();
for (BlockWidget w : selection) {
@ -204,15 +196,19 @@ public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> imp
}
public void setNewLocation(Widget widget, Point location) {
Point originalLocation = getOriginalLocation(widget);
int xOffset = location.x - originalLocation.x;
int yOffset = location.y - originalLocation.y;
for (Widget w : this.selection) {
Point p = new Point(w.getPreferredLocation());
p.translate(xOffset, yOffset);
w.setPreferredLocation(p);
if (selection.contains(widget)) {
// move entire selection
Point originalLocation = getOriginalLocation(widget);
int xOffset = location.x - originalLocation.x;
int yOffset = location.y - originalLocation.y;
for (Widget w : selection) {
Point p = new Point(w.getPreferredLocation());
p.translate(xOffset, yOffset);
w.setPreferredLocation(p);
}
} else {
widget.setPreferredLocation(location);
}
}
public Widget createSelectionWidget() {
@ -271,7 +267,15 @@ public class ControlFlowScene extends GraphScene<InputBlock, InputBlockEdge> imp
}
protected Widget attachEdgeWidget(InputBlockEdge edge) {
ConnectionWidget w = new BlockConnectionWidget(this, edge);
BlockConnectionWidget w = new BlockConnectionWidget(this, edge);
switch (edge.getState()) {
case NEW:
w.setBold(true);
break;
case DELETED:
w.setDashed(true);
break;
}
w.setRouter(RouterFactory.createDirectRouter());
w.setTargetAnchorShape(AnchorShape.TRIANGLE_FILLED);
edgeLayer.addChild(w);

View File

@ -3,6 +3,8 @@
<Form version="1.3" maxVersion="1.3" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -25,6 +25,7 @@ package com.sun.hotspot.igv.controlflow;
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.services.InputGraphProvider;
import com.sun.hotspot.igv.util.LookupHistory;
import java.awt.BorderLayout;
import java.io.Serializable;
import javax.swing.JScrollPane;
@ -63,17 +64,7 @@ final class ControlFlowTopComponent extends TopComponent implements LookupListen
this.add(panel, BorderLayout.CENTER);
}
@Override
public void requestFocus() {
super.requestFocus();
scene.getView().requestFocus();
}
@Override
public boolean requestFocusInWindow() {
super.requestFocusInWindow();
return scene.getView().requestFocusInWindow();
}
/** This method is called from within the constructor to
* initialize the form.
@ -96,6 +87,7 @@ final class ControlFlowTopComponent extends TopComponent implements LookupListen
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
// End of variables declaration//GEN-END:variables
/**
* Gets default instance. Do not use directly: reserved for *.settings files only,
* i.e. deserialization routines; otherwise you could get a non-deserialized instance.
@ -131,7 +123,7 @@ final class ControlFlowTopComponent extends TopComponent implements LookupListen
@Override
public void componentOpened() {
Lookup.Template tpl = new Lookup.Template(Object.class);
Lookup.Template<InputGraphProvider> tpl = new Lookup.Template<InputGraphProvider>(InputGraphProvider.class);
result = Utilities.actionsGlobalContext().lookup(tpl);
result.addLookupListener(this);
}
@ -143,16 +135,16 @@ final class ControlFlowTopComponent extends TopComponent implements LookupListen
}
public void resultChanged(LookupEvent lookupEvent) {
final InputGraphProvider p = Lookup.getDefault().lookup(InputGraphProvider.class);
final InputGraphProvider p = LookupHistory.getLast(InputGraphProvider.class);//Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
if (p != null) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
InputGraph g = p.getGraph();
if (g != null) {
scene.setGraph(g);
}
}
InputGraph g = p.getGraph();
if (g != null) {
scene.setGraph(g);
}
}
});
}
}
@ -169,8 +161,8 @@ final class ControlFlowTopComponent extends TopComponent implements LookupListen
@Override
public void requestActive() {
scene.getView().requestFocusInWindow();
super.requestActive();
scene.getView().requestFocus();
}
final static class ResolvableHelper implements Serializable {

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2011, 2015, 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 com.sun.hotspot.igv.controlflow;
import java.awt.Point;
import java.awt.event.MouseEvent;
import org.netbeans.api.visual.action.SelectProvider;
import org.netbeans.api.visual.action.WidgetAction;
import org.netbeans.api.visual.widget.Widget;
/**
* Selection action that acts on double-click only. Does not support aiming.
*
* @author Peter Hofer
*/
public class DoubleClickSelectAction extends WidgetAction.LockedAdapter {
private final SelectProvider provider;
public DoubleClickSelectAction(SelectProvider provider) {
this.provider = provider;
}
protected boolean isLocked() {
return false;
}
@Override
public State mousePressed(Widget widget, WidgetMouseEvent event) {
if (event.getClickCount() >= 2 && (event.getButton() == MouseEvent.BUTTON1 || event.getButton() == MouseEvent.BUTTON2)) {
boolean invert = (event.getModifiersEx() & MouseEvent.CTRL_DOWN_MASK) != 0;
Point point = event.getPoint();
if (provider.isSelectionAllowed(widget, point, invert)) {
provider.select(widget, point, invert);
return State.CHAIN_ONLY;
}
}
return State.REJECTED;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -34,7 +34,7 @@ import java.awt.Point;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -76,6 +76,10 @@ public class HierarchicalGraphLayout<N, E> extends GraphLayout<N, E> {
public void setControlPoints(List<Point> list) {
// Do nothing for now
}
public boolean isVIP() {
return false;
}
}
private class VertexWrapper implements Vertex {
@ -127,6 +131,7 @@ public class HierarchicalGraphLayout<N, E> extends GraphLayout<N, E> {
}
public int compareTo(Vertex o) {
@SuppressWarnings("unchecked")
VertexWrapper vw = (VertexWrapper) o;
return node.toString().compareTo(vw.node.toString());
}
@ -138,8 +143,8 @@ public class HierarchicalGraphLayout<N, E> extends GraphLayout<N, E> {
protected void performGraphLayout(UniversalGraph<N, E> graph) {
Set<LinkWrapper> links = new HashSet<LinkWrapper>();
Set<VertexWrapper> vertices = new HashSet<VertexWrapper>();
Set<LinkWrapper> links = new LinkedHashSet<LinkWrapper>();
Set<VertexWrapper> vertices = new LinkedHashSet<VertexWrapper>();
Map<N, VertexWrapper> vertexMap = new HashMap<N, VertexWrapper>();
for (N node : graph.getNodes()) {

View File

@ -1,2 +1,2 @@
javac.source=1.5
javac.compilerargs=-Xlint -Xlint:-serial
javac.source=1.7
javac.compilerargs=-Xlint -Xlint:-serial

View File

@ -1,126 +1,142 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.apisupport.project</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
<code-name-base>com.sun.hotspot.igv.coordinator</code-name-base>
<suite-component/>
<module-dependencies>
<dependency>
<code-name-base>com.sun.hotspot.igv.data</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.hotspot.igv.difference</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.hotspot.igv.settings</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.hotspot.igv.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.api.progress</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.10.0.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.actions</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.6.1.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.awt</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.11.0.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.dialogs</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.5.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.explorer</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.11</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.filesystems</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.3</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.loaders</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.7</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.nodes</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.2.0.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.9.0.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.windows</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.16</specification-version>
</run-dependency>
</dependency>
</module-dependencies>
<public-packages/>
</data>
</configuration>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
<type>org.netbeans.modules.apisupport.project</type>
<configuration>
<data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
<code-name-base>com.sun.hotspot.igv.coordinator</code-name-base>
<suite-component/>
<module-dependencies>
<dependency>
<code-name-base>com.sun.hotspot.igv.connection</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.hotspot.igv.data</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.hotspot.igv.difference</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.hotspot.igv.settings</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>com.sun.hotspot.igv.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.0</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.api.progress</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.23.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.actions</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.21.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.awt</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.30.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.dialogs</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.18.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.explorer</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.34.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.filesystems</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.46.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.loaders</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.20.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.nodes</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.20.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.14.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.util.lookup</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.6.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.windows</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.39.1</specification-version>
</run-dependency>
</dependency>
</module-dependencies>
<public-packages/>
</data>
</configuration>
</project>

View File

@ -1,2 +0,0 @@
com.sun.hotspot.igv.coordinator.StandardGroupOrganizer
com.sun.hotspot.igv.coordinator.GraphCountGroupOrganizer

View File

@ -1,7 +1,6 @@
AdvancedOption_DisplayName_Coordinator=Settings
AdvancedOption_Tooltip_Coordinator=Visualization Tool Settings
CTL_OutlineTopComponent=Outline Window
CTL_SomeAction=test
HINT_OutlineTopComponent=This is a Outline window
OpenIDE-Module-Name=Coordinator
AdvancedOption_DisplayName_Coordinator=Settings
AdvancedOption_Tooltip_Coordinator=Visualization Tool Settings
CTL_OutlineTopComponent=Outline
CTL_SomeAction=test
HINT_OutlineTopComponent=Displays loaded groups of graphs.
OpenIDE-Module-Name=Coordinator

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -24,18 +24,13 @@
package com.sun.hotspot.igv.coordinator;
import com.sun.hotspot.igv.coordinator.actions.RemoveCookie;
import com.sun.hotspot.igv.data.ChangedListener;
import com.sun.hotspot.igv.data.Group;
import com.sun.hotspot.igv.data.services.GroupOrganizer;
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.Pair;
import com.sun.hotspot.igv.data.*;
import java.awt.Image;
import java.util.ArrayList;
import java.util.List;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.util.Utilities;
import org.openide.util.ImageUtilities;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;
@ -45,107 +40,72 @@ import org.openide.util.lookup.InstanceContent;
*/
public class FolderNode extends AbstractNode {
private GroupOrganizer organizer;
private InstanceContent content;
private List<Pair<String, List<Group>>> structure;
private List<String> subFolders;
private FolderChildren children;
private static class FolderChildren extends Children.Keys implements ChangedListener<Group> {
private static class FolderChildren extends Children.Keys<FolderElement> implements ChangedListener {
private FolderNode parent;
private List<Group> registeredGroups;
private final Folder folder;
public void setParent(FolderNode parent) {
this.parent = parent;
this.registeredGroups = new ArrayList<Group>();
public FolderChildren(Folder folder) {
this.folder = folder;
folder.getChangedEvent().addListener(this);
}
@Override
protected Node[] createNodes(Object arg0) {
for(Group g : registeredGroups) {
g.getChangedEvent().removeListener(this);
}
registeredGroups.clear();
Pair<String, List<Group>> p = (Pair<String, List<Group>>) arg0;
if (p.getLeft().length() == 0) {
List<Node> curNodes = new ArrayList<Node>();
for (Group g : p.getRight()) {
for (InputGraph graph : g.getGraphs()) {
curNodes.add(new GraphNode(graph));
}
g.getChangedEvent().addListener(this);
registeredGroups.add(g);
}
Node[] result = new Node[curNodes.size()];
for (int i = 0; i < curNodes.size(); i++) {
result[i] = curNodes.get(i);
}
return result;
} else {
return new Node[]{new FolderNode(p.getLeft(), parent.organizer, parent.subFolders, p.getRight())};
protected Node[] createNodes(FolderElement e) {
if (e instanceof InputGraph) {
return new Node[]{new GraphNode((InputGraph) e)};
} else if (e instanceof Folder) {
return new Node[]{new FolderNode((Folder) e)};
} else {
return null;
}
}
@Override
public void addNotify() {
this.setKeys(parent.structure);
this.setKeys(folder.getElements());
}
public void changed(Group source) {
List<Pair<String, List<Group>>> newStructure = new ArrayList<Pair<String, List<Group>>>();
for(Pair<String, List<Group>> p : parent.structure) {
refreshKey(p);
}
}
}
protected InstanceContent getContent() {
return content;
@Override
public void changed(Object source) {
addNotify();
}
}
@Override
public Image getIcon(int i) {
return Utilities.loadImage("com/sun/hotspot/igv/coordinator/images/folder.gif");
return ImageUtilities.loadImage("com/sun/hotspot/igv/coordinator/images/folder.png");
}
protected FolderNode(String name, GroupOrganizer organizer, List<String> subFolders, List<Group> groups) {
this(name, organizer, subFolders, groups, new FolderChildren(), new InstanceContent());
protected FolderNode(Folder folder) {
this(folder, new FolderChildren(folder), new InstanceContent());
}
private FolderNode(String name, GroupOrganizer organizer, List<String> oldSubFolders, final List<Group> groups, FolderChildren children, InstanceContent content) {
private FolderNode(final Folder folder, FolderChildren children, InstanceContent content) {
super(children, new AbstractLookup(content));
children.setParent(this);
this.content = content;
this.children = children;
content.add(new RemoveCookie() {
public void remove() {
for (Group g : groups) {
if (g.getDocument() != null) {
g.getDocument().removeGroup(g);
}
if (folder instanceof FolderElement) {
final FolderElement folderElement = (FolderElement) folder;
this.setDisplayName(folderElement.getName());
content.add(new RemoveCookie() {
@Override
public void remove() {
folderElement.getParent().removeElement(folderElement);
}
}
});
init(name, organizer, oldSubFolders, groups);
});
}
}
public void init(String name, GroupOrganizer organizer, List<String> oldSubFolders, List<Group> groups) {
public void init(String name, List<Group> groups) {
this.setDisplayName(name);
this.organizer = organizer;
this.subFolders = new ArrayList<String>(oldSubFolders);
if (name.length() > 0) {
this.subFolders.add(name);
}
structure = organizer.organize(subFolders, groups);
assert structure != null;
children.addNotify();
for (Group g : groups) {
content.add(g);
}
}
@Override

View File

@ -1,81 +0,0 @@
/*
* Copyright (c) 1998, 2007, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 com.sun.hotspot.igv.coordinator;
import com.sun.hotspot.igv.data.Group;
import com.sun.hotspot.igv.data.Pair;
import com.sun.hotspot.igv.data.services.GroupOrganizer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
/**
*
* @author Thomas Wuerthinger
*/
public class GraphCountGroupOrganizer implements GroupOrganizer {
public String getName() {
return "Graph count structure";
}
public List<Pair<String, List<Group>>> organize(List<String> subFolders, List<Group> groups) {
List<Pair<String, List<Group>>> result = new ArrayList<Pair<String, List<Group>>>();
if (subFolders.size() == 0) {
Map<Integer, List<Group>> map = new HashMap<Integer, List<Group>>();
for (Group g : groups) {
Integer cur = g.getGraphs().size();
if (!map.containsKey(cur)) {
map.put(cur, new ArrayList<Group>());
}
map.get(cur).add(g);
}
SortedSet<Integer> keys = new TreeSet<Integer>(map.keySet());
for (Integer i : keys) {
result.add(new Pair<String, List<Group>>("Graph count " + i, map.get(i)));
}
} else if (subFolders.size() == 1) {
for (Group g : groups) {
List<Group> children = new ArrayList<Group>();
children.add(g);
Pair<String, List<Group>> p = new Pair<String, List<Group>>();
p.setLeft(g.getName());
p.setRight(children);
result.add(p);
}
} else if (subFolders.size() == 2) {
result.add(new Pair<String, List<Group>>("", groups));
}
return result;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -23,23 +23,27 @@
*/
package com.sun.hotspot.igv.coordinator;
import com.sun.hotspot.igv.coordinator.actions.CloneGraphAction;
import com.sun.hotspot.igv.coordinator.actions.DiffGraphAction;
import com.sun.hotspot.igv.coordinator.actions.DiffGraphCookie;
import com.sun.hotspot.igv.coordinator.actions.RemoveCookie;
import com.sun.hotspot.igv.coordinator.actions.GraphCloneCookie;
import com.sun.hotspot.igv.coordinator.actions.GraphOpenCookie;
import com.sun.hotspot.igv.coordinator.actions.GraphRemoveCookie;
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.Properties;
import com.sun.hotspot.igv.data.services.GraphViewer;
import com.sun.hotspot.igv.data.services.InputGraphProvider;
import com.sun.hotspot.igv.util.PropertiesSheet;
import java.awt.Image;
import javax.swing.Action;
import org.openide.actions.OpenAction;
import org.openide.cookies.OpenCookie;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
import org.openide.nodes.NodeAdapter;
import org.openide.nodes.NodeEvent;
import org.openide.nodes.NodeMemberEvent;
import org.openide.nodes.Sheet;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
import org.openide.util.Utilities;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;
@ -48,7 +52,6 @@ import org.openide.util.lookup.InstanceContent;
* @author Thomas Wuerthinger
*/
public class GraphNode extends AbstractNode {
private InputGraph graph;
/** Creates a new instance of GraphNode */
@ -56,7 +59,7 @@ public class GraphNode extends AbstractNode {
this(graph, new InstanceContent());
}
private GraphNode(final InputGraph graph, InstanceContent content) {
private GraphNode(InputGraph graph, InstanceContent content) {
super(Children.LEAF, new AbstractLookup(content));
this.graph = graph;
this.setDisplayName(graph.getName());
@ -66,19 +69,22 @@ public class GraphNode extends AbstractNode {
if (viewer != null) {
// Action for opening the graph
content.add(new OpenCookie() {
public void open() {
viewer.view(graph);
}
});
content.add(new GraphOpenCookie(viewer, graph));
}
// Action for removing a graph
content.add(new RemoveCookie() {
content.add(new GraphRemoveCookie(graph));
public void remove() {
graph.getGroup().removeGraph(graph);
// Action for diffing to the current graph
content.add(new DiffGraphCookie(graph));
// Action for cloning to the current graph
content.add(new GraphCloneCookie(viewer, graph));
this.addNodeListener(new NodeAdapter() {
@Override
public void childrenRemoved(NodeMemberEvent ev) {
GraphNode.this.graph = null;
}
});
}
@ -86,13 +92,17 @@ public class GraphNode extends AbstractNode {
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
PropertiesSheet.initializeSheet(graph.getProperties(), s);
Properties p = new Properties();
p.add(graph.getProperties());
p.setProperty("nodeCount", Integer.toString(graph.getNodes().size()));
p.setProperty("edgeCount", Integer.toString(graph.getEdges().size()));
PropertiesSheet.initializeSheet(p, s);
return s;
}
@Override
public Image getIcon(int i) {
return Utilities.loadImage("com/sun/hotspot/igv/coordinator/images/graph.gif");
return ImageUtilities.loadImage("com/sun/hotspot/igv/coordinator/images/graph.png");
}
@Override
@ -100,31 +110,29 @@ public class GraphNode extends AbstractNode {
return getIcon(i);
}
@Override
public <T extends Node.Cookie> T getCookie(Class<T> aClass) {
if (aClass == DiffGraphCookie.class) {
InputGraphProvider graphProvider = Utilities.actionsGlobalContext().lookup(InputGraphProvider.class);
InputGraph graphA = null;
if (graphProvider != null) {
graphA = graphProvider.getGraph();
}
if (graphA != null && !graphA.isDifferenceGraph()) {
return (T) new DiffGraphCookie(graphA, graph);
}
}
return super.getCookie(aClass);
}
@Override
public Action[] getActions(boolean b) {
return new Action[]{(Action) DiffGraphAction.findObject(DiffGraphAction.class, true), (Action) OpenAction.findObject(OpenAction.class, true)};
return new Action[]{(Action) DiffGraphAction.findObject(DiffGraphAction.class, true), (Action) CloneGraphAction.findObject(CloneGraphAction.class, true), (Action) OpenAction.findObject(OpenAction.class, true)};
}
@Override
public Action getPreferredAction() {
return (Action) OpenAction.findObject(OpenAction.class, true);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof GraphNode) {
return (graph == ((GraphNode) obj).graph);
}
return false;
}
@Override
public int hashCode() {
return graph.hashCode();
}
}

View File

@ -3,6 +3,8 @@
<Form version="1.2" maxVersion="1.2" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
@ -14,28 +16,17 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel2">
<Container class="javax.swing.JScrollPane" name="treeView">
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BeanTreeView();"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BeanTreeView();"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
</Container>
</SubComponents>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
</Container>
</SubComponents>
</Form>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2015, 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
@ -23,37 +23,25 @@
*/
package com.sun.hotspot.igv.coordinator;
import com.sun.hotspot.igv.coordinator.actions.ImportAction;
import com.sun.hotspot.igv.coordinator.actions.RemoveAction;
import com.sun.hotspot.igv.coordinator.actions.RemoveAllAction;
import com.sun.hotspot.igv.coordinator.actions.SaveAllAction;
import com.sun.hotspot.igv.coordinator.actions.SaveAsAction;
import com.sun.hotspot.igv.coordinator.actions.StructuredViewAction;
import com.sun.hotspot.igv.connection.Server;
import com.sun.hotspot.igv.coordinator.actions.*;
import com.sun.hotspot.igv.data.GraphDocument;
import com.sun.hotspot.igv.data.ChangedListener;
import com.sun.hotspot.igv.data.Group;
import com.sun.hotspot.igv.data.services.GroupCallback;
import com.sun.hotspot.igv.data.services.GroupOrganizer;
import com.sun.hotspot.igv.data.services.GroupReceiver;
import java.awt.BorderLayout;
import java.awt.Component;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.border.Border;
import org.openide.ErrorManager;
import org.openide.actions.GarbageCollectAction;
import org.openide.awt.Toolbar;
import org.openide.awt.ToolbarPool;
import org.openide.explorer.ExplorerManager;
import org.openide.explorer.ExplorerUtils;
import org.openide.explorer.view.BeanTreeView;
import org.openide.util.Lookup;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.NbBundle;
@ -72,7 +60,8 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
private ExplorerManager manager;
private GraphDocument document;
private FolderNode root;
private GroupOrganizer organizer;
private Server server;
private Server binaryServer;
private OutlineTopComponent() {
initComponents();
@ -88,17 +77,9 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
private void initListView() {
manager = new ExplorerManager();
organizer = new StandardGroupOrganizer();
root = new FolderNode("", organizer, new ArrayList<String>(), document.getGroups());
root = new FolderNode(document);
manager.setRootContext(root);
((BeanTreeView) this.jScrollPane1).setRootVisible(false);
document.getChangedEvent().addListener(new ChangedListener<GraphDocument>() {
public void changed(GraphDocument document) {
updateStructure();
}
});
((BeanTreeView) this.treeView).setRootVisible(false);
associateLookup(ExplorerUtils.createLookup(manager, getActionMap()));
}
@ -111,61 +92,41 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
this.add(toolbar, BorderLayout.NORTH);
toolbar.add(ImportAction.get(ImportAction.class));
toolbar.add(((NodeAction) RemoveAction.get(RemoveAction.class)).createContextAwareInstance(this.getLookup()));
toolbar.add(RemoveAllAction.get(RemoveAllAction.class));
toolbar.add(((NodeAction) SaveAsAction.get(SaveAsAction.class)).createContextAwareInstance(this.getLookup()));
toolbar.add(SaveAllAction.get(SaveAllAction.class));
toolbar.add(StructuredViewAction.get(StructuredViewAction.class).getToolbarPresenter());
toolbar.add(((NodeAction) RemoveAction.get(RemoveAction.class)).createContextAwareInstance(this.getLookup()));
toolbar.add(RemoveAllAction.get(RemoveAllAction.class));
toolbar.add(GarbageCollectAction.get(GarbageCollectAction.class).getToolbarPresenter());
for (Toolbar tb : ToolbarPool.getDefault().getToolbars()) {
tb.setVisible(false);
}
initOrganizers();
}
public void setOrganizer(GroupOrganizer organizer) {
this.organizer = organizer;
updateStructure();
}
private void initOrganizers() {
}
private void initReceivers() {
final GroupCallback callback = new GroupCallback() {
@Override
public void started(Group g) {
getDocument().addGroup(g);
synchronized(OutlineTopComponent.this) {
getDocument().addElement(g);
}
}
};
Collection<? extends GroupReceiver> receivers = Lookup.getDefault().lookupAll(GroupReceiver.class);
if (receivers.size() > 0) {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
for (GroupReceiver r : receivers) {
Component c = r.init(callback);
panel.add(c);
}
jPanel2.add(panel, BorderLayout.PAGE_START);
}
}
private void updateStructure() {
root.init("", organizer, new ArrayList<String>(), document.getGroups());
server = new Server(getDocument(), callback, false);
binaryServer = new Server(getDocument(), callback, true);
}
public void clear() {
document.clear();
}
@Override
public ExplorerManager getExplorerManager() {
return manager;
}
@ -221,6 +182,25 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
return PREFERRED_ID;
}
@Override
public void requestActive() {
super.requestActive();
treeView.requestFocus();
}
@Override
public boolean requestFocus(boolean temporary) {
treeView.requestFocus();
return super.requestFocus(temporary);
}
@Override
protected boolean requestFocusInWindow(boolean temporary) {
treeView.requestFocus();
return super.requestFocusInWindow(temporary);
}
@Override
public void resultChanged(LookupEvent lookupEvent) {
}
@ -228,7 +208,7 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {
// Not called when user starts application for the first time
super.readExternal(objectInput);
((BeanTreeView) this.jScrollPane1).setRootVisible(false);
((BeanTreeView) this.treeView).setRootVisible(false);
}
@Override
@ -253,19 +233,13 @@ public final class OutlineTopComponent extends TopComponent implements ExplorerM
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jPanel2 = new javax.swing.JPanel();
jScrollPane1 = new BeanTreeView();
treeView = new BeanTreeView();
setLayout(new java.awt.BorderLayout());
jPanel2.setLayout(new java.awt.BorderLayout());
jPanel2.add(jScrollPane1, java.awt.BorderLayout.CENTER);
add(jPanel2, java.awt.BorderLayout.CENTER);
add(treeView, java.awt.BorderLayout.CENTER);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel jPanel2;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane treeView;
// End of variables declaration//GEN-END:variables
}

View File

@ -4,7 +4,7 @@
<Row>
<Toolbar name="Edit" position="1" visible="false"/>
<Toolbar name="File" position="1" visible="false" />
<Toolbar name="Memory" position="1" visible="false" />
<Toolbar name="Memory" position="1" visible="true" />
</Row>
<Row>
<Toolbar name="WorkspaceSwitcher" />

View File

@ -1,62 +0,0 @@
/*
* Copyright (c) 1998, 2007, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 com.sun.hotspot.igv.coordinator;
import com.sun.hotspot.igv.data.Group;
import com.sun.hotspot.igv.data.services.GroupOrganizer;
import com.sun.hotspot.igv.data.Pair;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Thomas Wuerthinger
*/
public class StandardGroupOrganizer implements GroupOrganizer {
public String getName() {
return "-- None --";
}
public List<Pair<String, List<Group>>> organize(List<String> subFolders, List<Group> groups) {
List<Pair<String, List<Group>>> result = new ArrayList<Pair<String, List<Group>>>();
if (groups.size() == 1 && subFolders.size() > 0) {
result.add(new Pair<String, List<Group>>("", groups));
} else {
for (Group g : groups) {
List<Group> children = new ArrayList<Group>();
children.add(g);
Pair<String, List<Group>> p = new Pair<String, List<Group>>();
p.setLeft(g.getName());
p.setRight(children);
result.add(p);
}
}
return result;
}
}

View File

@ -1,18 +1,10 @@
CTL_EditFilterAction=Edit...
CTL_ImportAction=Open...
CTL_OpenGraphAction=View graph
CTL_DiffGraphAction=Difference to current graph
CTL_RemoveAction=Remove methods
CTL_ApplyFilterAction=Apply
CTL_FilterAction=Open Filter Window
CTL_AppliedFilterAction=Open AppliedFilter Window
CTL_OutlineAction=Open Outline Window
CTL_MoveFilterUpAction=Move upwards
CTL_MoveFilterDownAction=Move downwards
CTL_RemoveFilterAction=Remove
CTL_RemoveFilterSettingsAction=Remove filter setting
CTL_SaveAsAction=Save selected methods...
CTL_SaveAllAction=Save all...
CTL_SaveFilterSettingsAction=Save filter settings...
CTL_PropertiesAction=Open Properties Window
CTL_RemoveAction=Remove selected graphs and groups
CTL_RemoveAllAction=Remove all graphs and groups
CTL_OutlineAction=Outline
CTL_SaveAsAction=Save selected groups...
CTL_SaveAllAction=Save all groups...
CTL_PropertiesAction=Open Properties Window
CTL_NewFilterAction=New filter...

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