This commit is contained in:
J. Duke 2017-07-05 20:34:47 +02:00
commit e73c02a294
1074 changed files with 28500 additions and 11826 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

@ -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 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;
@ -82,11 +84,11 @@ public class OopMapSet extends VMObject {
}
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");
}
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");
}
@ -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;
}
@ -255,7 +275,7 @@ public class OopMapSet extends VMObject {
// 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");
}
@ -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

@ -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,12 +387,14 @@ 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++) {
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;
}
assert(xmm_off == float_regs_as_doubles_off, "incorrect number of xmm registers");
@ -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++) {
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;
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
@ -60,7 +62,16 @@ const char* XMMRegisterImpl::name() const {
"xmm0","xmm1","xmm2","xmm3","xmm4","xmm5","xmm6","xmm7"
#ifdef AMD64
,"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.
@ -216,13 +276,15 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl {
RegisterImpl::number_of_registers + // "H" half of a 64bit register
#endif // AMD64
2 * FloatRegisterImpl::number_of_registers +
8 * XMMRegisterImpl::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,6 +86,22 @@ class RegisterSaver {
DEF_XMM_OFFS(13),
DEF_XMM_OFFS(14),
DEF_XMM_OFFS(15),
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,
@ -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,8 +193,8 @@ 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
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);
@ -187,6 +211,59 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
__ 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,10 +264,20 @@ 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
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);
const Address rsi_save(rbp, rsi_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*);
@ -68,7 +68,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
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

@ -209,9 +209,18 @@ public:
erms : 1,
: 1,
rtm : 1,
: 7,
: 4,
avx512f : 1,
avx512dq : 1,
: 1,
adx : 1,
: 12;
: 6,
avx512pf : 1,
avx512er : 1,
avx512cd : 1,
: 1,
avx512bw : 1,
avx512vl : 1;
} bits;
};
@ -221,7 +230,11 @@ public:
uint32_t x87 : 1,
sse : 1,
ymm : 1,
: 29;
: 2,
opmask : 1,
zmm512 : 1,
zmm32 : 1,
: 24;
} bits;
};
@ -229,7 +242,7 @@ protected:
static int _cpu;
static int _model;
static int _stepping;
static int _cpuFeatures; // features returned by the "cpuid" instruction
static uint64_t _cpuFeatures; // features returned by the "cpuid" instruction
// 0 if this instruction is not available
static const char* _features_str;
@ -263,9 +276,17 @@ protected:
CPU_BMI1 = (1 << 22),
CPU_BMI2 = (1 << 23),
CPU_RTM = (1 << 24), // Restricted Transactional Memory instructions
CPU_ADX = (1 << 25)
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;
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()) {
return false;
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
@ -637,6 +695,13 @@ public:
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_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

@ -48,12 +48,21 @@ void VMRegImpl::set_regName() {
XMMRegister xreg = ::as_XMMRegister(0);
for (; i < ConcreteRegisterImpl::max_xmm;) {
for (int j = 0 ; j < 8 ; j++) {
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--------------------------
@ -279,8 +291,10 @@ static int pre_call_resets_size() {
size += 6; // fldcw
}
if (C->max_vector_size() > 16) {
if(UseAVX <= 2) {
size += 3; // vzeroupper
}
}
return size;
}
@ -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
@ -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 );

View File

@ -536,8 +536,12 @@ source %{
#define __ _masm.
static int clear_avx_size() {
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
// from the start of the call to the point where the return address
@ -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);
@ -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]);
%}
%}
@ -3589,8 +3605,7 @@ operand rFlagsRegUCF() %{
%}
// Float register operands
operand regF()
%{
operand regF() %{
constraint(ALLOC_IN_RC(float_reg));
match(RegF);
@ -3599,8 +3614,7 @@ operand regF()
%}
// Double register operands
operand regD()
%{
operand regD() %{
constraint(ALLOC_IN_RC(double_reg));
match(RegD);
@ -3608,6 +3622,39 @@ operand regD()
interface(REG_INTER);
%}
// Vectors
operand vecS() %{
constraint(ALLOC_IN_RC(vectors_reg));
match(VecS);
format %{ %}
interface(REG_INTER);
%}
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);
%}
//----------Memory Operands----------------------------------------------------
// Direct Memory Operand
// operand direct(immP addr)

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.
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.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;
}
DOMImplementation dom = (DOMImplementation) Method_getDOMImplementation.invoke(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) 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,2 +1,2 @@
javac.source=1.5
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() {
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

@ -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()) {
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) {
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 : this.selection) {
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,10 +135,10 @@ 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) {
@ -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.source=1.7
javac.compilerargs=-Xlint -Xlint:-serial

View File

@ -6,6 +6,14 @@
<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/>
@ -44,7 +52,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.10.0.1</specification-version>
<specification-version>1.23.1</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -52,7 +60,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.6.1.1</specification-version>
<specification-version>6.21.1</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -60,7 +68,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.11.0.1</specification-version>
<specification-version>7.30.1</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -68,7 +76,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.5.1</specification-version>
<specification-version>7.18.1</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -76,7 +84,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.11</specification-version>
<specification-version>6.34.1</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -84,7 +92,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.3</specification-version>
<specification-version>7.46.1</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -92,7 +100,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.7</specification-version>
<specification-version>7.20.1</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -100,7 +108,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>
@ -108,7 +116,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>
@ -116,7 +132,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,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_OutlineTopComponent=Outline
CTL_SomeAction=test
HINT_OutlineTopComponent=This is a Outline window
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;
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 new Node[]{new FolderNode(p.getLeft(), parent.organizer, parent.subFolders, p.getRight())};
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);
@Override
public void changed(Object source) {
addNotify();
}
}
}
protected InstanceContent getContent() {
return content;
}
@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;
if (folder instanceof FolderElement) {
final FolderElement folderElement = (FolderElement) folder;
this.setDisplayName(folderElement.getName());
content.add(new RemoveCookie() {
@Override
public void remove() {
for (Group g : groups) {
if (g.getDocument() != null) {
g.getDocument().removeGroup(g);
}
}
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,16 +16,7 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel2">
<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">
<Container class="javax.swing.JScrollPane" name="treeView">
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new BeanTreeView();"/>
</AuxValues>
@ -36,6 +29,4 @@
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
</Container>
</SubComponents>
</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,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_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...

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 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,35 +21,62 @@
* questions.
*
*/
package com.sun.hotspot.igv.view.actions;
import com.sun.hotspot.igv.view.EditorTopComponent;
import javax.swing.Action;
package com.sun.hotspot.igv.coordinator.actions;
import org.openide.nodes.Node;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.CookieAction;
/**
*
* @author Thomas Wuerthinger
*/
public final class NodeFindAction extends CallableSystemAction {
public final class CloneGraphAction extends CookieAction {
public void performAction() {
EditorTopComponent comp = EditorTopComponent.getActive();
if (comp != null) {
comp.findNode();
}
@Override
protected void performAction(Node[] activatedNodes) {
GraphCloneCookie c = activatedNodes[0].getCookie(GraphCloneCookie.class);
assert c != null;
c.openClone();
}
public NodeFindAction() {
putValue(Action.SHORT_DESCRIPTION, "Find nodes");
@Override
protected int mode() {
return CookieAction.MODE_EXACTLY_ONE;
}
@Override
protected boolean enable(Node[] activatedNodes) {
boolean b = super.enable(activatedNodes);
if (b) {
assert activatedNodes.length == 1;
GraphCloneCookie c = activatedNodes[0].getCookie(GraphCloneCookie.class);
assert c != null;
return true;
}
return false;
}
@Override
public String getName() {
return NbBundle.getMessage(NodeFindAction.class, "CTL_NodeFindAction");
return "Open clone";
}
@Override
protected Class<?>[] cookieClasses() {
return new Class<?>[]{
GraphCloneCookie.class
};
}
@Override
protected String iconResource() {
return "com/sun/hotspot/igv/coordinator/images/graph.png";
}
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
@ -58,14 +85,5 @@ public final class NodeFindAction extends CallableSystemAction {
protected boolean asynchronous() {
return false;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
protected String iconResource() {
return "com/sun/hotspot/igv/view/images/search.gif";
}
}

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
@ -35,30 +35,49 @@ import org.openide.util.actions.CookieAction;
*/
public final class DiffGraphAction extends CookieAction {
@Override
protected void performAction(Node[] activatedNodes) {
DiffGraphCookie c = activatedNodes[0].getCookie(DiffGraphCookie.class);
assert c != null;
c.openDiff();
}
@Override
protected int mode() {
return CookieAction.MODE_EXACTLY_ONE;
}
@Override
protected boolean enable(Node[] activatedNodes) {
boolean b = super.enable(activatedNodes);
if (b) {
assert activatedNodes.length == 1;
DiffGraphCookie c = activatedNodes[0].getCookie(DiffGraphCookie.class);
assert c != null;
return c.isPossible();
}
return false;
}
@Override
public String getName() {
return NbBundle.getMessage(DiffGraphAction.class, "CTL_DiffGraphAction");
}
protected Class[] cookieClasses() {
return new Class[]{
@Override
protected Class<?>[] cookieClasses() {
return new Class<?>[]{
DiffGraphCookie.class
};
}
@Override
protected String iconResource() {
return "com/sun/hotspot/igv/coordinator/images/diff.gif";
return "com/sun/hotspot/igv/coordinator/images/diff.png";
}
@Override
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
@ -68,3 +87,4 @@ public final class DiffGraphAction 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
@ -21,12 +21,13 @@
* questions.
*
*/
package com.sun.hotspot.igv.coordinator.actions;
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.services.GraphViewer;
import com.sun.hotspot.igv.data.services.InputGraphProvider;
import com.sun.hotspot.igv.difference.Difference;
import com.sun.hotspot.igv.util.LookupHistory;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
@ -36,21 +37,30 @@ import org.openide.util.Lookup;
*/
public class DiffGraphCookie implements Node.Cookie {
private InputGraph a;
private InputGraph b;
private InputGraph graph;
public DiffGraphCookie(InputGraph a, InputGraph b) {
this.a = a;
this.b = b;
public DiffGraphCookie(InputGraph graph) {
this.graph = graph;
}
private InputGraph getCurrentGraph() {
InputGraphProvider graphProvider = LookupHistory.getLast(InputGraphProvider.class);
if (graphProvider != null) {
return graphProvider.getGraph();
}
return null;
}
public boolean isPossible() {
return getCurrentGraph() != null;
}
public void openDiff() {
InputGraph other = getCurrentGraph();
final GraphViewer viewer = Lookup.getDefault().lookup(GraphViewer.class);
if (viewer != null) {
InputGraph diffGraph = Difference.createDiffGraph(a, b);
viewer.view(diffGraph);
InputGraph diffGraph = Difference.createDiffGraph(other, graph);
viewer.view(diffGraph, true);
}
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2013, 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.coordinator.actions;
import com.sun.hotspot.igv.data.InputGraph;
import com.sun.hotspot.igv.data.services.GraphViewer;
import org.openide.nodes.Node;
public class GraphCloneCookie implements Node.Cookie {
private final GraphViewer viewer;
private final InputGraph graph;
public GraphCloneCookie(GraphViewer viewer, InputGraph graph) {
this.viewer = viewer;
this.graph = graph;
}
public void openClone() {
viewer.view(graph, true);
}
}

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