();
/**
- * Creates a TIFFDirectory instance from the contents of
+ * Creates a {@code TIFFDirectory} instance from the contents of
* an image metadata object. The supplied object must support an image
* metadata format supported by the TIFF {@link javax.imageio.ImageWriter}
* plug-in. This will usually be either the TIFF native image metadata
@@ -139,12 +139,12 @@ public class TIFFDirectory implements Cloneable {
* @param tiffImageMetadata A metadata object which supports a compatible
* image metadata format.
*
- * @return A TIFFDirectory populated from the contents of
+ * @return A {@code TIFFDirectory} populated from the contents of
* the supplied metadata object.
*
- * @throws NullPointerException if tiffImageMetadata
- * is null.
- * @throws IllegalArgumentException if tiffImageMetadata
+ * @throws NullPointerException if {@code tiffImageMetadata}
+ * is {@code null}.
+ * @throws IllegalArgumentException if {@code tiffImageMetadata}
* does not support a compatible image metadata format.
* @throws IIOInvalidTreeException if the supplied metadata object
* cannot be parsed.
@@ -204,7 +204,7 @@ public class TIFFDirectory implements Cloneable {
}
/**
- * Converts a TIFFDirectory to a TIFFIFD.
+ * Converts a {@code TIFFDirectory} to a {@code TIFFIFD}.
*/
private static TIFFIFD getDirectoryAsIFD(TIFFDirectory dir) {
if(dir instanceof TIFFIFD) {
@@ -242,16 +242,16 @@ public class TIFFDirectory implements Cloneable {
}
/**
- * Constructs a TIFFDirectory which is aware of a given
+ * Constructs a {@code TIFFDirectory} which is aware of a given
* group of {@link TIFFTagSet}s. An optional parent {@link TIFFTag}
* may also be specified.
*
- * @param tagSets The TIFFTagSets associated with this
+ * @param tagSets The {@code TIFFTagSets} associated with this
* directory.
- * @param parentTag The parent TIFFTag of this directory;
- * may be null.
- * @throws NullPointerException if tagSets is
- * null.
+ * @param parentTag The parent {@code TIFFTag} of this directory;
+ * may be {@code null}.
+ * @throws NullPointerException if {@code tagSets} is
+ * {@code null}.
*/
public TIFFDirectory(TIFFTagSet[] tagSets, TIFFTag parentTag) {
if(tagSets == null) {
@@ -268,8 +268,8 @@ public class TIFFDirectory implements Cloneable {
/**
* Returns the {@link TIFFTagSet}s of which this directory is aware.
*
- * @return The TIFFTagSets associated with this
- * TIFFDirectory.
+ * @return The {@code TIFFTagSet}s associated with this
+ * {@code TIFFDirectory}.
*/
public TIFFTagSet[] getTagSets() {
return tagSets.toArray(new TIFFTagSet[tagSets.size()]);
@@ -279,9 +279,9 @@ public class TIFFDirectory implements Cloneable {
* Adds an element to the group of {@link TIFFTagSet}s of which this
* directory is aware.
*
- * @param tagSet The TIFFTagSet to add.
- * @throws NullPointerException if tagSet is
- * null.
+ * @param tagSet The {@code TIFFTagSet} to add.
+ * @throws NullPointerException if {@code tagSet} is
+ * {@code null}.
*/
public void addTagSet(TIFFTagSet tagSet) {
if(tagSet == null) {
@@ -297,9 +297,9 @@ public class TIFFDirectory implements Cloneable {
* Removes an element from the group of {@link TIFFTagSet}s of which this
* directory is aware.
*
- * @param tagSet The TIFFTagSet to remove.
- * @throws NullPointerException if tagSet is
- * null.
+ * @param tagSet The {@code TIFFTagSet} to remove.
+ * @throws NullPointerException if {@code tagSet} is
+ * {@code null}.
*/
public void removeTagSet(TIFFTagSet tagSet) {
if(tagSet == null) {
@@ -313,10 +313,10 @@ public class TIFFDirectory implements Cloneable {
/**
* Returns the parent {@link TIFFTag} of this directory if one
- * has been defined or null otherwise.
+ * has been defined or {@code null} otherwise.
*
- * @return The parent TIFFTag of this
- * TIFFDiectory or null.
+ * @return The parent {@code TIFFTag} of this
+ * {@code TIFFDiectory} or {@code null}.
*/
public TIFFTag getParentTag() {
return parentTag;
@@ -324,12 +324,12 @@ public class TIFFDirectory implements Cloneable {
/**
* Returns the {@link TIFFTag} which has tag number equal to
- * tagNumber or null if no such tag
+ * {@code tagNumber} or {@code null} if no such tag
* exists in the {@link TIFFTagSet}s associated with this
* directory.
*
* @param tagNumber The tag number of interest.
- * @return The corresponding TIFFTag or null.
+ * @return The corresponding {@code TIFFTag} or {@code null}.
*/
public TIFFTag getTag(int tagNumber) {
return TIFFIFD.getTag(tagNumber, tagSets);
@@ -338,8 +338,8 @@ public class TIFFDirectory implements Cloneable {
/**
* Returns the number of {@link TIFFField}s in this directory.
*
- * @return The number of TIFFFields in this
- * TIFFDirectory.
+ * @return The number of {@code TIFFField}s in this
+ * {@code TIFFDirectory}.
*/
public int getNumTIFFFields() {
return numLowFields + highFields.size();
@@ -351,7 +351,7 @@ public class TIFFDirectory implements Cloneable {
*
* @param tagNumber The tag number.
* @return Whether a {@link TIFFTag} with tag number equal to
- * tagNumber is present in this TIFFDirectory.
+ * {@code tagNumber} is present in this {@code TIFFDirectory}.
*/
public boolean containsTIFFField(int tagNumber) {
return (tagNumber >= 0 && tagNumber <= MAX_LOW_FIELD_TAG_NUM &&
@@ -363,7 +363,7 @@ public class TIFFDirectory implements Cloneable {
* Adds a TIFF field to the directory.
*
* @param f The field to add.
- * @throws NullPointerException if f is null.
+ * @throws NullPointerException if {@code f} is {@code null}.
*/
public void addTIFFField(TIFFField f) {
if(f == null) {
@@ -384,8 +384,8 @@ public class TIFFDirectory implements Cloneable {
* Retrieves a TIFF field from the directory.
*
* @param tagNumber The tag number of the tag associated with the field.
- * @return A TIFFField with the requested tag number of
- * null if no such field is present.
+ * @return A {@code TIFFField} with the requested tag number of
+ * {@code null} if no such field is present.
*/
public TIFFField getTIFFField(int tagNumber) {
TIFFField f;
@@ -456,7 +456,7 @@ public class TIFFDirectory implements Cloneable {
* Converts the directory to a metadata object.
*
* @return A metadata instance initialized from the contents of this
- * TIFFDirectory.
+ * {@code TIFFDirectory}.
*/
public IIOMetadata getAsMetadata() {
return new TIFFImageMetadata(getDirectoryAsIFD(this));
@@ -465,7 +465,7 @@ public class TIFFDirectory implements Cloneable {
/**
* Clones the directory and all the fields contained therein.
*
- * @return A clone of this TIFFDirectory.
+ * @return A clone of this {@code TIFFDirectory}.
* @throws CloneNotSupportedException if the instance cannot be cloned.
*/
@Override
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java
index 010f841315b..336f81550b7 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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,7 +35,7 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
*
* A field in a TIFF Image File Directory (IFD) is defined as a
* tag number accompanied by a sequence of values of identical data type.
- * TIFF 6.0 defines 12 data types; a 13th type IFD is
+ * TIFF 6.0 defines 12 data types; a 13th type {@code IFD} is
* defined in TIFF Tech Note 1 of TIFF Specification Supplement 1. These
* TIFF data types are referred to by Java constants and mapped internally
* onto Java language data types and type names as follows:
@@ -68,10 +68,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_BYTE}
*
*
- * byte
+ * {@code byte}
*
*
- * "Byte"
+ * {@code "Byte"}
*
*
*
@@ -83,10 +83,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_ASCII}
*
*
- * String
+ * {@code String}
*
*
- * "Ascii"
+ * {@code "Ascii"}
*
*
*
@@ -98,10 +98,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_SHORT}
*
*
- * char
+ * {@code char}
*
*
- * "Short"
+ * {@code "Short"}
*
*
*
@@ -113,10 +113,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_LONG}
*
*
- * long
+ * {@code long}
*
*
- * "Long"
+ * {@code "Long"}
*
*
*
@@ -128,10 +128,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_RATIONAL}
*
*
- * long[2] {numerator, denominator}
+ * {@code long[2]} {numerator, denominator}
*
*
- * "Rational"
+ * {@code "Rational"}
*
*
*
@@ -143,10 +143,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_SBYTE}
*
*
- * byte
+ * {@code byte}
*
*
- * "SByte"
+ * {@code "SByte"}
*
*
*
@@ -158,10 +158,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_UNDEFINED}
*
*
- * byte
+ * {@code byte}
*
*
- * "Undefined"
+ * {@code "Undefined"}
*
*
*
@@ -173,10 +173,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_SSHORT}
*
*
- * short
+ * {@code short}
*
*
- * "SShort"
+ * {@code "SShort"}
*
*
*
@@ -188,10 +188,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_SLONG}
*
*
- * int
+ * {@code int}
*
*
- * "SLong"
+ * {@code "SLong"}
*
*
*
@@ -203,10 +203,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_SRATIONAL}
*
*
- * int[2] {numerator, denominator}
+ * {@code int[2]} {numerator, denominator}
*
*
- * "SRational"
+ * {@code "SRational"}
*
*
*
@@ -218,10 +218,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_FLOAT}
*
*
- * float
+ * {@code float}
*
*
- * "Float"
+ * {@code "Float"}
*
*
*
@@ -233,10 +233,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_DOUBLE}
*
*
- * double
+ * {@code double}
*
*
- * "Double"
+ * {@code "Double"}
*
*
*
@@ -248,10 +248,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
* {@link TIFFTag#TIFF_IFD_POINTER}
*
*
- * long
+ * {@code long}
*
*
- * "IFDPointer"
+ * {@code "IFDPointer"}
*
*
*
@@ -411,19 +411,19 @@ public class TIFFField implements Cloneable {
}
/**
- * Creates a TIFFField from a TIFF native image
+ * Creates a {@code TIFFField} from a TIFF native image
* metadata node. If the value of the "tagNumber" attribute
- * of the node is not found in tagSet then a new
- * TIFFTag with name TIFFTag.UNKNOWN_TAG_NAME
+ * of the node is not found in {@code tagSet} then a new
+ * {@code TIFFTag} with name {@code TIFFTag.UNKNOWN_TAG_NAME}
* will be created and assigned to the field.
*
- * @param tagSet The TIFFTagSet to which the
- * TIFFTag of the field belongs.
- * @param node A native TIFF image metadata TIFFField node.
- * @throws NullPointerException if node is
- * null.
+ * @param tagSet The {@code TIFFTagSet} to which the
+ * {@code TIFFTag} of the field belongs.
+ * @param node A native TIFF image metadata {@code TIFFField} node.
+ * @throws NullPointerException if {@code node} is
+ * {@code null}.
* @throws IllegalArgumentException if the name of the node is not
- * "TIFFField".
+ * {@code "TIFFField"}.
* @return A new {@code TIFFField}.
*/
public static TIFFField createFromMetadataNode(TIFFTagSet tagSet,
@@ -487,14 +487,14 @@ public class TIFFField implements Cloneable {
}
/**
- * Constructs a TIFFField with arbitrary data. The
- * type parameter must be a value for which
+ * Constructs a {@code TIFFField} with arbitrary data. The
+ * {@code type} parameter must be a value for which
* {@link TIFFTag#isDataTypeOK tag.isDataTypeOK()}
- * returns true. The data parameter must
+ * returns {@code true}. The {@code data} parameter must
* be an array of a Java type appropriate for the type of the TIFF
* field.
*
- * Note that the value (data) of the TIFFField
+ *
Note that the value (data) of the {@code TIFFField}
* will always be the actual field value regardless of the number of
* bytes required for that value. This is the case despite the fact
* that the TIFF IFD Entry corresponding to the field may
@@ -503,29 +503,29 @@ public class TIFFField implements Cloneable {
* value fits into 4 bytes). In other words, the value of the
* field will already have been read from the TIFF stream. (An exception
* to this case may occur when the field represents the contents of a
- * non-baseline IFD. In that case the data will be a long[]
- * containing the offset to the IFD and the TIFFDirectory
+ * non-baseline IFD. In that case the data will be a {@code long[]}
+ * containing the offset to the IFD and the {@code TIFFDirectory}
* returned by {@link #getDirectory()} will be its contents.)
*
* @param tag The tag to associated with this field.
- * @param type One of the TIFFTag.TIFF_* constants
+ * @param type One of the {@code TIFFTag.TIFF_*} constants
* indicating the data type of the field as written to the TIFF stream.
* @param count The number of data values.
* @param data The actual data content of the field.
*
- * @throws NullPointerException if tag == null.
- * @throws IllegalArgumentException if type is not
- * one of the TIFFTag.TIFF_* data type constants.
- * @throws IllegalArgumentException if type is an unacceptable
- * data type for the supplied TIFFTag.
- * @throws IllegalArgumentException if count < 0.
- * @throws IllegalArgumentException if count < 1
- * and type is TIFF_RATIONAL or
- * TIFF_SRATIONAL.
- * @throws IllegalArgumentException if count ≠ 1
- * and type is TIFF_IFD_POINTER.
- * @throws NullPointerException if data == null.
- * @throws IllegalArgumentException if data is an instance of
+ * @throws NullPointerException if {@code tag == null}.
+ * @throws IllegalArgumentException if {@code type} is not
+ * one of the {@code TIFFTag.TIFF_*} data type constants.
+ * @throws IllegalArgumentException if {@code type} is an unacceptable
+ * data type for the supplied {@code TIFFTag}.
+ * @throws IllegalArgumentException if {@code count < 0}.
+ * @throws IllegalArgumentException if {@code count < 1}
+ * and {@code type} is {@code TIFF_RATIONAL} or
+ * {@code TIFF_SRATIONAL}.
+ * @throws IllegalArgumentException if {@code count ≠ 1}
+ * and {@code type} is {@code TIFF_IFD_POINTER}.
+ * @throws NullPointerException if {@code data == null}.
+ * @throws IllegalArgumentException if {@code data} is an instance of
* a class incompatible with the specified type.
* @throws IllegalArgumentException if the size of the data array is wrong.
*/
@@ -625,15 +625,15 @@ public class TIFFField implements Cloneable {
* parameters and the created array.
*
* @param tag The tag to associated with this field.
- * @param type One of the TIFFTag.TIFF_* constants
+ * @param type One of the {@code TIFFTag.TIFF_*} constants
* indicating the data type of the field as written to the TIFF stream.
* @param count The number of data values.
- * @throws NullPointerException if tag == null.
- * @throws IllegalArgumentException if type is not
- * one of the TIFFTag.TIFF_* data type constants.
- * @throws IllegalArgumentException if type is an unacceptable
- * data type for the supplied TIFFTag.
- * @throws IllegalArgumentException if count < 0.
+ * @throws NullPointerException if {@code tag == null}.
+ * @throws IllegalArgumentException if {@code type} is not
+ * one of the {@code TIFFTag.TIFF_*} data type constants.
+ * @throws IllegalArgumentException if {@code type} is an unacceptable
+ * data type for the supplied {@code TIFFTag}.
+ * @throws IllegalArgumentException if {@code count < 0}.
* @see #TIFFField(TIFFTag,int,int,Object)
*/
public TIFFField(TIFFTag tag, int type, int count) {
@@ -641,20 +641,20 @@ public class TIFFField implements Cloneable {
}
/**
- * Constructs a TIFFField with a single non-negative integral
+ * Constructs a {@code TIFFField} with a single non-negative integral
* value.
* The field will have type
* {@link TIFFTag#TIFF_SHORT TIFF_SHORT} if
- * val < 65536 and type
+ * {@code val < 65536} and type
* {@link TIFFTag#TIFF_LONG TIFF_LONG} otherwise. The count
* of the field will be unity.
*
* @param tag The tag to associate with this field.
* @param value The value to associate with this field.
- * @throws NullPointerException if tag == null.
+ * @throws NullPointerException if {@code tag == null}.
* @throws IllegalArgumentException if the derived type is unacceptable
- * for the supplied TIFFTag.
- * @throws IllegalArgumentException if value < 0.
+ * for the supplied {@code TIFFTag}.
+ * @throws IllegalArgumentException if {@code value < 0}.
*/
public TIFFField(TIFFTag tag, int value) {
if(tag == null) {
@@ -690,24 +690,24 @@ public class TIFFField implements Cloneable {
}
/**
- * Constructs a TIFFField with an IFD offset and contents.
+ * Constructs a {@code TIFFField} with an IFD offset and contents.
* The offset will be stored as the data of this field as
- * long[] {offset}. The directory will not be cloned. The count
+ * {@code long[] {offset}}. The directory will not be cloned. The count
* of the field will be unity.
*
* @param tag The tag to associated with this field.
- * @param type One of the constants TIFFTag.TIFF_LONG or
- * TIFFTag.TIFF_IFD_POINTER.
+ * @param type One of the constants {@code TIFFTag.TIFF_LONG} or
+ * {@code TIFFTag.TIFF_IFD_POINTER}.
* @param offset The IFD offset.
* @param dir The directory.
*
- * @throws NullPointerException if tag == null.
- * @throws IllegalArgumentException if type is neither
- * TIFFTag.TIFF_LONG nor TIFFTag.TIFF_IFD_POINTER.
- * @throws IllegalArgumentException if type is an unacceptable
- * data type for the supplied TIFFTag.
- * @throws IllegalArgumentException if offset is non-positive.
- * @throws NullPointerException if dir == null.
+ * @throws NullPointerException if {@code tag == null}.
+ * @throws IllegalArgumentException if {@code type} is neither
+ * {@code TIFFTag.TIFF_LONG} nor {@code TIFFTag.TIFF_IFD_POINTER}.
+ * @throws IllegalArgumentException if {@code type} is an unacceptable
+ * data type for the supplied {@code TIFFTag}.
+ * @throws IllegalArgumentException if {@code offset} is non-positive.
+ * @throws NullPointerException if {@code dir == null}.
*
* @see #TIFFField(TIFFTag,int,int,Object)
*/
@@ -728,14 +728,14 @@ public class TIFFField implements Cloneable {
/**
* Retrieves the tag associated with this field.
*
- * @return The associated TIFFTag.
+ * @return The associated {@code TIFFTag}.
*/
public TIFFTag getTag() {
return tag;
}
/**
- * Retrieves the tag number in the range [0, 65535].
+ * Retrieves the tag number in the range {@code [0, 65535]}.
*
* @return The tag number.
*/
@@ -745,7 +745,7 @@ public class TIFFField implements Cloneable {
/**
* Returns the type of the data stored in the field. For a TIFF 6.0
- * stream, the value will equal one of the TIFFTag.TIFF_*
+ * stream, the value will equal one of the {@code TIFFTag.TIFF_*}
* constants. For future revisions of TIFF, higher values are possible.
*
* @return The data type of the field value.
@@ -757,11 +757,11 @@ public class TIFFField implements Cloneable {
/**
* Returns the name of the supplied data type constant.
*
- * @param dataType One of the TIFFTag.TIFF_* constants
+ * @param dataType One of the {@code TIFFTag.TIFF_*} constants
* indicating the data type of the field as written to the TIFF stream.
* @return The type name corresponding to the supplied type constant.
- * @throws IllegalArgumentException if dataType is not
- * one of the TIFFTag.TIFF_* data type constants.
+ * @throws IllegalArgumentException if {@code dataType} is not
+ * one of the {@code TIFFTag.TIFF_*} data type constants.
*/
public static String getTypeName(int dataType) {
if (dataType < TIFFTag.MIN_DATATYPE ||
@@ -774,11 +774,11 @@ public class TIFFField implements Cloneable {
/**
* Returns the data type constant corresponding to the supplied data
- * type name. If the name is unknown -1 will be returned.
+ * type name. If the name is unknown {@code -1} will be returned.
*
* @param typeName The type name.
- * @return One of the TIFFTag.TIFF_* constants or
- * -1 if the name is not recognized.
+ * @return One of the {@code TIFFTag.TIFF_*} constants or
+ * {@code -1} if the name is not recognized.
*/
public static int getTypeByName(String typeName) {
for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) {
@@ -793,14 +793,14 @@ public class TIFFField implements Cloneable {
/**
* Creates an array appropriate for the indicated data type.
*
- * @param dataType One of the TIFFTag.TIFF_* data type
+ * @param dataType One of the {@code TIFFTag.TIFF_*} data type
* constants.
* @param count The number of values in the array.
* @return An array appropriate for the specified data type.
*
- * @throws IllegalArgumentException if dataType is not
- * one of the TIFFTag.TIFF_* data type constants.
- * @throws IllegalArgumentException if count < 0.
+ * @throws IllegalArgumentException if {@code dataType} is not
+ * one of the {@code TIFFTag.TIFF_*} data type constants.
+ * @throws IllegalArgumentException if {@code count < 0}.
*/
public static Object createArrayForType(int dataType, int count) {
if(count < 0) {
@@ -836,15 +836,15 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns the TIFFField as a node named either
+ * Returns the {@code TIFFField} as a node named either
* "TIFFField" or "TIFFIFD" as described in the
* TIFF native image metadata specification. The node will be named
* "TIFFIFD" if and only if the field's data object is an
* instance of {@link TIFFDirectory} or equivalently
* {@link TIFFTag#isIFDPointer getTag.isIFDPointer()} returns
- * true.
+ * {@code true}.
*
- * @return a Node named "TIFFField" or
+ * @return a {@code Node} named "TIFFField" or
* "TIFFIFD" .
*/
public Node getAsNativeNode() {
@@ -863,8 +863,8 @@ public class TIFFField implements Cloneable {
/**
* Returns the number of data items present in the field. For
- * TIFFTag.TIFF_ASCII fields, the value returned is the
- * number of Strings, not the total length of the
+ * {@code TIFFTag.TIFF_ASCII} fields, the value returned is the
+ * number of {@code String}s, not the total length of the
* data as in the file representation.
*
* @return The number of data items present in the field.
@@ -884,17 +884,17 @@ public class TIFFField implements Cloneable {
/**
* Returns the data as an uninterpreted array of
- * bytes. The type of the field must be one of
- * TIFFTag.TIFF_BYTE, TIFF_SBYTE, or
- * TIFF_UNDEFINED.
+ * {@code byte}s. The type of the field must be one of
+ * {@code TIFFTag.TIFF_BYTE}, {@code TIFF_SBYTE}, or
+ * {@code TIFF_UNDEFINED}.
*
- *
For data in TIFFTag.TIFF_BYTE format, the application
+ *
For data in {@code TIFFTag.TIFF_BYTE} format, the application
* must take care when promoting the data to longer integral types
* to avoid sign extension.
*
* @throws ClassCastException if the field is not of type
- * TIFF_BYTE, TIFF_SBYTE, or
- * TIFF_UNDEFINED.
+ * {@code TIFF_BYTE}, {@code TIFF_SBYTE}, or
+ * {@code TIFF_UNDEFINED}.
* @return The data as an uninterpreted array of bytes.
*/
public byte[] getAsBytes() {
@@ -902,11 +902,11 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns TIFFTag.TIFF_SHORT data as an array of
- * chars (unsigned 16-bit integers).
+ * Returns {@code TIFFTag.TIFF_SHORT} data as an array of
+ * {@code char}s (unsigned 16-bit integers).
*
* @throws ClassCastException if the field is not of type
- * TIFF_SHORT.
+ * {@code TIFF_SHORT}.
* @return The data as an array of {@code char}s.
*/
public char[] getAsChars() {
@@ -914,11 +914,11 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns TIFFTag.TIFF_SSHORT data as an array of
- * shorts (signed 16-bit integers).
+ * Returns {@code TIFFTag.TIFF_SSHORT} data as an array of
+ * {@code short}s (signed 16-bit integers).
*
* @throws ClassCastException if the field is not of type
- * TIFF_SSHORT.
+ * {@code TIFF_SSHORT}.
* @return The data as an array of {@code short}s.
*/
public short[] getAsShorts() {
@@ -926,12 +926,12 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns TIFFTag.TIFF_SLONG data as an array of
- * ints (signed 32-bit integers).
+ * Returns {@code TIFFTag.TIFF_SLONG} data as an array of
+ * {@code int}s (signed 32-bit integers).
*
* @throws ClassCastException if the field is not of type
- * TIFF_SHORT, TIFF_SSHORT, or
- * TIFF_SLONG.
+ * {@code TIFF_SHORT}, {@code TIFF_SSHORT}, or
+ * {@code TIFF_SLONG}.
* @return The data as an array of {@code int}s.
*/
public int[] getAsInts() {
@@ -957,12 +957,12 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns TIFFTag.TIFF_LONG or
- * TIFF_IFD_POINTER data as an array of
- * longs (signed 64-bit integers).
+ * Returns {@code TIFFTag.TIFF_LONG} or
+ * {@code TIFF_IFD_POINTER} data as an array of
+ * {@code long}s (signed 64-bit integers).
*
* @throws ClassCastException if the field is not of type
- * TIFF_LONG or TIFF_IFD_POINTER.
+ * {@code TIFF_LONG} or {@code TIFF_IFD_POINTER}.
* @return The data as an array of {@code long}s.
*/
public long[] getAsLongs() {
@@ -970,11 +970,11 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns TIFFTag.TIFF_FLOAT data as an array of
- * floats (32-bit floating-point values).
+ * Returns {@code TIFFTag.TIFF_FLOAT} data as an array of
+ * {@code float}s (32-bit floating-point values).
*
* @throws ClassCastException if the field is not of type
- * TIFF_FLOAT.
+ * {@code TIFF_FLOAT}.
* @return The data as an array of {@code float}s.
*/
public float[] getAsFloats() {
@@ -982,11 +982,11 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns TIFFTag.TIFF_DOUBLE data as an array of
- * doubles (64-bit floating-point values).
+ * Returns {@code TIFFTag.TIFF_DOUBLE} data as an array of
+ * {@code double}s (64-bit floating-point values).
*
* @throws ClassCastException if the field is not of type
- * TIFF_DOUBLE.
+ * {@code TIFF_DOUBLE}.
* @return The data as an array of {@code double}s.
*/
public double[] getAsDoubles() {
@@ -994,11 +994,11 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns TIFFTag.TIFF_SRATIONAL data as an array of
- * 2-element arrays of ints.
+ * Returns {@code TIFFTag.TIFF_SRATIONAL} data as an array of
+ * 2-element arrays of {@code int}s.
*
* @throws ClassCastException if the field is not of type
- * TIFF_SRATIONAL.
+ * {@code TIFF_SRATIONAL}.
* @return The data as an array of signed rationals.
*/
public int[][] getAsSRationals() {
@@ -1006,11 +1006,11 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns TIFFTag.TIFF_RATIONAL data as an array of
- * 2-element arrays of longs.
+ * Returns {@code TIFFTag.TIFF_RATIONAL} data as an array of
+ * 2-element arrays of {@code long}s.
*
* @throws ClassCastException if the field is not of type
- * TIFF_RATIONAL.
+ * {@code TIFF_RATIONAL}.
* @return The data as an array of unsigned rationals.
*/
public long[][] getAsRationals() {
@@ -1018,30 +1018,30 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns data in any format as an int.
+ * Returns data in any format as an {@code int}.
*
- *
TIFFTag.TIFF_BYTE values are treated as unsigned; that
+ *
{@code TIFFTag.TIFF_BYTE} values are treated as unsigned; that
* is, no sign extension will take place and the returned value
- * will be in the range [0, 255]. TIFF_SBYTE data
+ * will be in the range [0, 255]. {@code TIFF_SBYTE} data
* will be returned in the range [-128, 127].
*
- *
A TIFF_UNDEFINED value is treated as though
- * it were a TIFF_BYTE.
+ *
A {@code TIFF_UNDEFINED} value is treated as though
+ * it were a {@code TIFF_BYTE}.
*
- *
Data in TIFF_SLONG, TIFF_LONG,
- * TIFF_FLOAT, TIFF_DOUBLE or
- * TIFF_IFD_POINTER format are simply cast to
- * int and may suffer from truncation.
+ *
Data in {@code TIFF_SLONG}, {@code TIFF_LONG},
+ * {@code TIFF_FLOAT}, {@code TIFF_DOUBLE} or
+ * {@code TIFF_IFD_POINTER} format are simply cast to
+ * {@code int} and may suffer from truncation.
*
- *
Data in TIFF_SRATIONAL or
- * TIFF_RATIONAL format are evaluated by dividing the
+ *
Data in {@code TIFF_SRATIONAL} or
+ * {@code TIFF_RATIONAL} format are evaluated by dividing the
* numerator into the denominator using double-precision
- * arithmetic and then casting to int. Loss of
+ * arithmetic and then casting to {@code int}. Loss of
* precision and truncation may occur.
*
- *
Data in TIFF_ASCII format will be parsed as by
- * the Double.parseDouble method, with the result
- * case to int.
+ *
Data in {@code TIFF_ASCII} format will be parsed as by
+ * the {@code Double.parseDouble} method, with the result
+ * case to {@code int}.
*
* @param index The index of the data.
* @return The data at the given index as an {@code int}.
@@ -1081,17 +1081,17 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns data in any format as a long.
+ * Returns data in any format as a {@code long}.
*
- *
TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data
+ *
{@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data
* are treated as unsigned; that is, no sign extension will take
* place and the returned value will be in the range [0, 255].
- * TIFF_SBYTE data will be returned in the range
+ * {@code TIFF_SBYTE} data will be returned in the range
* [-128, 127].
*
- *
Data in TIFF_ASCII format will be parsed as by
- * the Double.parseDouble method, with the result
- * cast to long.
+ *
Data in {@code TIFF_ASCII} format will be parsed as by
+ * the {@code Double.parseDouble} method, with the result
+ * cast to {@code long}.
*
* @param index The index of the data.
* @return The data at the given index as a {@code long}.
@@ -1127,27 +1127,27 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns data in any format as a float.
+ * Returns data in any format as a {@code float}.
*
- *
TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data
+ *
{@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data
* are treated as unsigned; that is, no sign extension will take
* place and the returned value will be in the range [0, 255].
- * TIFF_SBYTE data will be returned in the range
+ * {@code TIFF_SBYTE} data will be returned in the range
* [-128, 127].
*
- *
Data in TIFF_SLONG, TIFF_LONG,
- * TIFF_DOUBLE, or TIFF_IFD_POINTER format are
- * simply cast to float and may suffer from
+ *
Data in {@code TIFF_SLONG}, {@code TIFF_LONG},
+ * {@code TIFF_DOUBLE}, or {@code TIFF_IFD_POINTER} format are
+ * simply cast to {@code float} and may suffer from
* truncation.
*
- *
Data in TIFF_SRATIONAL or
- * TIFF_RATIONAL format are evaluated by dividing the
+ *
Data in {@code TIFF_SRATIONAL} or
+ * {@code TIFF_RATIONAL} format are evaluated by dividing the
* numerator into the denominator using double-precision
- * arithmetic and then casting to float.
+ * arithmetic and then casting to {@code float}.
*
- *
Data in TIFF_ASCII format will be parsed as by
- * the Double.parseDouble method, with the result
- * cast to float.
+ *
Data in {@code TIFF_ASCII} format will be parsed as by
+ * the {@code Double.parseDouble} method, with the result
+ * cast to {@code float}.
*
* @param index The index of the data.
* @return The data at the given index as a {@code float}.
@@ -1187,21 +1187,21 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns data in any format as a double.
+ * Returns data in any format as a {@code double}.
*
- *
TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data
+ *
{@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data
* are treated as unsigned; that is, no sign extension will take
* place and the returned value will be in the range [0, 255].
- * TIFF_SBYTE data will be returned in the range
+ * {@code TIFF_SBYTE} data will be returned in the range
* [-128, 127].
*
- *
Data in TIFF_SRATIONAL or
- * TIFF_RATIONAL format are evaluated by dividing the
+ *
Data in {@code TIFF_SRATIONAL} or
+ * {@code TIFF_RATIONAL} format are evaluated by dividing the
* numerator into the denominator using double-precision
* arithmetic.
*
- *
Data in TIFF_ASCII format will be parsed as by
- * the Double.parseDouble method.
+ *
Data in {@code TIFF_ASCII} format will be parsed as by
+ * the {@code Double.parseDouble} method.
*
* @param index The index of the data.
* @return The data at the given index as a {@code double}.
@@ -1241,11 +1241,11 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns a TIFFTag.TIFF_ASCII value as a
- * String.
+ * Returns a {@code TIFFTag.TIFF_ASCII} value as a
+ * {@code String}.
*
* @throws ClassCastException if the field is not of type
- * TIFF_ASCII.
+ * {@code TIFF_ASCII}.
*
* @param index The index of the data.
* @return The data at the given index as a {@code String}.
@@ -1255,13 +1255,13 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns a TIFFTag.TIFF_SRATIONAL data item as a
- * two-element array of ints.
+ * Returns a {@code TIFFTag.TIFF_SRATIONAL} data item as a
+ * two-element array of {@code int}s.
*
* @param index The index of the data.
* @return The data at the given index as a signed rational.
* @throws ClassCastException if the field is not of type
- * TIFF_SRATIONAL.
+ * {@code TIFF_SRATIONAL}.
*/
public int[] getAsSRational(int index) {
return ((int[][])data)[index];
@@ -1274,7 +1274,7 @@ public class TIFFField implements Cloneable {
* @param index The index of the data.
* @return The data at the given index as an unsigned rational.
* @throws ClassCastException if the field is not of type
- * TIFF_RATIONAL.
+ * {@code TIFF_RATIONAL}.
*/
public long[] getAsRational(int index) {
return ((long[][])data)[index];
@@ -1282,11 +1282,11 @@ public class TIFFField implements Cloneable {
/**
- * Returns a String containing a human-readable
+ * Returns a {@code String} containing a human-readable
* version of the data item. Data of type
- * TIFFTag.TIFF_RATIONAL or TIFF_SRATIONAL are
+ * {@code TIFFTag.TIFF_RATIONAL} or {@code TIFF_SRATIONAL} are
* represented as a pair of integers separated by a
- * '/' character.
+ * {@code '/'} character.
*
* @param index The index of the data.
* @return The data at the given index as a {@code String}.
@@ -1355,7 +1355,7 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns whether the field has a TIFFDirectory.
+ * Returns whether the field has a {@code TIFFDirectory}.
*
* @return true if and only if getDirectory() returns non-null.
*/
@@ -1364,8 +1364,8 @@ public class TIFFField implements Cloneable {
}
/**
- * Returns the associated TIFFDirectory, if available. If no
- * directory is set, then null will be returned.
+ * Returns the associated {@code TIFFDirectory}, if available. If no
+ * directory is set, then {@code null} will be returned.
*
* @return the TIFFDirectory instance or null.
*/
@@ -1376,7 +1376,7 @@ public class TIFFField implements Cloneable {
/**
* Clones the field and all the information contained therein.
*
- * @return A clone of this TIFFField.
+ * @return A clone of this {@code TIFFField}.
* @throws CloneNotSupportedException if the instance cannot be cloned.
*/
@Override
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java
index 27f633c7cfd..9c120d094ef 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -39,11 +39,11 @@ import javax.imageio.ImageReadParam;
* be provided by this interface.
*
*
Additional TIFF tags must be organized into
- * TIFFTagSets. A TIFFTagSet may be
+ * {@code TIFFTagSet}s. A {@code TIFFTagSet} may be
* provided to the reader by means of the
- * addAllowedTagSet method. By default, the tag sets
- * BaselineTIFFTagSet, FaxTIFFTagSet,
- * ExifParentTIFFTagSet, and GeoTIFFTagSet
+ * {@code addAllowedTagSet} method. By default, the tag sets
+ * {@code BaselineTIFFTagSet}, {@code FaxTIFFTagSet},
+ * {@code ExifParentTIFFTagSet}, and {@code GeoTIFFTagSet}
* are included.
*
* @since 9
@@ -53,10 +53,10 @@ public class TIFFImageReadParam extends ImageReadParam {
private List allowedTagSets = new ArrayList(4);
/**
- * Constructs a TIFFImageReadParam. Tags defined by
- * the TIFFTagSets BaselineTIFFTagSet,
- * FaxTIFFTagSet, ExifParentTIFFTagSet, and
- * GeoTIFFTagSet will be supported.
+ * Constructs a {@code TIFFImageReadParam}. Tags defined by
+ * the {@code TIFFTagSet}s {@code BaselineTIFFTagSet},
+ * {@code FaxTIFFTagSet}, {@code ExifParentTIFFTagSet}, and
+ * {@code GeoTIFFTagSet} will be supported.
*
* @see BaselineTIFFTagSet
* @see FaxTIFFTagSet
@@ -71,13 +71,13 @@ public class TIFFImageReadParam extends ImageReadParam {
}
/**
- * Adds a TIFFTagSet object to the list of allowed
+ * Adds a {@code TIFFTagSet} object to the list of allowed
* tag sets.
*
- * @param tagSet a TIFFTagSet.
+ * @param tagSet a {@code TIFFTagSet}.
*
- * @throws IllegalArgumentException if tagSet is
- * null.
+ * @throws IllegalArgumentException if {@code tagSet} is
+ * {@code null}.
*/
public void addAllowedTagSet(TIFFTagSet tagSet) {
if (tagSet == null) {
@@ -87,15 +87,15 @@ public class TIFFImageReadParam extends ImageReadParam {
}
/**
- * Removes a TIFFTagSet object from the list of
- * allowed tag sets. Removal is based on the equals
- * method of the TIFFTagSet, which is normally
+ * Removes a {@code TIFFTagSet} object from the list of
+ * allowed tag sets. Removal is based on the {@code equals}
+ * method of the {@code TIFFTagSet}, which is normally
* defined as reference equality.
*
- * @param tagSet a TIFFTagSet.
+ * @param tagSet a {@code TIFFTagSet}.
*
- * @throws IllegalArgumentException if tagSet is
- * null.
+ * @throws IllegalArgumentException if {@code tagSet} is
+ * {@code null}.
*/
public void removeAllowedTagSet(TIFFTagSet tagSet) {
if (tagSet == null) {
@@ -105,10 +105,10 @@ public class TIFFImageReadParam extends ImageReadParam {
}
/**
- * Returns a List containing the allowed
- * TIFFTagSet objects.
+ * Returns a {@code List} containing the allowed
+ * {@code TIFFTagSet} objects.
*
- * @return a List of TIFFTagSets.
+ * @return a {@code List} of {@code TIFFTagSet}s.
*/
public List getAllowedTagSets() {
return allowedTagSets;
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java
index 68542c4078d..c312bd55419 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -105,7 +105,7 @@ public class TIFFTag {
* The name assigned to a tag with an unknown tag number. Such
* a tag may be created for example when reading an IFD and a
* tag number is encountered which is not in any of the
- * TIFFTagSets known to the reader.
+ * {@code TIFFTagSet}s known to the reader.
*/
public static final String UNKNOWN_TAG_NAME = "UnknownTag";
@@ -141,12 +141,12 @@ public class TIFFTag {
private SortedMap valueNames = null;
/**
- * Constructs a TIFFTag with a given name, tag number, set
+ * Constructs a {@code TIFFTag} with a given name, tag number, set
* of legal data types, and value count. A negative value count signifies
* that either an arbitrary number of values is legal or the required count
* is determined by the values of other fields in the IFD. A non-negative
* count specifies the number of values which an associated field must
- * contain. The tag will have no associated TIFFTagSet.
+ * contain. The tag will have no associated {@code TIFFTagSet}.
*
* If there are mnemonic names to be associated with the legal
* data values for the tag, {@link #addValueName(int, String)
@@ -183,18 +183,18 @@ public class TIFFTag {
}
/**
- * Constructs a TIFFTag with a given name, tag number and
- * TIFFTagSet to which it refers. The legal data types are
+ * Constructs a {@code TIFFTag} with a given name, tag number and
+ * {@code TIFFTagSet} to which it refers. The legal data types are
* set to include {@link #TIFF_LONG} and {@link #TIFF_IFD_POINTER} and the
- * value count is unity. The TIFFTagSet will
- * represent the set of TIFFTags which appear in the IFD
- * pointed to. A TIFFTag represents an IFD pointer if and
- * only if tagSet is non-null or the data
- * type TIFF_IFD_POINTER is legal.
+ * value count is unity. The {@code TIFFTagSet} will
+ * represent the set of {@code TIFFTag}s which appear in the IFD
+ * pointed to. A {@code TIFFTag} represents an IFD pointer if and
+ * only if {@code tagSet} is non-{@code null} or the data
+ * type {@code TIFF_IFD_POINTER} is legal.
*
* @param name the name of the tag.
* @param number the number used to represent the tag.
- * @param tagSet the TIFFTagSet to which this tag belongs.
+ * @param tagSet the {@code TIFFTagSet} to which this tag belongs.
* @throws NullPointerException if name or tagSet is null.
* @throws IllegalArgumentException if number is negative.
*
@@ -210,9 +210,9 @@ public class TIFFTag {
}
/**
- * Constructs a TIFFTag with a given name, tag number,
+ * Constructs a {@code TIFFTag} with a given name, tag number,
* and set of legal data types. The value count of the tag will be
- * undefined and it will have no associated TIFFTagSet.
+ * undefined and it will have no associated {@code TIFFTagSet}.
*
* @param name the name of the tag.
* @param number the number used to represent the tag.
@@ -236,9 +236,9 @@ public class TIFFTag {
*
* @return the number of bytes used to store the given data type.
*
- * @throws IllegalArgumentException if datatype is
- * less than MIN_DATATYPE or greater than
- * MAX_DATATYPE.
+ * @throws IllegalArgumentException if {@code datatype} is
+ * less than {@code MIN_DATATYPE} or greater than
+ * {@code MAX_DATATYPE}.
*/
public static int getSizeOfType(int dataType) {
if (dataType < MIN_DATATYPE ||dataType > MAX_DATATYPE) {
@@ -251,7 +251,7 @@ public class TIFFTag {
/**
* Returns the name of the tag, as it will appear in image metadata.
*
- * @return the tag name, as a String.
+ * @return the tag name, as a {@code String}.
*/
public String getName() {
return name;
@@ -260,7 +260,7 @@ public class TIFFTag {
/**
* Returns the integer used to represent the tag.
*
- * @return the tag number, as an int.
+ * @return the tag number, as an {@code int}.
*/
public int getNumber() {
return number;
@@ -276,7 +276,7 @@ public class TIFFTag {
* (1 << TIFFTag.TIFF_SHORT) | (1 << TIFFTag.TIFF_LONG)
*
*
- * @return an int containing a bitmask encoding the
+ * @return an {@code int} containing a bitmask encoding the
* set of valid data types.
*/
public int getDataTypes() {
@@ -285,11 +285,11 @@ public class TIFFTag {
/**
* Returns the value count of this tag. If this value is positive, it
- * represents the required number of values for a TIFFField
+ * represents the required number of values for a {@code TIFFField}
* which has this tag. If the value is negative, the count is undefined.
* In the latter case the count may be derived, e.g., the number of values
- * of the BitsPerSample field is SamplesPerPixel,
- * or it may be variable as in the case of most US-ASCII
+ * of the {@code BitsPerSample} field is {@code SamplesPerPixel},
+ * or it may be variable as in the case of most {@code US-ASCII}
* fields.
*
* @return the value count of this tag.
@@ -299,18 +299,18 @@ public class TIFFTag {
}
/**
- * Returns true if the given data type
+ * Returns {@code true} if the given data type
* may be used for the data associated with this tag.
*
* @param dataType the data type to be queried, one of
- * TIFF_BYTE, TIFF_SHORT, etc.
+ * {@code TIFF_BYTE}, {@code TIFF_SHORT}, etc.
*
- * @return a boolean indicating whether the given
+ * @return a {@code boolean} indicating whether the given
* data type may be used with this tag.
*
- * @throws IllegalArgumentException if datatype is
- * less than MIN_DATATYPE or greater than
- * MAX_DATATYPE.
+ * @throws IllegalArgumentException if {@code datatype} is
+ * less than {@code MIN_DATATYPE} or greater than
+ * {@code MAX_DATATYPE}.
*/
public boolean isDataTypeOK(int dataType) {
if (dataType < MIN_DATATYPE || dataType > MAX_DATATYPE) {
@@ -320,38 +320,38 @@ public class TIFFTag {
}
/**
- * Returns the TIFFTagSet of which this tag is a part.
+ * Returns the {@code TIFFTagSet} of which this tag is a part.
*
- * @return the containing TIFFTagSet.
+ * @return the containing {@code TIFFTagSet}.
*/
public TIFFTagSet getTagSet() {
return tagSet;
}
/**
- * Returns true if this tag is used to point to an IFD
- * structure containing additional tags. A TIFFTag represents
- * an IFD pointer if and only if its TIFFTagSet is
- * non-null or the data type TIFF_IFD_POINTER is
+ * Returns {@code true} if this tag is used to point to an IFD
+ * structure containing additional tags. A {@code TIFFTag} represents
+ * an IFD pointer if and only if its {@code TIFFTagSet} is
+ * non-{@code null} or the data type {@code TIFF_IFD_POINTER} is
* legal. This condition will be satisfied if and only if either
- * getTagSet() != null or
- * isDataTypeOK(TIFF_IFD_POINTER) == true.
+ * {@code getTagSet() != null} or
+ * {@code isDataTypeOK(TIFF_IFD_POINTER) == true}.
*
*
Many TIFF extensions use the IFD mechanism in order to limit the
* number of new tags that may appear in the root IFD.
*
- * @return true if this tag points to an IFD.
+ * @return {@code true} if this tag points to an IFD.
*/
public boolean isIFDPointer() {
return tagSet != null || isDataTypeOK(TIFF_IFD_POINTER);
}
/**
- * Returns true if there are mnemonic names associated with
+ * Returns {@code true} if there are mnemonic names associated with
* the set of legal values for the data associated with this tag. Mnemonic
* names apply only to tags which have integral data type.
*
- * @return true if mnemonic value names are available.
+ * @return {@code true} if mnemonic value names are available.
*/
public boolean hasValueNames() {
return valueNames != null;
@@ -373,14 +373,14 @@ public class TIFFTag {
/**
* Returns the mnemonic name associated with a particular value
- * that this tag's data may take on, or null if
+ * that this tag's data may take on, or {@code null} if
* no name is present. Mnemonic names apply only to tags which have
* integral data type.
*
* @param value the data value.
*
* @return the mnemonic name associated with the value, as a
- * String.
+ * {@code String}.
*/
public String getValueName(int value) {
if (valueNames == null) {
diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java
index 8082fba86b8..793bafce1b7 100644
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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
@@ -39,7 +39,7 @@ import java.util.TreeSet;
* specification itself).
*
* This class and its subclasses are responsible for mapping
- * between raw tag numbers and TIFFTag objects, which
+ * between raw tag numbers and {@code TIFFTag} objects, which
* contain additional information about each tag, such as the tag's
* name, legal data types, and mnemonic names for some or all of ts
* data values.
@@ -59,15 +59,15 @@ public class TIFFTagSet {
private TIFFTagSet() {}
/**
- * Constructs a TIFFTagSet, given a List
- * of TIFFTag objects.
+ * Constructs a {@code TIFFTagSet}, given a {@code List}
+ * of {@code TIFFTag} objects.
*
- * @param tags a List object containing
- * TIFFTag objects to be added to this tag set.
+ * @param tags a {@code List} object containing
+ * {@code TIFFTag} objects to be added to this tag set.
*
- * @throws IllegalArgumentException if tags is
- * null, or contains objects that are not instances
- * of the TIFFTag class.
+ * @throws IllegalArgumentException if {@code tags} is
+ * {@code null}, or contains objects that are not instances
+ * of the {@code TIFFTag} class.
*/
public TIFFTagSet(List tags) {
if (tags == null) {
@@ -88,29 +88,29 @@ public class TIFFTagSet {
}
/**
- * Returns the TIFFTag from this set that is
- * associated with the given tag number, or null if
+ * Returns the {@code TIFFTag} from this set that is
+ * associated with the given tag number, or {@code null} if
* no tag exists for that number.
*
* @param tagNumber the number of the tag to be retrieved.
*
- * @return the numbered TIFFTag, or null.
+ * @return the numbered {@code TIFFTag}, or {@code null}.
*/
public TIFFTag getTag(int tagNumber) {
return allowedTagsByNumber.get(Integer.valueOf(tagNumber));
}
/**
- * Returns the TIFFTag having the given tag name, or
- * null if the named tag does not belong to this tag set.
+ * Returns the {@code TIFFTag} having the given tag name, or
+ * {@code null} if the named tag does not belong to this tag set.
*
* @param tagName the name of the tag to be retrieved, as a
- * String.
+ * {@code String}.
*
- * @return the named TIFFTag, or null.
+ * @return the named {@code TIFFTag}, or {@code null}.
*
- * @throws IllegalArgumentException if tagName is
- * null.
+ * @throws IllegalArgumentException if {@code tagName} is
+ * {@code null}.
*/
public TIFFTag getTag(String tagName) {
if (tagName == null) {
@@ -123,7 +123,7 @@ public class TIFFTagSet {
* Retrieves an unmodifiable numerically increasing set of tag numbers.
*
* The returned object is unmodifiable and contains the tag
- * numbers of all TIFFTags in this TIFFTagSet
+ * numbers of all {@code TIFFTag}s in this {@code TIFFTagSet}
* sorted into ascending order according to
* {@link Integer#compareTo(Object)}.
*
@@ -145,7 +145,7 @@ public class TIFFTagSet {
* Retrieves an unmodifiable lexicographically increasing set of tag names.
*
* The returned object is unmodifiable and contains the tag
- * names of all TIFFTags in this TIFFTagSet
+ * names of all {@code TIFFTag}s in this {@code TIFFTagSet}
* sorted into ascending order according to
* {@link String#compareTo(Object)}.
*
From 4e4a6d18abe0f4633947128e16c29987ce34dd99 Mon Sep 17 00:00:00 2001
From: Ambarish Rapte
Date: Mon, 15 Feb 2016 14:36:54 +0530
Subject: [PATCH 010/311] 8025001: setFocusTraversalPolicy() to
ContainerOrderFocusTraversalPolicy results in an infinite loop
Reviewed-by: ssadetsky, psadhukhan
---
.../ContainerOrderFocusTraversalPolicy.java | 4 +-
.../ContainerOrderFTPTest.java | 90 +++++++++++++++++++
2 files changed, 93 insertions(+), 1 deletion(-)
create mode 100644 jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java
diff --git a/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java b/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java
index d23e672779c..9b04496f65b 100644
--- a/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java
+++ b/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java
@@ -231,7 +231,9 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy
// Before all the checks below we first see if it's an FTP provider or a focus cycle root.
// If it's the case just go down cycle (if it's set to "implicit").
Component comp = getComponentDownCycle(aComponent, FORWARD_TRAVERSAL);
- if (comp != null) {
+ // Check if aComponent is focus-cycle-root's default Component, i.e.
+ // focus cycle root & focus-cycle-root's default Component is same.
+ if (comp != null && comp != aComponent) {
return comp;
}
diff --git a/jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java b/jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java
new file mode 100644
index 00000000000..5957204ee79
--- /dev/null
+++ b/jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+/*
+ @test
+ @bug 8025001
+ @summary Tests java.awt.ContainerOrderFocusTraversalPolicy functionality.
+ @run main ContainerOrderFTPTest
+*/
+
+import java.awt.Frame;
+import java.awt.Button;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.ContainerOrderFocusTraversalPolicy;
+
+public class ContainerOrderFTPTest {
+
+ private final ContainerOrderFocusTraversalPolicy coftp;
+ private final Frame frame;
+ private final Button b1;
+ private final Button b2;
+ private final String expectedTraversal;
+
+ public ContainerOrderFTPTest() {
+ expectedTraversal = "B1B2F1";
+ b1 = new Button("B1");
+ b2 = new Button("B2");
+ frame = new Frame("F1");
+
+ frame.setLayout(new FlowLayout());
+ frame.setSize(200, 200);
+ coftp = new ContainerOrderFocusTraversalPolicy();
+ frame.setFocusTraversalPolicy(coftp);
+ frame.add(b1);
+ frame.add(b2);
+ frame.setVisible(true);
+ }
+
+ public static void main(String[] args) throws Exception {
+ ContainerOrderFTPTest test = new ContainerOrderFTPTest();
+ test.performTest();
+ test.dispose();
+ }
+
+ public void performTest() {
+ int count = 0;
+ Component comp = coftp.getFirstComponent(frame);
+ String traversal = "";
+ do {
+ comp = coftp.getComponentAfter(frame, comp);
+ if (comp instanceof Button) {
+ traversal += ((Button)comp).getLabel();
+ } else if (comp instanceof Frame) {
+ traversal += ((Frame)comp).getTitle();
+ }
+ count++;
+ } while(count < 3);
+
+ if (!expectedTraversal.equals(traversal)) {
+ dispose();
+ throw new RuntimeException("Incorrect Traversal. Expected : "
+ + expectedTraversal + "Actual : " + traversal);
+ }
+ }
+
+ public void dispose() {
+ frame.dispose();
+ }
+}
From 0b936de72ace703e09d5f2100b8197a89d52123a Mon Sep 17 00:00:00 2001
From: Sergey Bylokhov
Date: Fri, 12 Feb 2016 16:08:39 +0300
Subject: [PATCH 011/311] 8130061: java.beans.EventHandler.create does not
specify how it fails when an EventHandler cannot be created
Reviewed-by: alanb
---
.../share/classes/java/beans/EventHandler.java | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java b/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java
index 6f1427fe54a..1ab720f7555 100644
--- a/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java
+++ b/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -526,8 +526,11 @@ public class EventHandler implements InvocationHandler {
* @throws NullPointerException if {@code listenerInterface} is null
* @throws NullPointerException if {@code target} is null
* @throws NullPointerException if {@code action} is null
- *
+ * @throws IllegalArgumentException if creating a Proxy for
+ * {@code listenerInterface} fails for any of the restrictions
+ * specified by {@link Proxy#newProxyInstance}
* @see #create(Class, Object, String, String)
+ * @see Proxy#newProxyInstance
*/
public static T create(Class listenerInterface,
Object target, String action)
@@ -584,8 +587,11 @@ public class EventHandler implements InvocationHandler {
* @throws NullPointerException if {@code listenerInterface} is null
* @throws NullPointerException if {@code target} is null
* @throws NullPointerException if {@code action} is null
- *
+ * @throws IllegalArgumentException if creating a Proxy for
+ * {@code listenerInterface} fails for any of the restrictions
+ * specified by {@link Proxy#newProxyInstance}
* @see #create(Class, Object, String, String, String)
+ * @see Proxy#newProxyInstance
*/
public static T create(Class listenerInterface,
Object target, String action,
@@ -675,8 +681,11 @@ public class EventHandler implements InvocationHandler {
* @throws NullPointerException if {@code listenerInterface} is null
* @throws NullPointerException if {@code target} is null
* @throws NullPointerException if {@code action} is null
- *
+ * @throws IllegalArgumentException if creating a Proxy for
+ * {@code listenerInterface} fails for any of the restrictions
+ * specified by {@link Proxy#newProxyInstance}
* @see EventHandler
+ * @see Proxy#newProxyInstance
*/
public static T create(Class listenerInterface,
Object target, String action,
From 8eb27fd4d39087b3f12cf7156ceedc9d6fd88cb7 Mon Sep 17 00:00:00 2001
From: Sergey Bylokhov
Date: Fri, 12 Feb 2016 16:09:39 +0300
Subject: [PATCH 012/311] 8136382: SimpleBeanInfo.loadImage succeeds when
running with a security manager
Reviewed-by: alanb
---
.../classes/java/beans/SimpleBeanInfo.java | 30 +++++++++++--------
1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java b/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java
index ddef0cffad5..ba2cbcd2dc9 100644
--- a/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java
+++ b/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -27,7 +27,8 @@ package java.beans;
import java.awt.Image;
import java.awt.Toolkit;
-import java.io.InputStream;
+import java.awt.image.ImageProducer;
+import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -171,19 +172,24 @@ public class SimpleBeanInfo implements BeanInfo {
}
/**
- * This is a utility method to help in loading icon images.
- * It takes the name of a resource file associated with the
- * current object's class file and loads an image object
- * from that file. Typically images will be GIFs.
+ * This is a utility method to help in loading icon images. It takes the
+ * name of a resource file associated with the current object's class file
+ * and loads an image object from that file. Typically images will be GIFs.
*
- * @param resourceName A pathname relative to the directory
- * holding the class file of the current class. For example,
- * "wombat.gif".
- * @return an image object. May be null if the load failed.
+ * @param resourceName A pathname relative to the directory holding the
+ * class file of the current class. For example, "wombat.gif".
+ * @return an image object or null if the resource is not found or the
+ * resource could not be loaded as an Image
*/
public Image loadImage(final String resourceName) {
- try (InputStream in = getClass().getResourceAsStream(resourceName)) {
- return Toolkit.getDefaultToolkit().createImage(in.readAllBytes());
+ try {
+ final URL url = getClass().getResource(resourceName);
+ if (url != null) {
+ final ImageProducer ip = (ImageProducer) url.getContent();
+ if (ip != null) {
+ return Toolkit.getDefaultToolkit().createImage(ip);
+ }
+ }
} catch (final Exception ignored) {
}
return null;
From 4458220d4a5b5c77ff2575c45ab18032d501a575 Mon Sep 17 00:00:00 2001
From: Vladimir Ivanov
Date: Mon, 15 Feb 2016 20:27:12 +0300
Subject: [PATCH 013/311] 8148994: Replacing MH::invokeBasic with a direct call
breaks LF customization
Reviewed-by: jrose, redestad
---
.../classes/java/lang/invoke/MethodHandleImpl.java | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
index ebaf2a393ad..9b4029cc7b5 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
@@ -778,8 +778,21 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
return (asTypeCache = wrapper);
}
+ // Customize target if counting happens for too long.
+ private int invocations = CUSTOMIZE_THRESHOLD;
+ private void maybeCustomizeTarget() {
+ int c = invocations;
+ if (c >= 0) {
+ if (c == 1) {
+ target.customize();
+ }
+ invocations = c - 1;
+ }
+ }
+
boolean countDown() {
int c = count;
+ maybeCustomizeTarget();
if (c <= 1) {
// Try to limit number of updates. MethodHandle.updateForm() doesn't guarantee LF update visibility.
if (isCounting) {
From 4ccb461831829d8e241ba9ae350da18d85e6119e Mon Sep 17 00:00:00 2001
From: Brian Burkhalter
Date: Mon, 15 Feb 2016 16:59:56 -0800
Subject: [PATCH 014/311] 8150204: (fs) Enhance
java/nio/file/Files/probeContentType/Basic.java debugging output
Add debugging information to the test.
Reviewed-by: alanb
---
.../file/Files/probeContentType/Basic.java | 80 ++++++++++++++++---
1 file changed, 68 insertions(+), 12 deletions(-)
diff --git a/jdk/test/java/nio/file/Files/probeContentType/Basic.java b/jdk/test/java/nio/file/Files/probeContentType/Basic.java
index 02298b48fef..ec90ed6b18c 100644
--- a/jdk/test/java/nio/file/Files/probeContentType/Basic.java
+++ b/jdk/test/java/nio/file/Files/probeContentType/Basic.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, 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,8 +29,9 @@
* @run main/othervm Basic
*/
-import java.nio.file.*;
import java.io.*;
+import java.nio.file.*;
+import java.util.stream.Stream;
/**
* Uses Files.probeContentType to probe html file, custom file type, and minimal
@@ -38,6 +39,9 @@ import java.io.*;
*/
public class Basic {
+ private static final boolean IS_UNIX =
+ ! System.getProperty("os.name").startsWith("Windows");
+
static Path createHtmlFile() throws IOException {
Path file = Files.createTempFile("foo", ".html");
try (OutputStream out = Files.newOutputStream(file)) {
@@ -51,10 +55,61 @@ public class Basic {
return Files.createTempFile("red", ".grape");
}
- static void checkContentTypes(String[] extensions, String[] expectedTypes)
+ private static int checkContentTypes(String expected, String actual) {
+ assert expected != null;
+ assert actual != null;
+
+ if (!expected.equals(actual)) {
+ if (IS_UNIX) {
+ Path userMimeTypes =
+ Paths.get(System.getProperty("user.home"), ".mime.types");
+ if (!Files.exists(userMimeTypes)) {
+ System.out.println(userMimeTypes + " does not exist");
+ } else if (!Files.isReadable(userMimeTypes)) {
+ System.out.println(userMimeTypes + " is not readable");
+ } else {
+ System.out.println(userMimeTypes + " contents:");
+ try (Stream lines = Files.lines(userMimeTypes)) {
+ lines.forEach(System.out::println);
+ System.out.println("");
+ } catch (IOException ioe) {
+ System.err.println("Problem reading "
+ + userMimeTypes);
+ }
+ }
+
+ Path etcMimeTypes = Paths.get("/etc/mime.types");
+ if (!Files.exists(etcMimeTypes)) {
+ System.out.println(etcMimeTypes + " does not exist");
+ } else if (!Files.isReadable(etcMimeTypes)) {
+ System.out.println(etcMimeTypes + " is not readable");
+ } else {
+ System.out.println(etcMimeTypes + " contents:");
+ try (Stream lines = Files.lines(etcMimeTypes)) {
+ lines.forEach(System.out::println);
+ System.out.println("");
+ } catch (IOException ioe) {
+ System.err.println("Problem reading "
+ + etcMimeTypes);
+ }
+ }
+ }
+
+ System.err.println("Expected \"" + expected
+ + "\" but obtained \""
+ + actual + "\"");
+
+ return 1;
+ }
+
+ return 0;
+ }
+
+ static int checkOSXContentTypes(String[] extensions, String[] expectedTypes)
throws IOException {
if (extensions.length != expectedTypes.length) {
- throw new IllegalArgumentException("Parameter array lengths differ");
+ throw new IllegalArgumentException
+ ("Parameter array lengths differ");
}
int failures = 0;
@@ -79,12 +134,11 @@ public class Basic {
}
}
- if (failures > 0) {
- throw new RuntimeException("Test failed!");
- }
+ return failures;
}
public static void main(String[] args) throws IOException {
+ int failures = 0;
// exercise default file type detector
Path file = createHtmlFile();
@@ -93,8 +147,7 @@ public class Basic {
if (type == null) {
System.err.println("Content type cannot be determined - test skipped");
} else {
- if (!type.equals("text/html"))
- throw new RuntimeException("Unexpected type: " + type);
+ failures += checkContentTypes("text/html", type);
}
} finally {
Files.delete(file);
@@ -106,8 +159,7 @@ public class Basic {
String type = Files.probeContentType(file);
if (type == null)
throw new RuntimeException("Custom file type detector not installed?");
- if (!type.equals("grape/unknown"))
- throw new RuntimeException("Unexpected type: " + type);
+ failures += checkContentTypes("grape/unknown", type);
} finally {
Files.delete(file);
}
@@ -122,7 +174,11 @@ public class Basic {
"image/jpeg", "audio/mpeg", "video/mp4", "application/pdf",
"image/png"
};
- checkContentTypes(extensions, expectedTypes);
+ failures += checkOSXContentTypes(extensions, expectedTypes);
+ }
+
+ if (failures > 0) {
+ throw new RuntimeException("Test failed!");
}
}
}
From 4054254344ded96254cc750a063f4159a4395457 Mon Sep 17 00:00:00 2001
From: Steve Drach
Date: Mon, 15 Feb 2016 17:47:53 -0800
Subject: [PATCH 015/311] 8132734: JDK 9 runtime changes to support
multi-release jar files
JEP 238 Multi-Release JAR Files runtime support
Reviewed-by: alanb, psandoz, sherman
---
.../classes/java/net/JarURLConnection.java | 8 +
.../classes/java/util/jar/Attributes.java | 10 +-
.../share/classes/java/util/jar/JarFile.java | 478 ++++++++++++++++--
.../share/classes/sun/misc/URLClassPath.java | 10 +-
.../sun/net/www/protocol/jar/URLJarFile.java | 27 +-
.../net/www/protocol/jar/JarFileFactory.java | 12 +-
.../net/www/protocol/jar/JarFileFactory.java | 12 +-
.../util/jar/JarFile/MultiReleaseJarAPI.java | 177 +++++++
.../MultiReleaseJarHttpProperties.java | 156 ++++++
.../jar/JarFile/MultiReleaseJarIterators.java | 228 +++++++++
.../JarFile/MultiReleaseJarProperties.java | 200 ++++++++
.../jar/JarFile/MultiReleaseJarSecurity.java | 108 ++++
.../jar/MultiReleaseJarURLConnection.java | 117 +++++
13 files changed, 1483 insertions(+), 60 deletions(-)
create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java
create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java
create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java
create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java
create mode 100644 jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java
create mode 100644 jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java
diff --git a/jdk/src/java.base/share/classes/java/net/JarURLConnection.java b/jdk/src/java.base/share/classes/java/net/JarURLConnection.java
index 70dedec795e..4c7e0ab6f94 100644
--- a/jdk/src/java.base/share/classes/java/net/JarURLConnection.java
+++ b/jdk/src/java.base/share/classes/java/net/JarURLConnection.java
@@ -173,6 +173,14 @@ public abstract class JarURLConnection extends URLConnection {
}
jarFileURL = new URL(spec.substring(0, separator++));
+ /*
+ * The url argument may have had a runtime fragment appended, so
+ * we need to add a runtime fragment to the jarFileURL to enable
+ * runtime versioning when the underlying jar file is opened.
+ */
+ if ("runtime".equals(url.getRef())) {
+ jarFileURL = new URL(jarFileURL, "#runtime");
+ }
entryName = null;
/* if ! is the last letter of the innerURL, entryName is null */
diff --git a/jdk/src/java.base/share/classes/java/util/jar/Attributes.java b/jdk/src/java.base/share/classes/java/util/jar/Attributes.java
index f2a01acbdba..b99755b4bb6 100644
--- a/jdk/src/java.base/share/classes/java/util/jar/Attributes.java
+++ b/jdk/src/java.base/share/classes/java/util/jar/Attributes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -646,5 +646,13 @@ public class Attributes implements Map, Cloneable {
* manifest attribute used for package versioning.
*/
public static final Name SPECIFICATION_VENDOR = new Name("Specification-Vendor");
+
+ /**
+ * {@code Name} object for {@code Multi-Release}
+ * manifest attribute that indicates this is a multi-release JAR file.
+ *
+ * @since 9
+ */
+ public static final Name MULTI_RELEASE = new Name("Multi-Release");
}
}
diff --git a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java
index 62734ceefbd..d5032fed2fd 100644
--- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java
+++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java
@@ -28,6 +28,7 @@ package java.util.jar;
import java.io.*;
import java.lang.ref.SoftReference;
import java.net.URL;
+import java.security.PrivilegedAction;
import java.util.*;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@@ -37,28 +38,91 @@ import java.security.cert.Certificate;
import java.security.AccessController;
import java.security.CodeSource;
import jdk.internal.misc.SharedSecrets;
-import sun.security.action.GetPropertyAction;
import sun.security.util.ManifestEntryVerifier;
import sun.security.util.SignatureFileVerifier;
+import static java.util.jar.Attributes.Name.MULTI_RELEASE;
+
/**
* The {@code JarFile} class is used to read the contents of a jar file
* from any file that can be opened with {@code java.io.RandomAccessFile}.
* It extends the class {@code java.util.zip.ZipFile} with support
- * for reading an optional {@code Manifest} entry. The
- * {@code Manifest} can be used to specify meta-information about the
- * jar file and its entries.
+ * for reading an optional {@code Manifest} entry, and support for
+ * processing multi-release jar files. The {@code Manifest} can be used
+ * to specify meta-information about the jar file and its entries.
+ *
+ * A multi-release jar file is a jar file that contains
+ * a manifest with a main attribute named "Multi-Release",
+ * a set of "base" entries, some of which are public classes with public
+ * or protected methods that comprise the public interface of the jar file,
+ * and a set of "versioned" entries contained in subdirectories of the
+ * "META-INF/versions" directory. The versioned entries are partitioned by the
+ * major version of the Java platform. A versioned entry, with a version
+ * {@code n}, {@code 8 < n}, in the "META-INF/versions/{n}" directory overrides
+ * the base entry as well as any entry with a version number {@code i} where
+ * {@code 8 < i < n}.
+ *
+ *
By default, a {@code JarFile} for a multi-release jar file is configured
+ * to process the multi-release jar file as if it were a plain (unversioned) jar
+ * file, and as such an entry name is associated with at most one base entry.
+ * The {@code JarFile} may be configured to process a multi-release jar file by
+ * creating the {@code JarFile} with the
+ * {@link JarFile#JarFile(File, boolean, int, Release)} constructor. The
+ * {@code Release} object sets a maximum version used when searching for
+ * versioned entries. When so configured, an entry name
+ * can correspond with at most one base entry and zero or more versioned
+ * entries. A search is required to associate the entry name with the latest
+ * versioned entry whose version is less than or equal to the maximum version
+ * (see {@link #getEntry(String)}).
+ *
+ *
Class loaders that utilize {@code JarFile} to load classes from the
+ * contents of {@code JarFile} entries should construct the {@code JarFile}
+ * by invoking the {@link JarFile#JarFile(File, boolean, int, Release)}
+ * constructor with the value {@code Release.RUNTIME} assigned to the last
+ * argument. This assures that classes compatible with the major
+ * version of the running JVM are loaded from multi-release jar files.
+ *
+ *
If the verify flag is on when opening a signed jar file, the content of
+ * the file is verified against its signature embedded inside the file. Please
+ * note that the verification process does not include validating the signer's
+ * certificate. A caller should inspect the return value of
+ * {@link JarEntry#getCodeSigners()} to further determine if the signature
+ * can be trusted.
*
*
Unless otherwise noted, passing a {@code null} argument to a constructor
* or method in this class will cause a {@link NullPointerException} to be
* thrown.
*
- * If the verify flag is on when opening a signed jar file, the content of the
- * file is verified against its signature embedded inside the file. Please note
- * that the verification process does not include validating the signer's
- * certificate. A caller should inspect the return value of
- * {@link JarEntry#getCodeSigners()} to further determine if the signature
- * can be trusted.
+ * @implNote
+ *
+ * If the API can not be used to configure a {@code JarFile} (e.g. to override
+ * the configuration of a compiled application or library), two {@code System}
+ * properties are available.
+ *
+ *
+ * {@code jdk.util.jar.version} can be assigned a value that is the
+ * {@code String} representation of a non-negative integer
+ * {@code <= Version.current().major()}. The value is used to set the effective
+ * runtime version to something other than the default value obtained by
+ * evaluating {@code Version.current().major()}. The effective runtime version
+ * is the version that the {@link JarFile#JarFile(File, boolean, int, Release)}
+ * constructor uses when the value of the last argument is
+ * {@code Release.RUNTIME}.
+ *
+ *
+ * {@code jdk.util.jar.enableMultiRelease} can be assigned one of the three
+ * {@code String} values true , false , or force . The
+ * value true , the default value, enables multi-release jar file
+ * processing. The value false disables multi-release jar processing,
+ * ignoring the "Multi-Release" manifest attribute, and the versioned
+ * directories in a multi-release jar file if they exist. Furthermore,
+ * the method {@link JarFile#isMultiRelease()} returns false . The value
+ * force causes the {@code JarFile} to be initialized to runtime
+ * versioning after construction. It effectively does the same as this code:
+ * {@code (new JarFile(File, boolean, int, Release.RUNTIME)}.
+ *
+ *
+ *
*
* @author David Connelly
* @see Manifest
@@ -68,26 +132,126 @@ import sun.security.util.SignatureFileVerifier;
*/
public
class JarFile extends ZipFile {
+ private final static int BASE_VERSION;
+ private final static int RUNTIME_VERSION;
+ private final static boolean MULTI_RELEASE_ENABLED;
+ private final static boolean MULTI_RELEASE_FORCED;
private SoftReference manRef;
private JarEntry manEntry;
private JarVerifier jv;
private boolean jvInitialized;
private boolean verify;
+ private final int version;
+ private boolean notVersioned;
+ private final boolean runtimeVersioned;
// indicates if Class-Path attribute present (only valid if hasCheckedSpecialAttributes true)
private boolean hasClassPathAttribute;
// true if manifest checked for special attributes
private volatile boolean hasCheckedSpecialAttributes;
- // Set up JavaUtilJarAccess in SharedSecrets
static {
+ // Set up JavaUtilJarAccess in SharedSecrets
SharedSecrets.setJavaUtilJarAccess(new JavaUtilJarAccessImpl());
+
+ BASE_VERSION = 8; // one less than lowest version for versioned entries
+ RUNTIME_VERSION = AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public Integer run() {
+ Integer v = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 Version integrated
+ Integer i = Integer.getInteger("jdk.util.jar.version", v);
+ i = i < 0 ? 0 : i;
+ return i > v ? v : i;
+ }
+ }
+ );
+ String multi_release = AccessController.doPrivileged(
+ new PrivilegedAction() {
+ public String run() {
+ return System.getProperty("jdk.util.jar.enableMultiRelease", "true");
+ }
+ }
+ );
+ switch (multi_release) {
+ case "true":
+ default:
+ MULTI_RELEASE_ENABLED = true;
+ MULTI_RELEASE_FORCED = false;
+ break;
+ case "false":
+ MULTI_RELEASE_ENABLED = false;
+ MULTI_RELEASE_FORCED = false;
+ break;
+ case "force":
+ MULTI_RELEASE_ENABLED = true;
+ MULTI_RELEASE_FORCED = true;
+ break;
+ }
}
+ /**
+ * A set of constants that represent the entries in either the base directory
+ * or one of the versioned directories in a multi-release jar file. It's
+ * possible for a multi-release jar file to contain versioned directories
+ * that are not represented by the constants of the {@code Release} enum.
+ * In those cases, the entries will not be located by this {@code JarFile}
+ * through the aliasing mechanism, but they can be directly accessed by
+ * specifying the full path name of the entry.
+ *
+ * @since 9
+ */
+ public enum Release {
+ /**
+ * Represents unversioned entries, or entries in "regular", as opposed
+ * to multi-release jar files.
+ */
+ BASE(BASE_VERSION),
+
+ /**
+ * Represents entries found in the META-INF/versions/9 directory of a
+ * multi-release jar file.
+ */
+ VERSION_9(9),
+
+ // fill in the "blanks" for future releases
+
+ /**
+ * Represents entries found in the META-INF/versions/{n} directory of a
+ * multi-release jar file, where {@code n} is the effective runtime
+ * version of the jar file.
+ *
+ * @implNote
+ *
+ * The effective runtime version is determined
+ * by evaluating {@code Version.current().major()} or by using the value
+ * of the {@code jdk.util.jar.version} System property if it exists.
+ *
+ */
+ RUNTIME(RUNTIME_VERSION);
+
+ Release(int version) {
+ this.version = version;
+ }
+
+ private static Release valueOf(int version) {
+ return version <= BASE.value() ? BASE : valueOf("VERSION_" + version);
+ }
+
+ private final int version;
+
+ private int value() {
+ return this.version;
+ }
+ }
+
+ private static final String META_INF = "META-INF/";
+
+ private static final String META_INF_VERSIONS = META_INF + "versions/";
+
/**
* The JAR manifest file name.
*/
- public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
+ public static final String MANIFEST_NAME = META_INF + "MANIFEST.MF";
/**
* Creates a new {@code JarFile} to read from the specified
@@ -129,7 +293,6 @@ class JarFile extends ZipFile {
this(file, true, ZipFile.OPEN_READ);
}
-
/**
* Creates a new {@code JarFile} to read from the specified
* {@code File} object.
@@ -144,7 +307,6 @@ class JarFile extends ZipFile {
this(file, verify, ZipFile.OPEN_READ);
}
-
/**
* Creates a new {@code JarFile} to read from the specified
* {@code File} object in the specified mode. The mode argument
@@ -162,10 +324,104 @@ class JarFile extends ZipFile {
* @since 1.3
*/
public JarFile(File file, boolean verify, int mode) throws IOException {
- super(file, mode);
- this.verify = verify;
+ this(file, verify, mode, Release.BASE);
+ this.notVersioned = true;
}
+ /**
+ * Creates a new {@code JarFile} to read from the specified
+ * {@code File} object in the specified mode. The mode argument
+ * must be either {@code OPEN_READ} or {@code OPEN_READ | OPEN_DELETE}.
+ * The version argument configures the {@code JarFile} for processing
+ * multi-release jar files.
+ *
+ * @param file the jar file to be opened for reading
+ * @param verify whether or not to verify the jar file if
+ * it is signed.
+ * @param mode the mode in which the file is to be opened
+ * @param version specifies the release version for a multi-release jar file
+ * @throws IOException if an I/O error has occurred
+ * @throws IllegalArgumentException
+ * if the {@code mode} argument is invalid
+ * @throws SecurityException if access to the file is denied
+ * by the SecurityManager
+ * @throws NullPointerException if {@code version} is {@code null}
+ * @since 9
+ */
+ public JarFile(File file, boolean verify, int mode, Release version) throws IOException {
+ super(file, mode);
+ Objects.requireNonNull(version);
+ this.verify = verify;
+ // version applies to multi-release jar files, ignored for regular jar files
+ this.version = MULTI_RELEASE_FORCED ? RUNTIME_VERSION : version.value();
+ this.runtimeVersioned = version == Release.RUNTIME;
+ assert runtimeVersionExists();
+ }
+
+ private boolean runtimeVersionExists() {
+ int version = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 integrated
+ try {
+ Release.valueOf(version);
+ return true;
+ } catch (IllegalArgumentException x) {
+ System.err.println("No JarFile.Release object for release " + version);
+ return false;
+ }
+ }
+
+ /**
+ * Returns the maximum version used when searching for versioned entries.
+ *
+ * @return the maximum version, or {@code Release.BASE} if this jar file is
+ * processed as if it is an unversioned jar file or is not a
+ * multi-release jar file
+ * @since 9
+ */
+ public final Release getVersion() {
+ if (isMultiRelease()) {
+ return runtimeVersioned ? Release.RUNTIME : Release.valueOf(version);
+ } else {
+ return Release.BASE;
+ }
+ }
+
+ /**
+ * Indicates whether or not this jar file is a multi-release jar file.
+ *
+ * @return true if this JarFile is a multi-release jar file
+ * @since 9
+ */
+ public final boolean isMultiRelease() {
+ // do not call this code in a constructor because some subclasses use
+ // lazy loading of manifest so it won't be available at construction time
+ if (MULTI_RELEASE_ENABLED) {
+ // Doubled-checked locking pattern
+ Boolean result = isMultiRelease;
+ if (result == null) {
+ synchronized (this) {
+ result = isMultiRelease;
+ if (result == null) {
+ Manifest man = null;
+ try {
+ man = getManifest();
+ } catch (IOException e) {
+ //Ignored, manifest cannot be read
+ }
+ isMultiRelease = result = (man != null)
+ && man.getMainAttributes().containsKey(MULTI_RELEASE)
+ ? Boolean.TRUE : Boolean.FALSE;
+ }
+ }
+ }
+ return result == Boolean.TRUE;
+ } else {
+ return false;
+ }
+ }
+ // the following field, isMultiRelease, should only be used in the method
+ // isMultiRelease(), like a static local
+ private volatile Boolean isMultiRelease; // is jar multi-release?
+
/**
* Returns the jar file manifest, or {@code null} if none.
*
@@ -209,40 +465,87 @@ class JarFile extends ZipFile {
}
/**
- * Returns the {@code JarEntry} for the given entry name or
+ * Returns the {@code JarEntry} for the given base entry name or
* {@code null} if not found.
*
+ * If this {@code JarFile} is a multi-release jar file and is configured
+ * to be processed as such, then a search is performed to find and return
+ * a {@code JarEntry} that is the latest versioned entry associated with the
+ * given entry name. The returned {@code JarEntry} is the versioned entry
+ * corresponding to the given base entry name prefixed with the string
+ * {@code "META-INF/versions/{n}/"}, for the largest value of {@code n} for
+ * which an entry exists. If such a versioned entry does not exist, then
+ * the {@code JarEntry} for the base entry is returned, otherwise
+ * {@code null} is returned if no entries are found. The initial value for
+ * the version {@code n} is the maximum version as returned by the method
+ * {@link JarFile#getVersion()}.
+ *
* @param name the jar file entry name
- * @return the {@code JarEntry} for the given entry name or
- * {@code null} if not found.
+ * @return the {@code JarEntry} for the given entry name, or
+ * the versioned entry name, or {@code null} if not found
*
* @throws IllegalStateException
* may be thrown if the jar file has been closed
*
* @see java.util.jar.JarEntry
+ *
+ * @implSpec
+ *
+ * This implementation invokes {@link JarFile#getEntry(String)}.
+ *
*/
public JarEntry getJarEntry(String name) {
return (JarEntry)getEntry(name);
}
/**
- * Returns the {@code ZipEntry} for the given entry name or
+ * Returns the {@code ZipEntry} for the given base entry name or
* {@code null} if not found.
*
+ * If this {@code JarFile} is a multi-release jar file and is configured
+ * to be processed as such, then a search is performed to find and return
+ * a {@code ZipEntry} that is the latest versioned entry associated with the
+ * given entry name. The returned {@code ZipEntry} is the versioned entry
+ * corresponding to the given base entry name prefixed with the string
+ * {@code "META-INF/versions/{n}/"}, for the largest value of {@code n} for
+ * which an entry exists. If such a versioned entry does not exist, then
+ * the {@code ZipEntry} for the base entry is returned, otherwise
+ * {@code null} is returned if no entries are found. The initial value for
+ * the version {@code n} is the maximum version as returned by the method
+ * {@link JarFile#getVersion()}.
+ *
* @param name the jar file entry name
* @return the {@code ZipEntry} for the given entry name or
- * {@code null} if not found
+ * the versioned entry name or {@code null} if not found
*
* @throws IllegalStateException
* may be thrown if the jar file has been closed
*
* @see java.util.zip.ZipEntry
+ *
+ * @implSpec
+ *
+ * This implementation may return a versioned entry for the requested name
+ * even if there is not a corresponding base entry. This can occur
+ * if there is a private or package-private versioned entry that matches.
+ * If a subclass overrides this method, assure that the override method
+ * invokes {@code super.getEntry(name)} to obtain all versioned entries.
+ *
*/
public ZipEntry getEntry(String name) {
ZipEntry ze = super.getEntry(name);
if (ze != null) {
return new JarFileEntry(ze);
}
+ // no matching base entry, but maybe there is a versioned entry,
+ // like a new private class
+ if (isMultiRelease()) {
+ ze = new ZipEntry(name);
+ ZipEntry vze = getVersionedEntry(ze);
+ if (ze != vze) {
+ return new JarFileEntry(name, vze);
+ }
+ }
return null;
}
@@ -250,14 +553,42 @@ class JarFile extends ZipFile {
Iterator
{
final Enumeration extends ZipEntry> e = JarFile.super.entries();
+ ZipEntry ze;
public boolean hasNext() {
- return e.hasMoreElements();
+ if (notVersioned) {
+ return e.hasMoreElements();
+ }
+ if (ze != null) {
+ return true;
+ }
+ return findNext();
+ }
+
+ private boolean findNext() {
+ while (e.hasMoreElements()) {
+ ZipEntry ze2 = e.nextElement();
+ if (!ze2.getName().startsWith(META_INF_VERSIONS)) {
+ ze = ze2;
+ return true;
+ }
+ }
+ return false;
}
public JarEntry next() {
- ZipEntry ze = e.nextElement();
- return new JarFileEntry(ze);
+ ZipEntry ze2;
+
+ if (notVersioned) {
+ ze2 = e.nextElement();
+ return new JarFileEntry(ze2.getName(), ze2);
+ }
+ if (ze != null || findNext()) {
+ ze2 = ze;
+ ze = null;
+ return new JarFileEntry(ze2);
+ }
+ throw new NoSuchElementException();
}
public boolean hasMoreElements() {
@@ -274,7 +605,19 @@ class JarFile extends ZipFile {
}
/**
- * Returns an enumeration of the jar file entries.
+ * Returns an enumeration of the jar file entries. The set of entries
+ * returned depends on whether or not the jar file is a multi-release jar
+ * file, and on the constructor used to create the {@code JarFile}. If the
+ * jar file is not a multi-release jar file, all entries are returned,
+ * regardless of how the {@code JarFile} is created. If the constructor
+ * does not take a {@code Release} argument, all entries are returned.
+ * If the jar file is a multi-release jar file and the constructor takes a
+ * {@code Release} argument, then the set of entries returned is equivalent
+ * to the set of entries that would be returned if the set was built by
+ * invoking {@link JarFile#getEntry(String)} or
+ * {@link JarFile#getJarEntry(String)} with the name of each base entry in
+ * the jar file. A base entry is an entry whose path name does not start
+ * with "META-INF/versions/".
*
* @return an enumeration of the jar file entries
* @throws IllegalStateException
@@ -285,10 +628,21 @@ class JarFile extends ZipFile {
}
/**
- * Returns an ordered {@code Stream} over the jar file entries.
+ * Returns an ordered {@code Stream} over all the jar file entries.
* Entries appear in the {@code Stream} in the order they appear in
- * the central directory of the jar file.
- *
+ * the central directory of the jar file. The set of entries
+ * returned depends on whether or not the jar file is a multi-release jar
+ * file, and on the constructor used to create the {@code JarFile}. If the
+ * jar file is not a multi-release jar file, all entries are returned,
+ * regardless of how the {@code JarFile} is created. If the constructor
+ * does not take a {@code Release} argument, all entries are returned.
+ * If the jar file is a multi-release jar file and the constructor takes a
+ * {@code Release} argument, then the set of entries returned is equivalent
+ * to the set of entries that would be returned if the set was built by
+ * invoking {@link JarFile#getEntry(String)} or
+ * {@link JarFile#getJarEntry(String)} with the name of each base entry in
+ * the jar file. A base entry is an entry whose path name does not start
+ * with "META-INF/versions/".
* @return an ordered {@code Stream} of entries in this jar file
* @throws IllegalStateException if the jar file has been closed
* @since 1.8
@@ -300,14 +654,44 @@ class JarFile extends ZipFile {
Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
}
+ private ZipEntry searchForVersionedEntry(final int version, String name) {
+ ZipEntry vze = null;
+ String sname = "/" + name;
+ int i = version;
+ while (i > BASE_VERSION) {
+ vze = super.getEntry(META_INF_VERSIONS + i + sname);
+ if (vze != null) break;
+ i--;
+ }
+ return vze;
+ }
+
+ private ZipEntry getVersionedEntry(ZipEntry ze) {
+ ZipEntry vze = null;
+ if (version > BASE_VERSION && !ze.isDirectory()) {
+ String name = ze.getName();
+ if (!name.startsWith(META_INF)) {
+ vze = searchForVersionedEntry(version, name);
+ }
+ }
+ return vze == null ? ze : vze;
+ }
+
private class JarFileEntry extends JarEntry {
+ final private String name;
+
JarFileEntry(ZipEntry ze) {
- super(ze);
+ super(isMultiRelease() ? getVersionedEntry(ze) : ze);
+ this.name = ze.getName();
+ }
+ JarFileEntry(String name, ZipEntry vze) {
+ super(vze);
+ this.name = name;
}
public Attributes getAttributes() throws IOException {
Manifest man = JarFile.this.getManifest();
if (man != null) {
- return man.getAttributes(getName());
+ return man.getAttributes(super.getName());
} else {
return null;
}
@@ -319,7 +703,7 @@ class JarFile extends ZipFile {
throw new RuntimeException(e);
}
if (certs == null && jv != null) {
- certs = jv.getCerts(JarFile.this, this);
+ certs = jv.getCerts(JarFile.this, reifiedEntry());
}
return certs == null ? null : certs.clone();
}
@@ -330,10 +714,22 @@ class JarFile extends ZipFile {
throw new RuntimeException(e);
}
if (signers == null && jv != null) {
- signers = jv.getCodeSigners(JarFile.this, this);
+ signers = jv.getCodeSigners(JarFile.this, reifiedEntry());
}
return signers == null ? null : signers.clone();
}
+ JarFileEntry reifiedEntry() {
+ if (isMultiRelease()) {
+ String entryName = super.getName();
+ return entryName.equals(this.name) ? this : new JarFileEntry(entryName, this);
+ }
+ return this;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
}
/*
@@ -491,12 +887,19 @@ class JarFile extends ZipFile {
// wrap a verifier stream around the real stream
return new JarVerifier.VerifierStream(
getManifestFromReference(),
- ze instanceof JarFileEntry ?
- (JarEntry) ze : getJarEntry(ze.getName()),
+ verifiableEntry(ze),
super.getInputStream(ze),
jv);
}
+ private JarEntry verifiableEntry(ZipEntry ze) {
+ if (!(ze instanceof JarFileEntry)) {
+ ze = getJarEntry(ze.getName());
+ }
+ // assure the name and entry match for verification
+ return ze == null ? null : ((JarFileEntry)ze).reifiedEntry();
+ }
+
// Statics for hand-coded Boyer-Moore search
private static final char[] CLASSPATH_CHARS = {'c','l','a','s','s','-','p','a','t','h'};
// The bad character shift for "class-path"
@@ -523,7 +926,7 @@ class JarFile extends ZipFile {
private JarEntry getManEntry() {
if (manEntry == null) {
// First look up manifest entry using standard name
- manEntry = getJarEntry(MANIFEST_NAME);
+ ZipEntry manEntry = super.getEntry(MANIFEST_NAME);
if (manEntry == null) {
// If not found, then iterate through all the "META-INF/"
// entries to find a match.
@@ -531,12 +934,15 @@ class JarFile extends ZipFile {
if (names != null) {
for (String name : names) {
if (MANIFEST_NAME.equals(name.toUpperCase(Locale.ENGLISH))) {
- manEntry = getJarEntry(name);
+ manEntry = super.getEntry(name);
break;
}
}
}
}
+ this.manEntry = (manEntry == null)
+ ? null
+ : new JarFileEntry(manEntry.getName(), manEntry);
}
return manEntry;
}
diff --git a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java
index 1ad9a2776b6..01afb44a159 100644
--- a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java
+++ b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java
@@ -63,6 +63,7 @@ import java.util.jar.JarEntry;
import java.util.jar.Manifest;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
+import java.util.zip.ZipFile;
import jdk.internal.jimage.ImageLocation;
import jdk.internal.jimage.ImageReader;
@@ -727,9 +728,10 @@ public class URLClassPath {
if (!p.exists()) {
throw new FileNotFoundException(p.getPath());
}
- return checkJar(new JarFile(p.getPath()));
+ return checkJar(new JarFile(new File(p.getPath()), true, ZipFile.OPEN_READ,
+ JarFile.Release.RUNTIME));
}
- URLConnection uc = getBaseURL().openConnection();
+ URLConnection uc = (new URL(getBaseURL(), "#runtime")).openConnection();
uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION);
JarFile jarFile = ((JarURLConnection)uc).getJarFile();
return checkJar(jarFile);
@@ -756,7 +758,9 @@ public class URLClassPath {
final URL url;
try {
- url = new URL(getBaseURL(), ParseUtil.encodePath(name, false));
+ // add #runtime fragment to tell JarURLConnection to use
+ // runtime versioning if the underlying jar file is multi-release
+ url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime");
if (check) {
URLClassPath.check(url);
}
diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java
index 1e8697ba237..fe1a1f3c8f2 100644
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java
+++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java
@@ -65,9 +65,10 @@ public class URLJarFile extends JarFile {
}
static JarFile getJarFile(URL url, URLJarFileCloseController closeController) throws IOException {
- if (isFileURL(url))
- return new URLJarFile(url, closeController);
- else {
+ if (isFileURL(url)) {
+ Release version = "runtime".equals(url.getRef()) ? Release.RUNTIME : Release.BASE;
+ return new URLJarFile(url, closeController, version);
+ } else {
return retrieve(url, closeController);
}
}
@@ -89,8 +90,13 @@ public class URLJarFile extends JarFile {
this.closeController = closeController;
}
- private URLJarFile(URL url, URLJarFileCloseController closeController) throws IOException {
- super(ParseUtil.decode(url.getFile()));
+ private URLJarFile(File file, URLJarFileCloseController closeController, Release version) throws IOException {
+ super(file, true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE, version);
+ this.closeController = closeController;
+ }
+
+ private URLJarFile(URL url, URLJarFileCloseController closeController, Release version) throws IOException {
+ super(new File(ParseUtil.decode(url.getFile())), true, ZipFile.OPEN_READ, version);
this.closeController = closeController;
}
@@ -175,14 +181,6 @@ public class URLJarFile extends JarFile {
return false;
}
- /**
- * Given a URL, retrieves a JAR file, caches it to disk, and creates a
- * cached JAR file object.
- */
- private static JarFile retrieve(final URL url) throws IOException {
- return retrieve(url, null);
- }
-
/**
* Given a URL, retrieves a JAR file, caches it to disk, and creates a
* cached JAR file object.
@@ -202,6 +200,7 @@ public class URLJarFile extends JarFile {
{
JarFile result = null;
+ Release version = "runtime".equals(url.getRef()) ? Release.RUNTIME : Release.BASE;
/* get the stream before asserting privileges */
try (final InputStream in = url.openConnection().getInputStream()) {
@@ -211,7 +210,7 @@ public class URLJarFile extends JarFile {
Path tmpFile = Files.createTempFile("jar_cache", null);
try {
Files.copy(in, tmpFile, StandardCopyOption.REPLACE_EXISTING);
- JarFile jarFile = new URLJarFile(tmpFile.toFile(), closeController);
+ JarFile jarFile = new URLJarFile(tmpFile.toFile(), closeController, version);
tmpFile.toFile().deleteOnExit();
return jarFile;
} catch (Throwable thr) {
diff --git a/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java
index 559fda4144f..2001c382324 100644
--- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java
+++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java
@@ -85,7 +85,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController {
synchronized (instance) {
result = getCachedJarFile(url);
if (result == null) {
- fileCache.put(URLUtil.urlNoFragString(url), local_result);
+ fileCache.put(urlKey(url), local_result);
urlCache.put(local_result, url);
result = local_result;
} else {
@@ -113,13 +113,13 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController {
synchronized (instance) {
URL urlRemoved = urlCache.remove(jarFile);
if (urlRemoved != null)
- fileCache.remove(URLUtil.urlNoFragString(urlRemoved));
+ fileCache.remove(urlKey(urlRemoved));
}
}
private JarFile getCachedJarFile(URL url) {
assert Thread.holdsLock(instance);
- JarFile result = fileCache.get(URLUtil.urlNoFragString(url));
+ JarFile result = fileCache.get(urlKey(url));
/* if the JAR file is cached, the permission will always be there */
if (result != null) {
@@ -149,6 +149,12 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController {
return result;
}
+ private String urlKey(URL url) {
+ String urlstr = URLUtil.urlNoFragString(url);
+ if ("runtime".equals(url.getRef())) urlstr += "#runtime";
+ return urlstr;
+ }
+
private Permission getPermission(JarFile jarFile) {
try {
URLConnection uc = getConnection(jarFile);
diff --git a/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java
index 07db32fc079..91bf5388460 100644
--- a/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java
+++ b/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java
@@ -95,7 +95,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController {
synchronized (instance) {
result = getCachedJarFile(url);
if (result == null) {
- fileCache.put(URLUtil.urlNoFragString(url), local_result);
+ fileCache.put(urlKey(url), local_result);
urlCache.put(local_result, url);
result = local_result;
} else {
@@ -123,13 +123,13 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController {
synchronized (instance) {
URL urlRemoved = urlCache.remove(jarFile);
if (urlRemoved != null)
- fileCache.remove(URLUtil.urlNoFragString(urlRemoved));
+ fileCache.remove(urlKey(urlRemoved));
}
}
private JarFile getCachedJarFile(URL url) {
assert Thread.holdsLock(instance);
- JarFile result = fileCache.get(URLUtil.urlNoFragString(url));
+ JarFile result = fileCache.get(urlKey(url));
/* if the JAR file is cached, the permission will always be there */
if (result != null) {
@@ -159,6 +159,12 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController {
return result;
}
+ private String urlKey(URL url) {
+ String urlstr = URLUtil.urlNoFragString(url);
+ if ("runtime".equals(url.getRef())) urlstr += "#runtime";
+ return urlstr;
+ }
+
private Permission getPermission(JarFile jarFile) {
try {
URLConnection uc = getConnection(jarFile);
diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java
new file mode 100644
index 00000000000..7f7653e9eab
--- /dev/null
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8132734
+ * @summary Test the extended API and the aliasing additions in JarFile that
+ * support multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarAPI
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import static java.util.jar.JarFile.Release;
+import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+public class MultiReleaseJarAPI {
+ String userdir = System.getProperty("user.dir",".");
+ File unversioned = new File(userdir, "unversioned.jar");
+ File multirelease = new File(userdir, "multi-release.jar");
+ File signedmultirelease = new File(userdir, "signed-multi-release.jar");
+ Release[] values = JarFile.Release.values();
+
+
+ @BeforeClass
+ public void initialize() throws Exception {
+ CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
+ creator.compileEntries();
+ creator.buildUnversionedJar();
+ creator.buildMultiReleaseJar();
+ creator.buildSignedMultiReleaseJar();
+ }
+
+ @AfterClass
+ public void close() throws IOException {
+ Files.delete(unversioned.toPath());
+ Files.delete(multirelease.toPath());
+ Files.delete(signedmultirelease.toPath());
+ }
+
+ @Test
+ public void isMultiReleaseJar() throws Exception {
+ try (JarFile jf = new JarFile(unversioned)) {
+ Assert.assertFalse(jf.isMultiRelease());
+ }
+
+ try (JarFile jf = new JarFile(multirelease)) {
+ Assert.assertTrue(jf.isMultiRelease());
+ }
+ }
+
+ @Test
+ public void testVersioning() throws Exception {
+ // multi-release jar
+ JarFile jar = new JarFile(multirelease);
+ Assert.assertEquals(Release.BASE, jar.getVersion());
+ jar.close();
+
+ for (Release value : values) {
+ System.err.println("test versioning for Release " + value);
+ try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, value)) {
+ Assert.assertEquals(value, jf.getVersion());
+ }
+ }
+
+ // regular, unversioned, jar
+ for (Release value : values) {
+ try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, value)) {
+ Assert.assertEquals(Release.BASE, jf.getVersion());
+ }
+ }
+
+ // assure that we have a Release object corresponding to the actual runtime version
+ String version = "VERSION_" + jdkMajorVersion();
+ boolean runtimeVersionExists = false;
+ for (Release value : values) {
+ if (version.equals(value.name())) runtimeVersionExists = true;
+ }
+ Assert.assertTrue(runtimeVersionExists);
+ }
+
+ @Test
+ public void testAliasing() throws Exception {
+ for (Release value : values) {
+ System.err.println("test aliasing for Release " + value);
+ String name = value.name();
+ String prefix;
+ if (name.equals("BASE")) {
+ prefix = "";
+ } else if (name.equals("RUNTIME")) {
+ prefix = "META-INF/versions/" + jdkMajorVersion() + "/";
+ } else {
+ prefix = "META-INF/versions/" + name.substring(8) + "/";
+ }
+ // test both multi-release jars
+ readAndCompare(multirelease, value, "README", prefix + "README");
+ readAndCompare(multirelease, value, "version/Version.class", prefix + "version/Version.class");
+ // and signed multi-release jars
+ readAndCompare(signedmultirelease, value, "README", prefix + "README");
+ readAndCompare(signedmultirelease, value, "version/Version.class", prefix + "version/Version.class");
+ }
+ }
+
+ private void readAndCompare(File jar, Release version, String name, String realName) throws Exception {
+ byte[] baseBytes;
+ byte[] versionedBytes;
+ try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, Release.BASE)) {
+ ZipEntry ze = jf.getEntry(realName);
+ try (InputStream is = jf.getInputStream(ze)) {
+ baseBytes = is.readAllBytes();
+ }
+ }
+ assert baseBytes.length > 0;
+
+ try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, version)) {
+ ZipEntry ze = jf.getEntry(name);
+ try (InputStream is = jf.getInputStream(ze)) {
+ versionedBytes = is.readAllBytes();
+ }
+ }
+ assert versionedBytes.length > 0;
+
+ Assert.assertTrue(Arrays.equals(baseBytes, versionedBytes));
+ }
+
+ @Test
+ public void testNames() throws Exception {
+ String rname = "version/Version.class";
+ String vname = "META-INF/versions/9/version/Version.class";
+ ZipEntry ze1;
+ ZipEntry ze2;
+ try (JarFile jf = new JarFile(multirelease)) {
+ ze1 = jf.getEntry(vname);
+ }
+ Assert.assertEquals(ze1.getName(), vname);
+ try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) {
+ ze2 = jf.getEntry(rname);
+ }
+ Assert.assertEquals(ze2.getName(), rname);
+ Assert.assertNotEquals(ze1.getName(), ze2.getName());
+ }
+}
diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java
new file mode 100644
index 00000000000..f80991d09d5
--- /dev/null
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8132734
+ * @summary Test the System properties for JarFile that support multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
+ */
+
+import com.sun.net.httpserver.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties {
+ private SimpleHttpServer server;
+
+ @BeforeClass
+ public void initialize() throws Exception {
+ server = new SimpleHttpServer();
+ server.start();
+ super.initialize();
+ }
+
+ @Override
+ protected void initializeClassLoader() throws Exception {
+ URL[] urls = new URL[]{
+ new URL("http://localhost:" + server.getPort() + "/multi-release-jar")
+ };
+ cldr = new URLClassLoader(urls);
+ // load any class, Main is convenient and in the root entries
+ rootClass = cldr.loadClass("version.Main");
+ }
+
+ @AfterClass
+ public void close() throws IOException {
+ // Windows requires server to stop before file is deleted
+ if (server != null)
+ server.stop();
+ super.close();
+ }
+
+ /*
+ * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader
+ */
+
+ @Test
+ public void testURLClassLoader() throws Throwable {
+ Class> vcls = cldr.loadClass("version.Version");
+ invokeMethod(vcls, rtVersion);
+ }
+
+ @Test
+ public void testGetResourceAsStream() throws Exception {
+ String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
+ // use rootClass as a base for getting resources
+ getResourceAsStream(rootClass, resource);
+ }
+
+ @Test
+ public void testGetResource() throws Exception {
+ String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
+ // use rootClass as a base for getting resources
+ getResource(rootClass, resource);
+ }
+}
+
+/**
+ * Extremely simple server that only performs one task. The server listens for
+ * requests on the ephemeral port. If it sees a request that begins with
+ * "/multi-release-jar", it consumes the request and returns a stream of bytes
+ * representing the jar file multi-release.jar found in "userdir".
+ */
+class SimpleHttpServer {
+ private static final String userdir = System.getProperty("user.dir", ".");
+ private static final Path multirelease = Paths.get(userdir, "multi-release.jar");
+
+ private final HttpServer server;
+
+ public SimpleHttpServer() throws IOException {
+ server = HttpServer.create();
+ }
+
+ public void start() throws IOException {
+ server.bind(new InetSocketAddress(0), 0);
+ server.createContext("/multi-release-jar", t -> {
+ try (InputStream is = t.getRequestBody()) {
+ is.readAllBytes(); // probably not necessary to consume request
+ byte[] bytes = Files.readAllBytes(multirelease);
+ t.sendResponseHeaders(200, bytes.length);
+ try (OutputStream os = t.getResponseBody()) {
+ os.write(bytes);
+ }
+ }
+ });
+ server.setExecutor(null); // creates a default executor
+ server.start();
+ }
+
+ public void stop() {
+ server.stop(0);
+ }
+
+ int getPort() {
+ return server.getAddress().getPort();
+ }
+}
+
diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java
new file mode 100644
index 00000000000..587bf6e5da1
--- /dev/null
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java
@@ -0,0 +1,228 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8132734
+ * @summary Test the extended API and the aliasing additions in JarFile that
+ * support multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarIterators
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import java.util.zip.ZipFile;
+
+import static java.util.jar.JarFile.Release;
+import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+public class MultiReleaseJarIterators {
+ String userdir = System.getProperty("user.dir", ".");
+ File unversioned = new File(userdir, "unversioned.jar");
+ File multirelease = new File(userdir, "multi-release.jar");
+ Map uvEntries = new HashMap<>();
+ Map mrEntries = new HashMap<>();
+ Map baseEntries = new HashMap<>();
+ Map v9Entries = new HashMap<>();
+ Map v10Entries = new HashMap<>();
+
+ @BeforeClass
+ public void initialize() throws Exception {
+ CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
+ creator.compileEntries();
+ creator.buildUnversionedJar();
+ creator.buildMultiReleaseJar();
+
+ try (JarFile jf = new JarFile(multirelease)) {
+ for (Enumeration e = jf.entries(); e.hasMoreElements(); ) {
+ JarEntry je = e.nextElement();
+ String name = je.getName();
+ mrEntries.put(name, je);
+ if (name.startsWith("META-INF/versions/")) {
+ if (name.startsWith("META-INF/versions/9/")) {
+ v9Entries.put(name.substring(20), je);
+ } else if (name.startsWith("META-INF/versions/10/")) {
+ v10Entries.put(name.substring(21), je);
+ }
+ } else {
+ baseEntries.put(name, je);
+ }
+ }
+ }
+ Assert.assertEquals(mrEntries.size(), 14);
+ Assert.assertEquals(baseEntries.size(), 6);
+ Assert.assertEquals(v9Entries.size(), 5);
+ Assert.assertEquals(v10Entries.size(), 3);
+
+ try (JarFile jf = new JarFile(unversioned)) {
+ jf.entries().asIterator().forEachRemaining(je -> uvEntries.put(je.getName(), je));
+ }
+ Assert.assertEquals(uvEntries.size(), 6);
+ }
+
+ @AfterClass
+ public void close() throws IOException {
+ Files.delete(unversioned.toPath());
+ Files.delete(multirelease.toPath());
+ }
+
+ @Test
+ public void testMultiReleaseJar() throws IOException {
+ try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ)) {
+ testEnumeration(jf, mrEntries);
+ testStream(jf, mrEntries);
+ }
+
+ try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.BASE)) {
+ testEnumeration(jf, baseEntries);
+ testStream(jf, baseEntries);
+ }
+
+ try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) {
+ testEnumeration(jf, v9Entries);
+ testStream(jf, v9Entries);
+ }
+
+ try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
+ Map expectedEntries;
+ switch (jdkMajorVersion()) {
+ case 9:
+ expectedEntries = v9Entries;
+ break;
+ case 10: // won't get here until JDK 10
+ expectedEntries = v10Entries;
+ break;
+ default:
+ expectedEntries = baseEntries;
+ break;
+ }
+
+ testEnumeration(jf, expectedEntries);
+ testStream(jf, expectedEntries);
+ }
+ }
+
+ @Test
+ public void testUnversionedJar() throws IOException {
+ try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ)) {
+ testEnumeration(jf, uvEntries);
+ testStream(jf, uvEntries);
+ }
+
+ try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.BASE)) {
+ testEnumeration(jf, uvEntries);
+ testStream(jf, uvEntries);
+ }
+
+ try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.VERSION_9)) {
+ testEnumeration(jf, uvEntries);
+ testStream(jf, uvEntries);
+ }
+
+ try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
+ testEnumeration(jf, uvEntries);
+ testStream(jf, uvEntries);
+ }
+ }
+
+ private void testEnumeration(JarFile jf, Map expectedEntries) {
+ Map actualEntries = new HashMap<>();
+ for (Enumeration e = jf.entries(); e.hasMoreElements(); ) {
+ JarEntry je = e.nextElement();
+ actualEntries.put(je.getName(), je);
+ }
+
+ testEntries(jf, actualEntries, expectedEntries);
+ }
+
+
+ private void testStream(JarFile jf, Map expectedEntries) {
+ Map actualEntries = jf.stream().collect(Collectors.toMap(je -> je.getName(), je -> je));
+
+ testEntries(jf, actualEntries, expectedEntries);
+ }
+
+ private void testEntries(JarFile jf, Map actualEntries, Map expectedEntries) {
+ /* For multi-release jar files constructed with a Release object,
+ * actualEntries contain versionedEntries that are considered part of the
+ * public API. They have a 1-1 correspondence with baseEntries,
+ * so entries that are not part of the public API won't be present,
+ * i.e. those entries with a name that starts with version/PackagePrivate
+ * in this particular jar file (multi-release.jar)
+ */
+
+ Map entries;
+ if (expectedEntries == mrEntries) {
+ Assert.assertEquals(actualEntries.size(), mrEntries.size());
+ entries = mrEntries;
+ } else if (expectedEntries == uvEntries) {
+ Assert.assertEquals(actualEntries.size(), uvEntries.size());
+ entries = uvEntries;
+ } else {
+ Assert.assertEquals(actualEntries.size(), baseEntries.size()); // this is correct
+ entries = baseEntries;
+ }
+
+ entries.keySet().forEach(name -> {
+ JarEntry ee = expectedEntries.get(name);
+ if (ee == null) ee = entries.get(name);
+ JarEntry ae = actualEntries.get(name);
+ try {
+ compare(jf, ae, ee);
+ } catch (IOException x) {
+ throw new RuntimeException(x);
+ }
+ });
+ }
+
+ private void compare(JarFile jf, JarEntry actual, JarEntry expected) throws IOException {
+ byte[] abytes;
+ byte[] ebytes;
+
+ try (InputStream is = jf.getInputStream(actual)) {
+ abytes = is.readAllBytes();
+ }
+
+ try (InputStream is = jf.getInputStream(expected)) {
+ ebytes = is.readAllBytes();
+ }
+
+ Assert.assertEquals(abytes, ebytes);
+ }
+}
diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java
new file mode 100644
index 00000000000..978ba328be6
--- /dev/null
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8132734
+ * @summary Test the System properties for JarFile that support multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import static sun.misc.Version.jdkMajorVersion; // fixme JEP 223 Version
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class MultiReleaseJarProperties {
+ final static int ROOTVERSION = 8; // magic number from knowledge of internals
+ final static String userdir = System.getProperty("user.dir", ".");
+ final static File multirelease = new File(userdir, "multi-release.jar");
+ protected int rtVersion;
+ boolean force;
+ protected ClassLoader cldr;
+ protected Class> rootClass;
+
+ @BeforeClass
+ public void initialize() throws Exception {
+ CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
+ creator.compileEntries();
+ creator.buildMultiReleaseJar();
+
+ rtVersion = Integer.getInteger("jdk.util.jar.version", jdkMajorVersion());
+ String mrprop = System.getProperty("jdk.util.jar.enableMultiRelease", "");
+ if (mrprop.equals("false")) {
+ rtVersion = ROOTVERSION;
+ } else if (rtVersion < ROOTVERSION) {
+ rtVersion = ROOTVERSION;
+ } else if (rtVersion > jdkMajorVersion()) {
+ rtVersion = jdkMajorVersion();
+ }
+ force = mrprop.equals("force");
+
+ initializeClassLoader();
+ }
+
+ protected void initializeClassLoader() throws Exception {
+ URL[] urls = new URL[]{multirelease.toURI().toURL()};
+ cldr = new URLClassLoader(urls);
+ // load any class, Main is convenient and in the root entries
+ rootClass = cldr.loadClass("version.Main");
+ }
+
+ @AfterClass
+ public void close() throws IOException {
+ ((URLClassLoader)cldr).close();
+ Files.delete(multirelease.toPath());
+ }
+
+ /*
+ * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader
+ */
+ @Test
+ public void testURLClassLoader() throws Throwable {
+ Class> vcls = cldr.loadClass("version.Version");
+ invokeMethod(vcls, rtVersion);
+ }
+
+ protected void invokeMethod(Class> vcls, int expected) throws Throwable {
+ MethodType mt = MethodType.methodType(int.class);
+ MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt);
+ Assert.assertEquals(expected, (int) mh.invoke(vcls.newInstance()));
+ }
+
+ /*
+ * jdk.util.jar.enableMultiRelease=force should affect a custom class loader
+ */
+ @Test
+ public void testClassLoader() throws Throwable {
+ try (JarFile jf = new JarFile(multirelease)) { // do not set runtime versioning
+ ClassLoader cldr = new CustomClassLoader(jf);
+ Class> vcls = cldr.loadClass("version.Version");
+ if (rtVersion == 9) {
+ try {
+ cldr.loadClass("version.PackagePrivate");
+ } catch (ClassNotFoundException x) {
+ if (force) throw x;
+ }
+ }
+ invokeMethod(vcls, force ? rtVersion : ROOTVERSION);
+ }
+ }
+
+ private static class CustomClassLoader extends ClassLoader {
+ private final JarFile jf;
+
+ CustomClassLoader(JarFile jf) throws Exception {
+ super(null);
+ this.jf = jf;
+ }
+
+ protected Class> findClass(String name) throws ClassNotFoundException {
+ try {
+ byte[] b;
+ String entryName = name.replace(".", "/") + ".class";
+ JarEntry je = jf.getJarEntry(entryName);
+ if (je != null) {
+ try (InputStream is = jf.getInputStream(je)) {
+ b = new byte[(int) je.getSize()];
+ is.read(b);
+ }
+ return defineClass(name, b, 0, b.length);
+ }
+ throw new ClassNotFoundException(name);
+ } catch (IOException x) {
+ throw new ClassNotFoundException(x.getMessage());
+ }
+ }
+ }
+
+ @Test
+ public void testGetResourceAsStream() throws Exception {
+ String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
+ // use fileRootClass as a base for getting resources
+ getResourceAsStream(rootClass, resource);
+ }
+
+ protected void getResourceAsStream(Class> rootClass, String resource) throws Exception {
+ try (InputStream is = rootClass.getResourceAsStream(resource)) {
+ byte[] bytes = is.readAllBytes();
+ resource = new String(bytes);
+ }
+ String match = "return " + rtVersion + ";";
+ Assert.assertTrue(resource.contains(match));
+ }
+
+ @Test
+ public void testGetResource() throws Exception {
+ String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
+ // use rootClass as a base for getting resources
+ getResource(rootClass, resource);
+ }
+
+ protected void getResource(Class> rootClass, String resource) throws Exception {
+ URL url = rootClass.getResource(resource);
+ try (InputStream is = url.openStream()) {
+ byte[] bytes = is.readAllBytes();
+ resource = new String(bytes);
+ }
+ String match = "return " + rtVersion + ";";
+ Assert.assertTrue(resource.contains(match));
+ }
+}
diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java
new file mode 100644
index 00000000000..6547c990b2a
--- /dev/null
+++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8132734
+ * @summary Test potential security related issues
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarSecurity
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.security.CodeSigner;
+import java.security.cert.Certificate;
+import java.util.Arrays;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.zip.ZipFile;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class MultiReleaseJarSecurity {
+ String userdir = System.getProperty("user.dir",".");
+ File multirelease = new File(userdir, "multi-release.jar");
+ File signedmultirelease = new File(userdir, "signed-multi-release.jar");
+
+ @BeforeClass
+ public void initialize() throws Exception {
+ CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
+ creator.compileEntries();
+ creator.buildMultiReleaseJar();
+ creator.buildSignedMultiReleaseJar();
+ }
+
+ @AfterClass
+ public void close() throws IOException {
+ Files.delete(multirelease.toPath());
+ Files.delete(signedmultirelease.toPath());
+ }
+
+ @Test
+ public void testCertsAndSigners() throws IOException {
+ try (JarFile jf = new JarFile(signedmultirelease, true, ZipFile.OPEN_READ, JarFile.Release.RUNTIME)) {
+ int version = sun.misc.Version.jdkMajorVersion(); // fixme JEP 223 Version
+ CertsAndSigners vcas = new CertsAndSigners(jf, jf.getJarEntry("version/Version.class"));
+ CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + version + "/version/Version.class"));
+ Assert.assertTrue(Arrays.equals(rcas.getCertificates(), vcas.getCertificates()));
+ Assert.assertTrue(Arrays.equals(rcas.getCodeSigners(), vcas.getCodeSigners()));
+ }
+ }
+
+ private static class CertsAndSigners {
+ final private JarFile jf;
+ final private JarEntry je;
+ private boolean readComplete;
+
+ CertsAndSigners(JarFile jf, JarEntry je) {
+ this.jf = jf;
+ this.je = je;
+ }
+
+ Certificate[] getCertificates() throws IOException {
+ readEntry();
+ return je.getCertificates();
+ }
+
+ CodeSigner[] getCodeSigners() throws IOException {
+ readEntry();
+ return je.getCodeSigners();
+ }
+
+ private void readEntry() throws IOException {
+ if (!readComplete) {
+ try (InputStream is = jf.getInputStream(je)) {
+ is.readAllBytes();
+ }
+ readComplete = true;
+ }
+ }
+ }
+}
diff --git a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java
new file mode 100644
index 00000000000..a500eb2e25c
--- /dev/null
+++ b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8132734
+ * @summary Test that URL connections to multi-release jars can be runtime versioned
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarURLConnection
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.jar.JarFile;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class MultiReleaseJarURLConnection {
+ String userdir = System.getProperty("user.dir",".");
+ String urlFile = "jar:file:" + userdir + "/multi-release.jar!/";
+ String urlEntry = urlFile + "version/Version.java";
+
+ @BeforeClass
+ public void initialize() throws Exception {
+ CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
+ creator.compileEntries();
+ creator.buildMultiReleaseJar();
+ }
+
+ @AfterClass
+ public void close() throws IOException {
+ Files.delete(Paths.get(userdir, "multi-release.jar"));
+ }
+
+ @Test
+ public void testRuntimeVersioning() throws Exception {
+ Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8"));
+ // #runtime is "magic"
+ Assert.assertTrue(readAndCompare(new URL(urlEntry + "#runtime"), "return 9"));
+ // #fragment or any other fragment is not magic
+ Assert.assertTrue(readAndCompare(new URL(urlEntry + "#fragment"), "return 8"));
+ // cached entities not affected
+ Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8"));
+ }
+
+ @Test
+ public void testCachedJars() throws Exception {
+ URL rootUrl = new URL(urlFile);
+ JarURLConnection juc = (JarURLConnection)rootUrl.openConnection();
+ JarFile rootJar = juc.getJarFile();
+ JarFile.Release root = rootJar.getVersion();
+
+ URL runtimeUrl = new URL(urlFile + "#runtime");
+ juc = (JarURLConnection)runtimeUrl.openConnection();
+ JarFile runtimeJar = juc.getJarFile();
+ JarFile.Release runtime = runtimeJar.getVersion();
+ Assert.assertNotEquals(root, runtime);
+
+ juc = (JarURLConnection)rootUrl.openConnection();
+ JarFile jar = juc.getJarFile();
+ Assert.assertEquals(jar.getVersion(), root);
+ Assert.assertEquals(jar, rootJar);
+
+ juc = (JarURLConnection)runtimeUrl.openConnection();
+ jar = juc.getJarFile();
+ Assert.assertEquals(jar.getVersion(), runtime);
+ Assert.assertEquals(jar, runtimeJar);
+
+ rootJar.close();
+ runtimeJar.close();
+ jar.close(); // probably not needed
+ }
+
+ private boolean readAndCompare(URL url, String match) throws Exception {
+ boolean result;
+ // necessary to do it this way, instead of openStream(), so we can
+ // close underlying JarFile, otherwise windows can't delete the file
+ URLConnection conn = url.openConnection();
+ try (InputStream is = conn.getInputStream()) {
+ byte[] bytes = is.readAllBytes();
+ result = (new String(bytes)).contains(match);
+ }
+ if (conn instanceof JarURLConnection) {
+ ((JarURLConnection)conn).getJarFile().close();
+ }
+ return result;
+ }
+}
From 6d0ef1b692d806a211da08cf09d9f20561b39c56 Mon Sep 17 00:00:00 2001
From: Kim Barrett
Date: Tue, 16 Feb 2016 21:58:49 -0500
Subject: [PATCH 016/311] 8146728: TestPrintGCDetailsVerbose is never run by
jtreg
Remove requirement for fastdebug, update logging option
Reviewed-by: sjohanss, brutisso, dfazunen
---
hotspot/test/TEST.ROOT | 4 ++--
hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java | 7 +++----
2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT
index 57f0e0ae061..8dd7c84e9ee 100644
--- a/hotspot/test/TEST.ROOT
+++ b/hotspot/test/TEST.ROOT
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2016, 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 @@
keys=cte_test jcmd nmt regression gc stress
groups=TEST.groups [closed/TEST.groups]
-requires.properties=sun.arch.data.model java.version
+requires.properties=sun.arch.data.model
# Tests using jtreg 4.1 b12 features
requiredVersion=4.1 b12
diff --git a/hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java b/hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java
index 8e138db694d..1a7501e0981 100644
--- a/hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java
+++ b/hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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,12 +24,11 @@
/*
* @test TestPrintGCDetailsVerbose
* @bug 8016740
- * @summary Tests that jvm with PrintGCDetails and Verbose flags do not crash when ParOldGC has no memory
+ * @summary Tests that jvm with maximally verbose GC logging does not crash when ParOldGC has no memory
* @key gc
- * @requires java.version ~= ".*fastdebug"
* @requires vm.gc=="Parallel" | vm.gc=="null"
* @library /testlibrary
- * @run main/othervm -Xmx50m -XX:+UseParallelOldGC -XX:+PrintGCDetails -XX:+Verbose TestPrintGCDetailsVerbose
+ * @run main/othervm -Xmx50m -XX:+UseParallelGC -Xlog:gc*=trace TestPrintGCDetailsVerbose
*/
public class TestPrintGCDetailsVerbose {
From a4d0bc4a4e5236ed9dca5dd43412b9e3308cfd44 Mon Sep 17 00:00:00 2001
From: Dmitry Dmitriev
Date: Wed, 17 Feb 2016 11:00:57 +0300
Subject: [PATCH 017/311] 8144578: TestOptionsWithRanges test only ever uses
the default collector
Reviewed-by: sangheki, dholmes
---
.../TestOptionsWithRanges.java | 9 +++-
.../common/optionsvalidation/JVMOption.java | 54 ++++++++++---------
.../optionsvalidation/JVMOptionsUtils.java | 37 ++++++++++---
.../common/optionsvalidation/JVMStartup.java | 51 ++++++++++++++++++
4 files changed, 118 insertions(+), 33 deletions(-)
create mode 100644 hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMStartup.java
diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java
index f762017bff2..24f7ad70a53 100644
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -83,6 +83,13 @@ public class TestOptionsWithRanges {
setAllowedExitCodes("SharedMiscDataSize", 2);
setAllowedExitCodes("SharedMiscCodeSize", 2);
+ /*
+ * JDK-8145204
+ * Temporarily remove testing of max range for ParGCArrayScanChunk because
+ * JVM can hang when ParGCArrayScanChunk=4294967296 and ParallelGC is used
+ */
+ excludeTestMaxRange("ParGCArrayScanChunk");
+
/*
* Remove CICompilerCount from testing because currently it can hang system
*/
diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java
index d4d54669987..031d6a2cc64 100644
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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 @@ import jdk.test.lib.dcmd.JMXExecutor;
import sun.tools.attach.HotSpotVirtualMachine;
import static optionsvalidation.JVMOptionsUtils.failedMessage;
+import static optionsvalidation.JVMOptionsUtils.GCType;
import static optionsvalidation.JVMOptionsUtils.printOutputContent;
import static optionsvalidation.JVMOptionsUtils.VMType;
@@ -374,17 +375,21 @@ public abstract class JVMOption {
private boolean runJavaWithParam(String optionValue, boolean valid) throws Exception {
int exitCode;
boolean result = true;
- String value = optionValue.substring(optionValue.lastIndexOf("=") + 1);
- String fullOptionString = prependString.toString() + optionValue;
+ String errorMessage = null;
List runJava = new ArrayList<>();
OutputAnalyzer out;
if (VMType != null) {
runJava.add(VMType);
}
+
+ if (GCType != null) {
+ runJava.add(GCType);
+ }
+
runJava.addAll(prepend);
runJava.add(optionValue);
- runJava.add(JVMOptionsUtils.class.getName());
+ runJava.add(JVMStartup.class.getName());
out = new OutputAnalyzer(ProcessTools.createJavaProcessBuilder(runJava.toArray(new String[0])).start());
@@ -392,40 +397,37 @@ public abstract class JVMOption {
if (out.getOutput().contains("A fatal error has been detected by the Java Runtime Environment")) {
/* Always consider "fatal error" in output as fail */
- failedMessage(name, fullOptionString, valid, "JVM output reports a fatal error. JVM exited with code " + exitCode + "!");
- printOutputContent(out);
- result = false;
+ errorMessage = "JVM output reports a fatal error. JVM exited with code " + exitCode + "!";
} else if (valid == true) {
if (!allowedExitCodes.contains(exitCode)) {
- failedMessage(name, fullOptionString, valid, "JVM exited with unexpected error code = " + exitCode);
- printOutputContent(out);
- result = false;
+ errorMessage = "JVM exited with unexpected error code = " + exitCode;
} else if ((exitCode != 0) && (out.getOutput().isEmpty() == true)) {
- failedMessage(name, fullOptionString, valid, "JVM exited with error(exitcode == " + exitCode +
- "), but with empty stdout and stderr. Description of error is needed!");
- result = false;
+ errorMessage = "JVM exited with error(exitcode == " + exitCode + "), but with empty stdout and stderr. " +
+ "Description of error is needed!";
} else if (out.getOutput().contains("is outside the allowed range")) {
- failedMessage(name, fullOptionString, valid, "JVM output contains \"is outside the allowed range\"");
- printOutputContent(out);
- result = false;
+ errorMessage = "JVM output contains \"is outside the allowed range\"";
}
} else {
// valid == false
+ String value = optionValue.substring(optionValue.lastIndexOf("=") + 1);
+ String errorMessageCommandLineValue = getErrorMessageCommandLine(value);
if (exitCode == 0) {
- failedMessage(name, fullOptionString, valid, "JVM successfully exit");
- result = false;
+ errorMessage = "JVM successfully exit";
} else if (exitCode != 1) {
- failedMessage(name, fullOptionString, valid, "JVM exited with code "
- + exitCode + " which not equal to 1");
- result = false;
- } else if (!out.getOutput().contains(getErrorMessageCommandLine(value))) {
- failedMessage(name, fullOptionString, valid, "JVM output does not contain "
- + "expected output \"" + getErrorMessageCommandLine(value) + "\"");
- printOutputContent(out);
- result = false;
+ errorMessage = "JVM exited with code " + exitCode + " which not equal to 1";
+ } else if (!out.getOutput().contains(errorMessageCommandLineValue)) {
+ errorMessage = "JVM output does not contain expected output \"" + errorMessageCommandLineValue + "\"";
}
}
+ if (errorMessage != null) {
+ String fullOptionString = String.format("%s %s %s %s",
+ VMType == null ? "" : VMType, GCType == null ? "" : GCType, prependString.toString(), optionValue).trim().replaceAll(" +", " ");
+ failedMessage(name, fullOptionString, valid, errorMessage);
+ printOutputContent(out);
+ result = false;
+ }
+
System.out.println("");
return result;
diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java
index 944b8d5964c..cfde0ee0e3d 100644
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -27,6 +27,8 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
@@ -50,6 +52,9 @@ public class JVMOptionsUtils {
/* Used to start the JVM with the same type as current */
static String VMType;
+ /* Used to start the JVM with the same GC type as current */
+ static String GCType;
+
private static Map optionsAsMap;
static {
@@ -64,6 +69,27 @@ public class JVMOptionsUtils {
} else {
VMType = null;
}
+
+ List gcMxBeans = ManagementFactory.getGarbageCollectorMXBeans();
+
+ GCType = null;
+
+ for (GarbageCollectorMXBean gcMxBean : gcMxBeans) {
+ switch (gcMxBean.getName()) {
+ case "ConcurrentMarkSweep":
+ GCType = "-XX:+UseConcMarkSweepGC";
+ break;
+ case "MarkSweepCompact":
+ GCType = "-XX:+UseSerialGC";
+ break;
+ case "PS Scavenge":
+ GCType = "-XX:+UseParallelGC";
+ break;
+ case "G1 Old Generation":
+ GCType = "-XX:+UseG1GC";
+ break;
+ }
+ }
}
public static boolean fitsRange(String optionName, BigDecimal number) throws Exception {
@@ -443,6 +469,10 @@ public class JVMOptionsUtils {
if (VMType != null) {
runJava.add(VMType);
}
+
+ if (GCType != null) {
+ runJava.add(GCType);
+ }
runJava.add(PRINT_FLAGS_RANGES);
runJava.add("-version");
@@ -534,9 +564,4 @@ public class JVMOptionsUtils {
public static Map getOptionsWithRangeAsMap(String... additionalArgs) throws Exception {
return getOptionsWithRangeAsMap(origin -> true, additionalArgs);
}
-
- /* Simple method to test that java start-up. Used for testing options. */
- public static void main(String[] args) {
- System.out.print("Java start-up!");
- }
}
diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMStartup.java b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMStartup.java
new file mode 100644
index 00000000000..5b5d96e5576
--- /dev/null
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMStartup.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016, 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 optionsvalidation;
+
+import java.lang.ref.WeakReference;
+
+class JVMStartup {
+ private static volatile WeakReference weakRef;
+
+ private static synchronized void createWeakRef() {
+ Object o = new Object();
+ weakRef = new WeakReference<>(o);
+ }
+
+ /* Simple method to test that java start-up. Used for testing options. */
+ public static void main(String[] args) throws Exception {
+ byte[] garbage = new byte[8192];
+ int i = 0;
+ createWeakRef();
+ do {
+ garbage = new byte[8192];
+ i++;
+ /* Initiate GC after 5 iterations */
+ if (i > 5) {
+ System.gc();
+ }
+ } while(weakRef.get() != null);
+ System.out.println("Java start-up!");
+ }
+}
From a81f4a10da20d493b639313cc0f6d0501d913a6b Mon Sep 17 00:00:00 2001
From: Robbin Ehn
Date: Wed, 17 Feb 2016 11:11:47 +0100
Subject: [PATCH 018/311] 8148219: Add decorator hostname to UL
Reviewed-by: dholmes, mlarsson
---
hotspot/src/os/posix/vm/os_posix.cpp | 4 +---
hotspot/src/os/windows/vm/os_windows.cpp | 2 --
.../src/share/vm/logging/logConfiguration.cpp | 5 ++---
hotspot/src/share/vm/logging/logDecorations.cpp | 17 ++++++++++++++++-
hotspot/src/share/vm/logging/logDecorations.hpp | 9 ++++-----
hotspot/src/share/vm/logging/logDecorators.hpp | 4 +++-
hotspot/src/share/vm/runtime/os.hpp | 4 +++-
7 files changed, 29 insertions(+), 16 deletions(-)
diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp
index 68ab843bf44..8cccda34d21 100644
--- a/hotspot/src/os/posix/vm/os_posix.cpp
+++ b/hotspot/src/os/posix/vm/os_posix.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -238,14 +238,12 @@ void os::Posix::print_uname_info(outputStream* st) {
st->cr();
}
-#ifndef PRODUCT
bool os::get_host_name(char* buf, size_t buflen) {
struct utsname name;
uname(&name);
jio_snprintf(buf, buflen, "%s", name.nodename);
return true;
}
-#endif // PRODUCT
bool os::has_allocatable_memory_limit(julong* limit) {
struct rlimit rlim;
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index 1df102a7607..19d7319e7e1 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -1531,12 +1531,10 @@ int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *pa
return result;
}
-#ifndef PRODUCT
bool os::get_host_name(char* buf, size_t buflen) {
DWORD size = (DWORD)buflen;
return (GetComputerNameEx(ComputerNameDnsHostname, buf, &size) == TRUE);
}
-#endif // PRODUCT
void os::get_summary_os_info(char* buf, size_t buflen) {
stringStream sst(buf, buflen);
diff --git a/hotspot/src/share/vm/logging/logConfiguration.cpp b/hotspot/src/share/vm/logging/logConfiguration.cpp
index 2ff86004cce..2bdd8682f93 100644
--- a/hotspot/src/share/vm/logging/logConfiguration.cpp
+++ b/hotspot/src/share/vm/logging/logConfiguration.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -82,8 +82,7 @@ void LogConfiguration::post_initialize() {
void LogConfiguration::initialize(jlong vm_start_time) {
LogFileOutput::set_file_name_parameters(vm_start_time);
- LogDecorations::set_vm_start_time_millis(vm_start_time);
-
+ LogDecorations::initialize(vm_start_time);
assert(_outputs == NULL, "Should not initialize _outputs before this function, initialize called twice?");
_outputs = NEW_C_HEAP_ARRAY(LogOutput*, 2, mtLogging);
_outputs[0] = LogOutput::Stdout;
diff --git a/hotspot/src/share/vm/logging/logDecorations.cpp b/hotspot/src/share/vm/logging/logDecorations.cpp
index 3438b8ad734..210ab31313a 100644
--- a/hotspot/src/share/vm/logging/logDecorations.cpp
+++ b/hotspot/src/share/vm/logging/logDecorations.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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,12 +29,21 @@
#include "services/management.hpp"
jlong LogDecorations::_vm_start_time_millis = 0;
+const char* LogDecorations::_host_name = "";
LogDecorations::LogDecorations(LogLevelType level, const LogTagSet &tagset, const LogDecorators &decorators)
: _level(level), _tagset(tagset), _millis(-1) {
create_decorations(decorators);
}
+void LogDecorations::initialize(jlong vm_start_time) {
+ char buffer[1024];
+ if (os::get_host_name(buffer, sizeof(buffer))){
+ _host_name = os::strdup_check_oom(buffer);
+ }
+ _vm_start_time_millis = vm_start_time;
+}
+
void LogDecorations::create_decorations(const LogDecorators &decorators) {
char* position = _decorations_buffer;
#define DECORATOR(full_name, abbr) \
@@ -109,3 +118,9 @@ char* LogDecorations::create_tags_decoration(char* pos) {
int written = _tagset.label(pos, DecorationsBufferSize - (pos - _decorations_buffer));
ASSERT_AND_RETURN(written, pos)
}
+
+char* LogDecorations::create_hostname_decoration(char* pos) {
+ int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer), "%s", _host_name);
+ ASSERT_AND_RETURN(written, pos)
+}
+
diff --git a/hotspot/src/share/vm/logging/logDecorations.hpp b/hotspot/src/share/vm/logging/logDecorations.hpp
index 08a675f225b..fcc166147e8 100644
--- a/hotspot/src/share/vm/logging/logDecorations.hpp
+++ b/hotspot/src/share/vm/logging/logDecorations.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -39,6 +39,7 @@ class LogDecorations VALUE_OBJ_CLASS_SPEC {
LogTagSet _tagset;
jlong _millis;
static jlong _vm_start_time_millis;
+ static const char* _host_name;
jlong java_millis();
void create_decorations(const LogDecorators& decorators);
@@ -48,15 +49,13 @@ class LogDecorations VALUE_OBJ_CLASS_SPEC {
#undef DECORATOR
public:
+ static void initialize(jlong vm_start_time);
+
LogDecorations(LogLevelType level, const LogTagSet& tagset, const LogDecorators& decorators);
const char* decoration(LogDecorators::Decorator decorator) const {
return _decoration_offset[decorator];
}
-
- static void set_vm_start_time_millis(jlong start_time) {
- _vm_start_time_millis = start_time;
- }
};
#endif // SHARE_VM_LOGGING_LOGDECORATIONS_HPP
diff --git a/hotspot/src/share/vm/logging/logDecorators.hpp b/hotspot/src/share/vm/logging/logDecorators.hpp
index 56a4778b034..1e52124060f 100644
--- a/hotspot/src/share/vm/logging/logDecorators.hpp
+++ b/hotspot/src/share/vm/logging/logDecorators.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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,6 +34,7 @@
// uptimemillis - Milliseconds since the JVM started
// timenanos - The same value as generated by System.nanoTime()
// uptimenanos - Nanoseconds since the JVM started
+// hostname - The hostname
// pid - The process identifier
// tid - The thread identifier
// level - The level associated with the log message
@@ -45,6 +46,7 @@
DECORATOR(uptimemillis, um) \
DECORATOR(timenanos, tn) \
DECORATOR(uptimenanos, un) \
+ DECORATOR(hostname, hn) \
DECORATOR(pid, p) \
DECORATOR(tid, ti) \
DECORATOR(level, l) \
diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp
index 9668104ef5d..128c73c3194 100644
--- a/hotspot/src/share/vm/runtime/os.hpp
+++ b/hotspot/src/share/vm/runtime/os.hpp
@@ -152,7 +152,6 @@ class os: AllStatic {
static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned);
// Get summary strings for system information in buffer provided
- static bool get_host_name(char* buf, size_t buflen) PRODUCT_RETURN_(return false;); // true if available
static void get_summary_cpu_info(char* buf, size_t buflen);
static void get_summary_os_info(char* buf, size_t buflen);
@@ -595,6 +594,9 @@ class os: AllStatic {
// Write to stream
static int log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) ATTRIBUTE_PRINTF(3, 0);
+ // Get host name in buffer provided
+ static bool get_host_name(char* buf, size_t buflen);
+
// Print out system information; they are called by fatal error handler.
// Output format may be different on different platforms.
static void print_os_info(outputStream* st);
From c867b023b670ef369a0447f454c30cca363f8f4d Mon Sep 17 00:00:00 2001
From: Dmitry Dmitriev
Date: Tue, 16 Feb 2016 13:20:38 -0800
Subject: [PATCH 019/311] 8149643: Remove check of counters in
VirtualSpaceNode::inc_container_count
Reviewed-by: brutisso, kbarrett, mgerdin
---
hotspot/src/share/vm/memory/metaspace.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp
index 72ec52da3d1..199702e083e 100644
--- a/hotspot/src/share/vm/memory/metaspace.cpp
+++ b/hotspot/src/share/vm/memory/metaspace.cpp
@@ -791,7 +791,6 @@ Mutex* const SpaceManager::_expand_lock =
void VirtualSpaceNode::inc_container_count() {
assert_lock_strong(SpaceManager::expand_lock());
_container_count++;
- DEBUG_ONLY(verify_container_count();)
}
void VirtualSpaceNode::dec_container_count() {
@@ -1073,6 +1072,7 @@ void VirtualSpaceList::purge(ChunkManager* chunk_manager) {
VirtualSpaceNode* next_vsl = prev_vsl;
while (next_vsl != NULL) {
VirtualSpaceNode* vsl = next_vsl;
+ DEBUG_ONLY(vsl->verify_container_count();)
next_vsl = vsl->next();
// Don't free the current virtual space since it will likely
// be needed soon.
@@ -1137,19 +1137,19 @@ void VirtualSpaceList::retire_current_virtual_space() {
}
void VirtualSpaceNode::retire(ChunkManager* chunk_manager) {
+ DEBUG_ONLY(verify_container_count();)
for (int i = (int)MediumIndex; i >= (int)ZeroIndex; --i) {
ChunkIndex index = (ChunkIndex)i;
size_t chunk_size = chunk_manager->free_chunks(index)->size();
while (free_words_in_vs() >= chunk_size) {
- DEBUG_ONLY(verify_container_count();)
Metachunk* chunk = get_chunk_vs(chunk_size);
assert(chunk != NULL, "allocation should have been successful");
chunk_manager->return_chunks(index, chunk);
chunk_manager->inc_free_chunks_total(chunk_size);
- DEBUG_ONLY(verify_container_count();)
}
+ DEBUG_ONLY(verify_container_count();)
}
assert(free_words_in_vs() == 0, "should be empty now");
}
From 58fe974cb716c70be3a7f304d582546141b6e0f1 Mon Sep 17 00:00:00 2001
From: Peter Brunet
Date: Tue, 16 Feb 2016 19:38:26 -0600
Subject: [PATCH 020/311] 8149161: CSM call Class.forName in
com.sun.java.accessibility.util.Translator
Add call to checkPackageAccess
Reviewed-by: serb, prr
---
.../com/sun/java/accessibility/util/Translator.java | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java
index 177fbb4403c..224b5375283 100644
--- a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java
@@ -32,6 +32,7 @@ import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
+import java.security.AccessControlException;
// Do not import Swing classes. This module is intended to work
// with both Swing and AWT.
// import javax.swing.*;
@@ -77,7 +78,7 @@ public class Translator extends AccessibleContext
return null;
}
try {
- t = Class.forName("com.sun.java.accessibility.util.internal"
+ t = Class.forName("com.sun.java.accessibility.util.internal."
+ c.getSimpleName()
+ "Translator");
return t;
@@ -105,6 +106,10 @@ public class Translator extends AccessibleContext
if (o instanceof Accessible) {
a = (Accessible)o;
} else {
+ // About to "newInstance" an object of a class of a restricted package
+ // so ensure the caller is allowed access to that package.
+ String pkg = "com.sun.java.accessibility.util.internal";
+ System.getSecurityManager().checkPackageAccess(pkg);
Class> translatorClass = getTranslatorClass(o.getClass());
if (translatorClass != null) {
try {
From 8372c1c09a468d5c09ff115873c15721a22d2197 Mon Sep 17 00:00:00 2001
From: Avik Niyogi
Date: Wed, 17 Feb 2016 11:44:07 +0530
Subject: [PATCH 021/311] 8146321: [macosx] JInternalFrame frame icon in wrong
position on Mac L&F if icon is not ImageIcon
Reviewed-by: serb, alexsch, rchamyal
---
.../apple/laf/AquaInternalFrameBorder.java | 49 +++-
.../8146321/JInternalFrameIconTest.java | 275 ++++++++++++++++++
2 files changed, 309 insertions(+), 15 deletions(-)
create mode 100644 jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java
diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java
index ef5ca43cf23..4a72d0fd371 100644
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java
@@ -40,6 +40,7 @@ import apple.laf.JRSUIState.TitleBarHeightState;
import com.apple.laf.AquaUtils.RecyclableSingleton;
import com.apple.laf.AquaInternalFrameBorderMetrics;
+import java.awt.geom.AffineTransform;
public class AquaInternalFrameBorder implements Border, UIResource {
private static final int kCloseButton = 0;
@@ -309,18 +310,40 @@ public class AquaInternalFrameBorder implements Border, UIResource {
return isInsideYButtonArea(i, y) && x >= startX && x <= endX;
}
- protected void paintTitleIcon(final Graphics g, final JInternalFrame frame, final int x, final int y) {
- Icon icon = frame.getFrameIcon();
- if (icon == null) icon = UIManager.getIcon("InternalFrame.icon");
- if (icon == null) return;
+ protected void paintTitleIcon(final Graphics g, final JInternalFrame frame,
+ final int x, final int y) {
- // Resize to 16x16 if necessary.
- if (icon instanceof ImageIcon && (icon.getIconWidth() > sMaxIconWidth || icon.getIconHeight() > sMaxIconHeight)) {
- final Image img = ((ImageIcon)icon).getImage();
- ((ImageIcon)icon).setImage(img.getScaledInstance(sMaxIconWidth, sMaxIconHeight, Image.SCALE_SMOOTH));
+ Icon icon = frame.getFrameIcon();
+ if (icon == null) {
+ icon = UIManager.getIcon("InternalFrame.icon");
}
- icon.paintIcon(frame, g, x, y);
+ if (icon == null) {
+ return;
+ }
+
+ if (icon.getIconWidth() > sMaxIconWidth
+ || icon.getIconHeight() > sMaxIconHeight) {
+ final Graphics2D g2 = (Graphics2D) g;
+ final AffineTransform savedAT = g2.getTransform();
+ double xScaleFactor = (double) sMaxIconWidth / icon.getIconWidth();
+ double yScaleFactor = (double) sMaxIconHeight / icon.getIconHeight();
+
+ //Coordinates are after a translation hence relative origin shifts
+ g2.translate(x, y);
+
+ //scaling factor is needed to scale while maintaining aspect ratio
+ double scaleMaintainAspectRatio = Math.min(xScaleFactor, yScaleFactor);
+
+ //minimum value is taken to set to a maximum Icon Dimension
+ g2.scale(scaleMaintainAspectRatio, scaleMaintainAspectRatio);
+
+ icon.paintIcon(frame, g2, 0, 0);
+ g2.setTransform(savedAT);
+
+ } else {
+ icon.paintIcon(frame, g, x, y);
+ }
}
protected int getIconWidth(final JInternalFrame frame) {
@@ -330,9 +353,7 @@ public class AquaInternalFrameBorder implements Border, UIResource {
if (icon == null) {
icon = UIManager.getIcon("InternalFrame.icon");
}
-
- if (icon != null && icon instanceof ImageIcon) {
- // Resize to 16x16 if necessary.
+ if (icon != null) {
width = Math.min(icon.getIconWidth(), sMaxIconWidth);
}
@@ -346,9 +367,7 @@ public class AquaInternalFrameBorder implements Border, UIResource {
if (icon == null) {
icon = UIManager.getIcon("InternalFrame.icon");
}
-
- if (icon != null && icon instanceof ImageIcon) {
- // Resize to 16x16 if necessary.
+ if (icon != null) {
height = Math.min(icon.getIconHeight(), sMaxIconHeight);
}
diff --git a/jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java b/jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java
new file mode 100644
index 00000000000..4ff95c5bc30
--- /dev/null
+++ b/jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java
@@ -0,0 +1,275 @@
+/*
+ * 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.
+ */
+
+/* @test
+ * @bug 8146321
+ * @summary verifies JInternalFrame Icon and ImageIcon
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main JInternalFrameIconTest
+ */
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.image.BufferedImage;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JDesktopPane;
+import javax.swing.JFrame;
+import javax.swing.JInternalFrame;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+
+public class JInternalFrameIconTest {
+
+ private static JFrame frame;
+ private static JDesktopPane desktopPane;
+ private static JInternalFrame internalFrame;
+ private static ImageIcon titleImageIcon;
+ private static Icon titleIcon;
+ private static BufferedImage imageIconImage;
+ private static BufferedImage iconImage;
+
+ private static Robot robot;
+
+ public static void main(String[] args) throws Exception {
+ robot = new Robot();
+ robot.delay(2000);
+ UIManager.LookAndFeelInfo[] lookAndFeelArray
+ = UIManager.getInstalledLookAndFeels();
+ for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) {
+ executeCase(lookAndFeelItem.getClassName());
+ }
+
+ }
+
+ private static void executeCase(String lookAndFeelString) throws Exception {
+ if (tryLookAndFeel(lookAndFeelString)) {
+ createImageIconUI(lookAndFeelString);
+ robot.delay(1000);
+ getImageIconBufferedImage();
+ robot.waitForIdle();
+ cleanUp();
+ robot.waitForIdle();
+
+ createIconUI(lookAndFeelString);
+ robot.delay(1000);
+ getIconBufferedImage();
+ robot.waitForIdle();
+ cleanUp();
+ robot.waitForIdle();
+ testIfSame();
+ robot.waitForIdle();
+ }
+
+ }
+
+ private static void createImageIconUI(final String lookAndFeelString)
+ throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ desktopPane = new JDesktopPane();
+ internalFrame = new JInternalFrame();
+ frame = new JFrame();
+ internalFrame.setTitle(lookAndFeelString);
+ titleImageIcon = new ImageIcon() {
+ @Override
+ public int getIconWidth() {
+ return 16;
+ }
+
+ @Override
+ public int getIconHeight() {
+ return 16;
+ }
+
+ @Override
+ public void paintIcon(
+ Component c, Graphics g, int x, int y) {
+ g.setColor(java.awt.Color.black);
+ g.fillRect(x, y, 16, 16);
+ }
+ };
+ internalFrame.setFrameIcon(titleImageIcon);
+ internalFrame.setSize(500, 200);
+ internalFrame.setVisible(true);
+ desktopPane.add(internalFrame);
+
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.getContentPane().setLayout(new BorderLayout());
+ frame.getContentPane().add(desktopPane, "Center");
+ frame.setSize(500, 500);
+ frame.setLocationRelativeTo(null);
+ frame.setVisible(true);
+ frame.toFront();
+ }
+ });
+ }
+
+ private static void createIconUI(final String lookAndFeelString)
+ throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ desktopPane = new JDesktopPane();
+ internalFrame = new JInternalFrame();
+ frame = new JFrame();
+ internalFrame.setTitle(lookAndFeelString);
+ titleIcon = new Icon() {
+ @Override
+ public int getIconWidth() {
+ return 16;
+ }
+
+ @Override
+ public int getIconHeight() {
+ return 16;
+ }
+
+ @Override
+ public void paintIcon(
+ Component c, Graphics g, int x, int y) {
+ g.setColor(java.awt.Color.black);
+ g.fillRect(x, y, 16, 16);
+ }
+ };
+ internalFrame.setFrameIcon(titleIcon);
+ internalFrame.setSize(500, 200);
+ internalFrame.setVisible(true);
+ desktopPane.add(internalFrame);
+
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.getContentPane().setLayout(new BorderLayout());
+ frame.getContentPane().add(desktopPane, "Center");
+ frame.setSize(500, 500);
+ frame.setLocationRelativeTo(null);
+ frame.setVisible(true);
+ frame.toFront();
+ }
+ });
+ }
+
+ private static void getImageIconBufferedImage() throws Exception {
+ Point point = internalFrame.getLocationOnScreen();
+ Rectangle rect = internalFrame.getBounds();
+ Rectangle captureRect = new Rectangle(
+ point.x + internalFrame.getInsets().left,
+ point.y,
+ rect.width,
+ internalFrame.getInsets().top);
+ imageIconImage
+ = robot.createScreenCapture(captureRect);
+ }
+
+ private static void getIconBufferedImage() throws Exception {
+ Point point = internalFrame.getLocationOnScreen();
+ Rectangle rect = internalFrame.getBounds();
+ Rectangle captureRect = new Rectangle(
+ point.x + internalFrame.getInsets().left,
+ point.y,
+ rect.width,
+ internalFrame.getInsets().top);
+ iconImage
+ = robot.createScreenCapture(captureRect);
+ }
+
+ private static void testIfSame() throws Exception {
+ if (!bufferedImagesEqual(imageIconImage, iconImage)) {
+ System.err.println("ERROR: icon and imageIcon not same.");
+ } else {
+ System.out.println("SUCCESS: icon and imageIcon same.");
+ }
+ }
+
+ private static boolean bufferedImagesEqual(
+ BufferedImage bufferedImage1, BufferedImage bufferedImage2) {
+ boolean flag = true;
+
+ if (bufferedImage1.getWidth() == bufferedImage2.getWidth()
+ && bufferedImage1.getHeight() == bufferedImage2.getHeight()) {
+ final int colorTolerance = 25;
+ final int mismatchTolerance = (int) (0.1
+ * bufferedImage1.getWidth() * bufferedImage1.getHeight());
+ int mismatchCounter = 0;
+ for (int x = 0; x < bufferedImage1.getWidth(); x++) {
+ for (int y = 0; y < bufferedImage1.getHeight(); y++) {
+
+ int color1 = bufferedImage1.getRGB(x, y);
+ int red1 = (color1 >> 16) & 0x000000FF;
+ int green1 = (color1 >> 8) & 0x000000FF;
+ int blue1 = (color1) & 0x000000FF;
+
+ int color2 = bufferedImage2.getRGB(x, y);
+ int red2 = (color2 >> 16) & 0x000000FF;
+ int green2 = (color2 >> 8) & 0x000000FF;
+ int blue2 = (color2) & 0x000000FF;
+ if (red1 != red2 || green1 != green2 || blue1 != blue2) {
+ ++mismatchCounter;
+ if ((Math.abs(red1 - red2) > colorTolerance)
+ || (Math.abs(green1 - green2) > colorTolerance)
+ || (Math.abs(blue1 - blue2) > colorTolerance)) {
+
+ flag = false;
+ }
+ }
+ }
+ }
+ if (mismatchCounter > mismatchTolerance) {
+ flag = false;
+ }
+ } else {
+ System.err.println("ERROR: size is different");
+ flag = false;
+ }
+ return flag;
+ }
+
+ private static void cleanUp() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame.dispose();
+ }
+ });
+ }
+
+ private static boolean tryLookAndFeel(String lookAndFeelString)
+ throws Exception {
+ try {
+ UIManager.setLookAndFeel(
+ lookAndFeelString);
+
+ } catch (UnsupportedLookAndFeelException
+ | ClassNotFoundException
+ | InstantiationException
+ | IllegalAccessException e) {
+ return false;
+ }
+ return true;
+ }
+}
From 88575c5de777893560d39060bc5e65725b2f1487 Mon Sep 17 00:00:00 2001
From: Christian Thalinger
Date: Wed, 24 Feb 2016 09:22:45 -0800
Subject: [PATCH 022/311] 8150561: [AArch64] JVMCI improvements
Reviewed-by: kvn
---
hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp | 2 +-
hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp | 7 +++++++
.../src/jdk/vm/ci/hotspot/HotSpotVMConfig.java | 7 ++-----
hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp | 8 ++++++++
hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp | 8 ++++++++
hotspot/src/share/vm/runtime/frame.cpp | 4 ++--
6 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp
index 3e65f538de5..b302548557b 100644
--- a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp
@@ -74,7 +74,7 @@ void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, T
void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) {
address pc = _instructions->start() + pc_offset;
NativeInstruction* inst = nativeInstruction_at(pc);
- if (inst->is_adr_aligned()) {
+ if (inst->is_adr_aligned() || inst->is_ldr_literal()) {
address dest = _constants->start() + data_offset;
_instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS));
TRACE_jvmci_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset);
diff --git a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp
index 72c3479659c..d83017c1770 100644
--- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp
@@ -105,13 +105,20 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
inline friend NativeInstruction* nativeInstruction_at(address address);
static bool is_adrp_at(address instr);
+
static bool is_ldr_literal_at(address instr);
+
+ bool is_ldr_literal() {
+ return is_ldr_literal_at(addr_at(0));
+ }
+
static bool is_ldrw_to_zr(address instr);
static bool is_call_at(address instr) {
const uint32_t insn = (*(uint32_t*)instr);
return (insn >> 26) == 0b100101;
}
+
bool is_call() {
return is_call_at(addr_at(0));
}
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java
index 3e90a4d73b0..88da9e5b32a 100644
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java
@@ -1141,7 +1141,7 @@ public class HotSpotVMConfig {
@HotSpotVMField(name = "JavaFrameAnchor::_last_Java_sp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaSpOffset;
@HotSpotVMField(name = "JavaFrameAnchor::_last_Java_pc", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaPcOffset;
- @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET, archs = {"amd64"}) @Stable private int javaFrameAnchorLastJavaFpOffset;
+ @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET, archs = {"aarch64, amd64"}) @Stable private int javaFrameAnchorLastJavaFpOffset;
@HotSpotVMField(name = "JavaFrameAnchor::_flags", type = "int", get = HotSpotVMField.Type.OFFSET, archs = {"sparc"}) @Stable private int javaFrameAnchorFlagsOffset;
public int threadLastJavaSpOffset() {
@@ -1152,11 +1152,8 @@ public class HotSpotVMConfig {
return javaThreadAnchorOffset + javaFrameAnchorLastJavaPcOffset;
}
- /**
- * This value is only valid on AMD64.
- */
public int threadLastJavaFpOffset() {
- // TODO add an assert for AMD64
+ assert getHostArchitectureName().equals("aarch64") || getHostArchitectureName().equals("amd64");
return javaThreadAnchorOffset + javaFrameAnchorLastJavaFpOffset;
}
diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp
index cb06c34d4b6..2043b59d5e1 100644
--- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp
+++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp
@@ -551,6 +551,14 @@ JVMCIEnv::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, Hand
compiler, _debug_recorder, _dependencies, env, id,
has_unsafe_access, _has_wide_vector, installed_code, compiled_code, speculation_log);
cb = nm;
+ if (nm != NULL && env == NULL) {
+ DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, compiler);
+ bool printnmethods = directive->PrintAssemblyOption || directive->PrintNMethodsOption;
+ if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
+ nm->print_nmethod(printnmethods);
+ }
+ DirectivesStack::release(directive);
+ }
}
if (cb != NULL) {
diff --git a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
index 9456f34a0eb..99a7fbd3ac9 100644
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
@@ -592,6 +592,14 @@
#endif // TARGET_OS_FAMILY_bsd
+#ifdef TARGET_ARCH_aarch64
+
+#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \
+ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*)
+
+#endif // TARGET_ARCH_aarch64
+
+
#ifdef TARGET_ARCH_x86
#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \
diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp
index 3abf884cfbb..1a72cec46a8 100644
--- a/hotspot/src/share/vm/runtime/frame.cpp
+++ b/hotspot/src/share/vm/runtime/frame.cpp
@@ -662,14 +662,14 @@ void frame::print_on_error(outputStream* st, char* buf, int buflen, bool verbose
st->print("J %d%s %s ",
nm->compile_id(), (nm->is_osr_method() ? "%" : ""),
((nm->compiler() != NULL) ? nm->compiler()->name() : ""));
+ st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]",
+ buf, m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin());
#if INCLUDE_JVMCI
char* jvmciName = nm->jvmci_installed_code_name(buf, buflen);
if (jvmciName != NULL) {
st->print(" (%s)", jvmciName);
}
#endif
- st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]",
- buf, m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin());
} else {
st->print("J " PTR_FORMAT, p2i(pc()));
}
From abebc2da5c26b42098d9bd95d9a7d790916183ab Mon Sep 17 00:00:00 2001
From: Vladimir Ivanov
Date: Fri, 26 Feb 2016 01:58:26 +0300
Subject: [PATCH 023/311] 8150186: Folding mismatched accesses with @Stable is
incorrect
Reviewed-by: kvn, jrose, shade
---
hotspot/src/share/vm/ci/ciArray.cpp | 3 +-
hotspot/src/share/vm/opto/memnode.cpp | 14 +++-
.../unsafe/UnsafeGetStableArrayElement.java | 68 +++++++++++++++++++
3 files changed, 81 insertions(+), 4 deletions(-)
create mode 100644 hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java
diff --git a/hotspot/src/share/vm/ci/ciArray.cpp b/hotspot/src/share/vm/ci/ciArray.cpp
index f527d3ed538..04a6db8df3f 100644
--- a/hotspot/src/share/vm/ci/ciArray.cpp
+++ b/hotspot/src/share/vm/ci/ciArray.cpp
@@ -107,8 +107,9 @@ ciConstant ciArray::element_value_by_offset(intptr_t element_offset) {
intptr_t header = arrayOopDesc::base_offset_in_bytes(elembt);
intptr_t index = (element_offset - header) >> shift;
intptr_t offset = header + ((intptr_t)index << shift);
- if (offset != element_offset || index != (jint)index)
+ if (offset != element_offset || index != (jint)index || index < 0 || index >= length()) {
return ciConstant();
+ }
return element_value((jint) index);
}
diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp
index 75a699349f8..55ca4581485 100644
--- a/hotspot/src/share/vm/opto/memnode.cpp
+++ b/hotspot/src/share/vm/opto/memnode.cpp
@@ -1582,6 +1582,15 @@ LoadNode::load_array_final_field(const TypeKlassPtr *tkls,
return NULL;
}
+static bool is_mismatched_access(ciConstant con, BasicType loadbt) {
+ BasicType conbt = con.basic_type();
+ assert(conbt != T_NARROWOOP, "sanity");
+ if (loadbt == T_NARROWOOP || loadbt == T_ARRAY) {
+ loadbt = T_OBJECT;
+ }
+ return (conbt != loadbt);
+}
+
// Try to constant-fold a stable array element.
static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicType loadbt) {
assert(ary->const_oop(), "array should be constant");
@@ -1590,8 +1599,7 @@ static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicTyp
// Decode the results of GraphKit::array_element_address.
ciArray* aobj = ary->const_oop()->as_array();
ciConstant con = aobj->element_value_by_offset(off);
-
- if (con.basic_type() != T_ILLEGAL && !con.is_null_or_zero()) {
+ if (con.basic_type() != T_ILLEGAL && !is_mismatched_access(con, loadbt) && !con.is_null_or_zero()) {
const Type* con_type = Type::make_from_constant(con);
if (con_type != NULL) {
if (con_type->isa_aryptr()) {
@@ -1642,7 +1650,7 @@ const Type* LoadNode::Value(PhaseGVN* phase) const {
const bool off_beyond_header = ((uint)off >= (uint)min_base_off);
// Try to constant-fold a stable array element.
- if (FoldStableValues && ary->is_stable() && ary->const_oop() != NULL) {
+ if (FoldStableValues && !is_mismatched_access() && ary->is_stable() && ary->const_oop() != NULL) {
// Make sure the reference is not into the header and the offset is constant
if (off_beyond_header && adr->is_AddP() && off != Type::OffsetBot) {
const Type* con_type = fold_stable_ary_elem(ary, off, memory_type());
diff --git a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java
new file mode 100644
index 00000000000..afdb1a6e7a3
--- /dev/null
+++ b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+/*
+ * @test
+ * @summary tests on constant folding of unsafe get operations
+ * @library /testlibrary /test/lib
+ *
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions
+ * -Xbatch -XX:-TieredCompilation
+ * -XX:+FoldStableValues
+ * UnsafeGetStableArrayElement
+ *
+ * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions
+ * -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1
+ * -XX:+FoldStableValues
+ * UnsafeGetStableArrayElement
+ */
+import jdk.internal.misc.Unsafe;
+import jdk.internal.vm.annotation.Stable;
+import java.util.concurrent.Callable;
+
+import static jdk.internal.misc.Unsafe.*;
+import static jdk.test.lib.Asserts.*;
+
+public class UnsafeGetStableArrayElement {
+ @Stable static final byte[] STABLE_BYTE_ARRAY = new byte[] { 0, 1, -128, 127};
+
+ static final Unsafe U = Unsafe.getUnsafe();
+
+ static int testChar() {
+ return U.getChar(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET + 0 * ARRAY_CHAR_INDEX_SCALE) +
+ U.getChar(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET + 1 * ARRAY_CHAR_INDEX_SCALE);
+ }
+
+ static void run(Callable c) throws Exception {
+ Object first = c.call();
+ for (int i = 0; i < 20_000; i++) {
+ assertEQ(first, c.call());
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ run(UnsafeGetStableArrayElement::testChar);
+ }
+}
From a7d78599d772bff1a3b24c179370a55bec9a1f63 Mon Sep 17 00:00:00 2001
From: Vladimir Ivanov
Date: Fri, 26 Feb 2016 01:58:29 +0300
Subject: [PATCH 024/311] 8150436: Incorrect invocation mode when
linkToInteface linker is eliminated
Reviewed-by: kvn, shade
---
.../src/share/vm/runtime/sharedRuntime.cpp | 19 +++++++++++++------
.../jsr292/NonInlinedCall/InvokeTest.java | 5 ++++-
2 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp
index 5b862a01fab..4adec0c45ca 100644
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp
@@ -1134,12 +1134,19 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread,
MethodHandles::is_signature_polymorphic_intrinsic(id)) {
bc = MethodHandles::signature_polymorphic_intrinsic_bytecode(id);
- // Need to adjust invokehandle since inlining through signature-polymorphic
- // method happened.
- if (bc == Bytecodes::_invokehandle &&
- !MethodHandles::is_signature_polymorphic_method(attached_method())) {
- bc = attached_method->is_static() ? Bytecodes::_invokestatic
- : Bytecodes::_invokevirtual;
+ // Adjust invocation mode according to the attached method.
+ switch (bc) {
+ case Bytecodes::_invokeinterface:
+ if (!attached_method->method_holder()->is_interface()) {
+ bc = Bytecodes::_invokevirtual;
+ }
+ break;
+ case Bytecodes::_invokehandle:
+ if (!MethodHandles::is_signature_polymorphic_method(attached_method())) {
+ bc = attached_method->is_static() ? Bytecodes::_invokestatic
+ : Bytecodes::_invokevirtual;
+ }
+ break;
}
}
} else {
diff --git a/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java b/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java
index 02bdef91a10..90724b371a8 100644
--- a/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java
+++ b/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java
@@ -180,7 +180,10 @@ public class InvokeTest {
static void testInterface() {
System.out.println("linkToInterface");
- // Monomorphic case (optimized virtual call)
+ // Monomorphic case (optimized virtual call), concrete target method
+ run(() -> linkToInterface(new P1(), P1.class));
+
+ // Monomorphic case (optimized virtual call), default target method
run(() -> linkToInterface(new T(), I.class));
// Megamorphic case (virtual call)
From 782e6b33f2d63d73b14021f46fb36fdc218abed5 Mon Sep 17 00:00:00 2001
From: Vladimir Ivanov
Date: Fri, 26 Feb 2016 15:54:55 +0300
Subject: [PATCH 025/311] 8068038: C2: large constant offsets aren't handled on
SPARC
Reviewed-by: kvn
---
hotspot/src/cpu/sparc/vm/sparc.ad | 368 ++++++++++++++----------------
1 file changed, 175 insertions(+), 193 deletions(-)
diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad
index 6bbef4e5708..5cf884a5501 100644
--- a/hotspot/src/cpu/sparc/vm/sparc.ad
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad
@@ -948,28 +948,28 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, PhaseRegAlloc* ra, const MachNode* n,
}
#endif
- uint instr;
- instr = (Assembler::ldst_op << 30)
- | (dst_enc << 25)
- | (primary << 19)
- | (src1_enc << 14);
+ uint instr = (Assembler::ldst_op << 30)
+ | (dst_enc << 25)
+ | (primary << 19)
+ | (src1_enc << 14);
uint index = src2_enc;
int disp = disp32;
if (src1_enc == R_SP_enc || src1_enc == R_FP_enc) {
disp += STACK_BIAS;
- // Quick fix for JDK-8029668: check that stack offset fits, bailout if not
+ // Check that stack offset fits, load into O7 if not
if (!Assembler::is_simm13(disp)) {
- ra->C->record_method_not_compilable("unable to handle large constant offsets");
- return;
+ MacroAssembler _masm(&cbuf);
+ __ set(disp, O7);
+ if (index != R_G0_enc) {
+ __ add(O7, reg_to_register_object(index), O7);
+ }
+ index = R_O7_enc;
+ disp = 0;
}
}
- // We should have a compiler bailout here rather than a guarantee.
- // Better yet would be some mechanism to handle variable-size matches correctly.
- guarantee(Assembler::is_simm13(disp), "Do not match large constant offsets" );
-
if( disp == 0 ) {
// use reg-reg form
// bit 13 is already zero
@@ -983,7 +983,7 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, PhaseRegAlloc* ra, const MachNode* n,
cbuf.insts()->emit_int32(instr);
#ifdef ASSERT
- {
+ if (VerifyOops) {
MacroAssembler _masm(&cbuf);
if (is_verified_oop_base) {
__ verify_oop(reg_to_register_object(src1_enc));
@@ -1342,7 +1342,7 @@ int MachEpilogNode::safepoint_offset() const {
// Figure out which register class each belongs in: rc_int, rc_float, rc_stack
enum RC { rc_bad, rc_int, rc_float, rc_stack };
static enum RC rc_class( OptoReg::Name reg ) {
- if( !OptoReg::is_valid(reg) ) return rc_bad;
+ if (!OptoReg::is_valid(reg)) return rc_bad;
if (OptoReg::is_stack(reg)) return rc_stack;
VMReg r = OptoReg::as_VMReg(reg);
if (r->is_Register()) return rc_int;
@@ -1350,66 +1350,79 @@ static enum RC rc_class( OptoReg::Name reg ) {
return rc_float;
}
-static int impl_helper(const MachNode* mach, CodeBuffer* cbuf, PhaseRegAlloc* ra, bool do_size, bool is_load, int offset, int reg, int opcode, const char *op_str, int size, outputStream* st ) {
+#ifndef PRODUCT
+ATTRIBUTE_PRINTF(2, 3)
+static void print_helper(outputStream* st, const char* format, ...) {
+ if (st->position() > 0) {
+ st->cr();
+ st->sp();
+ }
+ va_list ap;
+ va_start(ap, format);
+ st->vprint(format, ap);
+ va_end(ap);
+}
+#endif // !PRODUCT
+
+static void impl_helper(const MachNode* mach, CodeBuffer* cbuf, PhaseRegAlloc* ra, bool is_load, int offset, int reg, int opcode, const char *op_str, outputStream* st) {
if (cbuf) {
emit_form3_mem_reg(*cbuf, ra, mach, opcode, -1, R_SP_enc, offset, 0, Matcher::_regEncode[reg]);
}
#ifndef PRODUCT
- else if (!do_size) {
- if (size != 0) st->print("\n\t");
- if (is_load) st->print("%s [R_SP + #%d],R_%s\t! spill",op_str,offset,OptoReg::regname(reg));
- else st->print("%s R_%s,[R_SP + #%d]\t! spill",op_str,OptoReg::regname(reg),offset);
+ else {
+ if (is_load) {
+ print_helper(st, "%s [R_SP + #%d],R_%s\t! spill", op_str, offset, OptoReg::regname(reg));
+ } else {
+ print_helper(st, "%s R_%s,[R_SP + #%d]\t! spill", op_str, OptoReg::regname(reg), offset);
+ }
}
#endif
- return size+4;
}
-static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int op1, int op2, const char *op_str, int size, outputStream* st ) {
- if( cbuf ) emit3( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst], op1, 0, op2, Matcher::_regEncode[src] );
+static void impl_mov_helper(CodeBuffer *cbuf, int src, int dst, int op1, int op2, const char *op_str, outputStream* st) {
+ if (cbuf) {
+ emit3(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst], op1, 0, op2, Matcher::_regEncode[src]);
+ }
#ifndef PRODUCT
- else if( !do_size ) {
- if( size != 0 ) st->print("\n\t");
- st->print("%s R_%s,R_%s\t! spill",op_str,OptoReg::regname(src),OptoReg::regname(dst));
+ else {
+ print_helper(st, "%s R_%s,R_%s\t! spill", op_str, OptoReg::regname(src), OptoReg::regname(dst));
}
#endif
- return size+4;
}
-uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
- PhaseRegAlloc *ra_,
- bool do_size,
- outputStream* st ) const {
+static void mach_spill_copy_implementation_helper(const MachNode* mach,
+ CodeBuffer *cbuf,
+ PhaseRegAlloc *ra_,
+ outputStream* st) {
// Get registers to move
- OptoReg::Name src_second = ra_->get_reg_second(in(1));
- OptoReg::Name src_first = ra_->get_reg_first(in(1));
- OptoReg::Name dst_second = ra_->get_reg_second(this );
- OptoReg::Name dst_first = ra_->get_reg_first(this );
+ OptoReg::Name src_second = ra_->get_reg_second(mach->in(1));
+ OptoReg::Name src_first = ra_->get_reg_first(mach->in(1));
+ OptoReg::Name dst_second = ra_->get_reg_second(mach);
+ OptoReg::Name dst_first = ra_->get_reg_first(mach);
enum RC src_second_rc = rc_class(src_second);
- enum RC src_first_rc = rc_class(src_first);
+ enum RC src_first_rc = rc_class(src_first);
enum RC dst_second_rc = rc_class(dst_second);
- enum RC dst_first_rc = rc_class(dst_first);
+ enum RC dst_first_rc = rc_class(dst_first);
- assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" );
+ assert(OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register");
- // Generate spill code!
- int size = 0;
-
- if( src_first == dst_first && src_second == dst_second )
- return size; // Self copy, no move
+ if (src_first == dst_first && src_second == dst_second) {
+ return; // Self copy, no move
+ }
// --------------------------------------
// Check for mem-mem move. Load into unused float registers and fall into
// the float-store case.
- if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) {
+ if (src_first_rc == rc_stack && dst_first_rc == rc_stack) {
int offset = ra_->reg2offset(src_first);
// Further check for aligned-adjacent pair, so we can use a double load
- if( (src_first&1)==0 && src_first+1 == src_second ) {
+ if ((src_first&1) == 0 && src_first+1 == src_second) {
src_second = OptoReg::Name(R_F31_num);
src_second_rc = rc_float;
- size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F30_num,Assembler::lddf_op3,"LDDF",size, st);
+ impl_helper(mach, cbuf, ra_, true, offset, R_F30_num, Assembler::lddf_op3, "LDDF", st);
} else {
- size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F30_num,Assembler::ldf_op3 ,"LDF ",size, st);
+ impl_helper(mach, cbuf, ra_, true, offset, R_F30_num, Assembler::ldf_op3, "LDF ", st);
}
src_first = OptoReg::Name(R_F30_num);
src_first_rc = rc_float;
@@ -1417,7 +1430,7 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
if( src_second_rc == rc_stack && dst_second_rc == rc_stack ) {
int offset = ra_->reg2offset(src_second);
- size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F31_num,Assembler::ldf_op3,"LDF ",size, st);
+ impl_helper(mach, cbuf, ra_, true, offset, R_F31_num, Assembler::ldf_op3, "LDF ", st);
src_second = OptoReg::Name(R_F31_num);
src_second_rc = rc_float;
}
@@ -1427,36 +1440,38 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS < 3) {
int offset = frame::register_save_words*wordSize;
if (cbuf) {
- emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16 );
- impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st);
- impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st);
- emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16 );
+ emit3_simm13(*cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16);
+ impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st);
+ impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st);
+ emit3_simm13(*cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16);
}
#ifndef PRODUCT
- else if (!do_size) {
- if (size != 0) st->print("\n\t");
- st->print( "SUB R_SP,16,R_SP\n");
- impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st);
- impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st);
- st->print("\tADD R_SP,16,R_SP\n");
+ else {
+ print_helper(st, "SUB R_SP,16,R_SP");
+ impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st);
+ impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st);
+ print_helper(st, "ADD R_SP,16,R_SP");
}
#endif
- size += 16;
}
// Check for float->int copy on T4
if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS >= 3) {
// Further check for aligned-adjacent pair, so we can use a double move
- if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second)
- return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mdtox_opf,"MOVDTOX",size, st);
- size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mstouw_opf,"MOVSTOUW",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mdtox_opf, "MOVDTOX", st);
+ return;
+ }
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mstouw_opf, "MOVSTOUW", st);
}
// Check for int->float copy on T4
if (src_first_rc == rc_int && dst_first_rc == rc_float && UseVIS >= 3) {
// Further check for aligned-adjacent pair, so we can use a double move
- if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second)
- return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mxtod_opf,"MOVXTOD",size, st);
- size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mwtos_opf,"MOVWTOS",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mxtod_opf, "MOVXTOD", st);
+ return;
+ }
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mwtos_opf, "MOVWTOS", st);
}
// --------------------------------------
@@ -1466,10 +1481,10 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
// there. Misaligned sources only come from native-long-returns (handled
// special below).
#ifndef _LP64
- if( src_first_rc == rc_int && // source is already big-endian
+ if (src_first_rc == rc_int && // source is already big-endian
src_second_rc != rc_bad && // 64-bit move
- ((dst_first&1)!=0 || dst_second != dst_first+1) ) { // misaligned dst
- assert( (src_first&1)==0 && src_second == src_first+1, "source must be aligned" );
+ ((dst_first & 1) != 0 || dst_second != dst_first + 1)) { // misaligned dst
+ assert((src_first & 1) == 0 && src_second == src_first + 1, "source must be aligned");
// Do the big-endian flop.
OptoReg::Name tmp = dst_first ; dst_first = dst_second ; dst_second = tmp ;
enum RC tmp_rc = dst_first_rc; dst_first_rc = dst_second_rc; dst_second_rc = tmp_rc;
@@ -1478,30 +1493,28 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
// --------------------------------------
// Check for integer reg-reg copy
- if( src_first_rc == rc_int && dst_first_rc == rc_int ) {
+ if (src_first_rc == rc_int && dst_first_rc == rc_int) {
#ifndef _LP64
- if( src_first == R_O0_num && src_second == R_O1_num ) { // Check for the evil O0/O1 native long-return case
+ if (src_first == R_O0_num && src_second == R_O1_num) { // Check for the evil O0/O1 native long-return case
// Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value
// as stored in memory. On a big-endian machine like SPARC, this means that the _second
// operand contains the least significant word of the 64-bit value and vice versa.
OptoReg::Name tmp = OptoReg::Name(R_O7_num);
- assert( (dst_first&1)==0 && dst_second == dst_first+1, "return a native O0/O1 long to an aligned-adjacent 64-bit reg" );
+ assert((dst_first & 1) == 0 && dst_second == dst_first + 1, "return a native O0/O1 long to an aligned-adjacent 64-bit reg" );
// Shift O0 left in-place, zero-extend O1, then OR them into the dst
- if( cbuf ) {
- emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[tmp], Assembler::sllx_op3, Matcher::_regEncode[src_first], 0x1020 );
- emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[src_second], Assembler::srl_op3, Matcher::_regEncode[src_second], 0x0000 );
- emit3 ( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler:: or_op3, Matcher::_regEncode[tmp], 0, Matcher::_regEncode[src_second] );
+ if ( cbuf ) {
+ emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tmp], Assembler::sllx_op3, Matcher::_regEncode[src_first], 0x1020);
+ emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[src_second], Assembler::srl_op3, Matcher::_regEncode[src_second], 0x0000);
+ emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler:: or_op3, Matcher::_regEncode[tmp], 0, Matcher::_regEncode[src_second]);
#ifndef PRODUCT
- } else if( !do_size ) {
- if( size != 0 ) st->print("\n\t");
- st->print("SLLX R_%s,32,R_%s\t! Move O0-first to O7-high\n\t", OptoReg::regname(src_first), OptoReg::regname(tmp));
- st->print("SRL R_%s, 0,R_%s\t! Zero-extend O1\n\t", OptoReg::regname(src_second), OptoReg::regname(src_second));
- st->print("OR R_%s,R_%s,R_%s\t! spill",OptoReg::regname(tmp), OptoReg::regname(src_second), OptoReg::regname(dst_first));
+ } else {
+ print_helper(st, "SLLX R_%s,32,R_%s\t! Move O0-first to O7-high\n\t", OptoReg::regname(src_first), OptoReg::regname(tmp));
+ print_helper(st, "SRL R_%s, 0,R_%s\t! Zero-extend O1\n\t", OptoReg::regname(src_second), OptoReg::regname(src_second));
+ print_helper(st, "OR R_%s,R_%s,R_%s\t! spill",OptoReg::regname(tmp), OptoReg::regname(src_second), OptoReg::regname(dst_first));
#endif
}
- return size+12;
- }
- else if( dst_first == R_I0_num && dst_second == R_I1_num ) {
+ return;
+ } else if (dst_first == R_I0_num && dst_second == R_I1_num) {
// returning a long value in I0/I1
// a SpillCopy must be able to target a return instruction's reg_class
// Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value
@@ -1511,27 +1524,25 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
if (src_first == dst_first) {
tdest = OptoReg::Name(R_O7_num);
- size += 4;
}
- if( cbuf ) {
- assert( (src_first&1) == 0 && (src_first+1) == src_second, "return value was in an aligned-adjacent 64-bit reg");
+ if (cbuf) {
+ assert((src_first & 1) == 0 && (src_first + 1) == src_second, "return value was in an aligned-adjacent 64-bit reg");
// Shift value in upper 32-bits of src to lower 32-bits of I0; move lower 32-bits to I1
// ShrL_reg_imm6
- emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[tdest], Assembler::srlx_op3, Matcher::_regEncode[src_second], 32 | 0x1000 );
+ emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tdest], Assembler::srlx_op3, Matcher::_regEncode[src_second], 32 | 0x1000);
// ShrR_reg_imm6 src, 0, dst
- emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srl_op3, Matcher::_regEncode[src_first], 0x0000 );
+ emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srl_op3, Matcher::_regEncode[src_first], 0x0000);
if (tdest != dst_first) {
- emit3 ( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler::or_op3, 0/*G0*/, 0/*op2*/, Matcher::_regEncode[tdest] );
+ emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler::or_op3, 0/*G0*/, 0/*op2*/, Matcher::_regEncode[tdest]);
}
}
#ifndef PRODUCT
- else if( !do_size ) {
- if( size != 0 ) st->print("\n\t"); // %%%%% !!!!!
- st->print("SRLX R_%s,32,R_%s\t! Extract MSW\n\t",OptoReg::regname(src_second),OptoReg::regname(tdest));
- st->print("SRL R_%s, 0,R_%s\t! Extract LSW\n\t",OptoReg::regname(src_first),OptoReg::regname(dst_second));
+ else {
+ print_helper(st, "SRLX R_%s,32,R_%s\t! Extract MSW\n\t",OptoReg::regname(src_second),OptoReg::regname(tdest));
+ print_helper(st, "SRL R_%s, 0,R_%s\t! Extract LSW\n\t",OptoReg::regname(src_first),OptoReg::regname(dst_second));
if (tdest != dst_first) {
- st->print("MOV R_%s,R_%s\t! spill\n\t", OptoReg::regname(tdest), OptoReg::regname(dst_first));
+ print_helper(st, "MOV R_%s,R_%s\t! spill\n\t", OptoReg::regname(tdest), OptoReg::regname(dst_first));
}
}
#endif // PRODUCT
@@ -1539,65 +1550,77 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
}
#endif // !_LP64
// Else normal reg-reg copy
- assert( src_second != dst_first, "smashed second before evacuating it" );
- size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::or_op3,0,"MOV ",size, st);
- assert( (src_first&1) == 0 && (dst_first&1) == 0, "never move second-halves of int registers" );
+ assert(src_second != dst_first, "smashed second before evacuating it");
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::or_op3, 0, "MOV ", st);
+ assert((src_first & 1) == 0 && (dst_first & 1) == 0, "never move second-halves of int registers");
// This moves an aligned adjacent pair.
// See if we are done.
- if( src_first+1 == src_second && dst_first+1 == dst_second )
- return size;
+ if (src_first + 1 == src_second && dst_first + 1 == dst_second) {
+ return;
+ }
}
// Check for integer store
- if( src_first_rc == rc_int && dst_first_rc == rc_stack ) {
+ if (src_first_rc == rc_int && dst_first_rc == rc_stack) {
int offset = ra_->reg2offset(dst_first);
// Further check for aligned-adjacent pair, so we can use a double store
- if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second )
- return impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stx_op3,"STX ",size, st);
- size = impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stw_op3,"STW ",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stx_op3, "STX ", st);
+ return;
+ }
+ impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stw_op3, "STW ", st);
}
// Check for integer load
- if( dst_first_rc == rc_int && src_first_rc == rc_stack ) {
+ if (dst_first_rc == rc_int && src_first_rc == rc_stack) {
int offset = ra_->reg2offset(src_first);
// Further check for aligned-adjacent pair, so we can use a double load
- if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second )
- return impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::ldx_op3 ,"LDX ",size, st);
- size = impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::ldx_op3, "LDX ", st);
+ return;
+ }
+ impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st);
}
// Check for float reg-reg copy
- if( src_first_rc == rc_float && dst_first_rc == rc_float ) {
+ if (src_first_rc == rc_float && dst_first_rc == rc_float) {
// Further check for aligned-adjacent pair, so we can use a double move
- if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second )
- return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::fpop1_op3,Assembler::fmovd_opf,"FMOVD",size, st);
- size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::fpop1_op3,Assembler::fmovs_opf,"FMOVS",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::fpop1_op3, Assembler::fmovd_opf, "FMOVD", st);
+ return;
+ }
+ impl_mov_helper(cbuf, src_first, dst_first, Assembler::fpop1_op3, Assembler::fmovs_opf, "FMOVS", st);
}
// Check for float store
- if( src_first_rc == rc_float && dst_first_rc == rc_stack ) {
+ if (src_first_rc == rc_float && dst_first_rc == rc_stack) {
int offset = ra_->reg2offset(dst_first);
// Further check for aligned-adjacent pair, so we can use a double store
- if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second )
- return impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stdf_op3,"STDF",size, st);
- size = impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stdf_op3, "STDF", st);
+ return;
+ }
+ impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st);
}
// Check for float load
- if( dst_first_rc == rc_float && src_first_rc == rc_stack ) {
+ if (dst_first_rc == rc_float && src_first_rc == rc_stack) {
int offset = ra_->reg2offset(src_first);
// Further check for aligned-adjacent pair, so we can use a double load
- if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second )
- return impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::lddf_op3,"LDDF",size, st);
- size = impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::ldf_op3 ,"LDF ",size, st);
+ if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) {
+ impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lddf_op3, "LDDF", st);
+ return;
+ }
+ impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::ldf_op3, "LDF ", st);
}
// --------------------------------------------------------------------
// Check for hi bits still needing moving. Only happens for misaligned
// arguments to native calls.
- if( src_second == dst_second )
- return size; // Self copy; no move
- assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" );
+ if (src_second == dst_second) {
+ return; // Self copy; no move
+ }
+ assert(src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad");
#ifndef _LP64
// In the LP64 build, all registers can be moved as aligned/adjacent
@@ -1609,52 +1632,57 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
// 32-bits of a 64-bit register, but are needed in low bits of another
// register (else it's a hi-bits-to-hi-bits copy which should have
// happened already as part of a 64-bit move)
- if( src_second_rc == rc_int && dst_second_rc == rc_int ) {
- assert( (src_second&1)==1, "its the evil O0/O1 native return case" );
- assert( (dst_second&1)==0, "should have moved with 1 64-bit move" );
+ if (src_second_rc == rc_int && dst_second_rc == rc_int) {
+ assert((src_second & 1) == 1, "its the evil O0/O1 native return case");
+ assert((dst_second & 1) == 0, "should have moved with 1 64-bit move");
// Shift src_second down to dst_second's low bits.
- if( cbuf ) {
- emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020 );
+ if (cbuf) {
+ emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020);
#ifndef PRODUCT
- } else if( !do_size ) {
- if( size != 0 ) st->print("\n\t");
- st->print("SRLX R_%s,32,R_%s\t! spill: Move high bits down low",OptoReg::regname(src_second-1),OptoReg::regname(dst_second));
+ } else {
+ print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second - 1), OptoReg::regname(dst_second));
#endif
}
- return size+4;
+ return;
}
// Check for high word integer store. Must down-shift the hi bits
// into a temp register, then fall into the case of storing int bits.
- if( src_second_rc == rc_int && dst_second_rc == rc_stack && (src_second&1)==1 ) {
+ if (src_second_rc == rc_int && dst_second_rc == rc_stack && (src_second & 1) == 1) {
// Shift src_second down to dst_second's low bits.
- if( cbuf ) {
- emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[R_O7_num], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020 );
+ if (cbuf) {
+ emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[R_O7_num], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020);
#ifndef PRODUCT
- } else if( !do_size ) {
- if( size != 0 ) st->print("\n\t");
- st->print("SRLX R_%s,32,R_%s\t! spill: Move high bits down low",OptoReg::regname(src_second-1),OptoReg::regname(R_O7_num));
+ } else {
+ print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second-1), OptoReg::regname(R_O7_num));
#endif
}
- size+=4;
src_second = OptoReg::Name(R_O7_num); // Not R_O7H_num!
}
// Check for high word integer load
- if( dst_second_rc == rc_int && src_second_rc == rc_stack )
- return impl_helper(this,cbuf,ra_,do_size,true ,ra_->reg2offset(src_second),dst_second,Assembler::lduw_op3,"LDUW",size, st);
+ if (dst_second_rc == rc_int && src_second_rc == rc_stack)
+ return impl_helper(this, cbuf, ra_, true, ra_->reg2offset(src_second), dst_second, Assembler::lduw_op3, "LDUW", size, st);
// Check for high word integer store
- if( src_second_rc == rc_int && dst_second_rc == rc_stack )
- return impl_helper(this,cbuf,ra_,do_size,false,ra_->reg2offset(dst_second),src_second,Assembler::stw_op3 ,"STW ",size, st);
+ if (src_second_rc == rc_int && dst_second_rc == rc_stack)
+ return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stw_op3, "STW ", size, st);
// Check for high word float store
- if( src_second_rc == rc_float && dst_second_rc == rc_stack )
- return impl_helper(this,cbuf,ra_,do_size,false,ra_->reg2offset(dst_second),src_second,Assembler::stf_op3 ,"STF ",size, st);
+ if (src_second_rc == rc_float && dst_second_rc == rc_stack)
+ return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stf_op3, "STF ", size, st);
#endif // !_LP64
Unimplemented();
+}
+
+uint MachSpillCopyNode::implementation(CodeBuffer *cbuf,
+ PhaseRegAlloc *ra_,
+ bool do_size,
+ outputStream* st) const {
+ assert(!do_size, "not supported");
+ mach_spill_copy_implementation_helper(this, cbuf, ra_, st);
return 0;
}
@@ -1669,19 +1697,19 @@ void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
}
uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const {
- return implementation( NULL, ra_, true, NULL );
+ return MachNode::size(ra_);
}
//=============================================================================
#ifndef PRODUCT
-void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const {
+void MachNopNode::format(PhaseRegAlloc *, outputStream *st) const {
st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count);
}
#endif
-void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const {
+void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *) const {
MacroAssembler _masm(&cbuf);
- for(int i = 0; i < _count; i += 1) {
+ for (int i = 0; i < _count; i += 1) {
__ nop();
}
}
@@ -5197,7 +5225,6 @@ instruct stkI_to_regF(regF dst, stackSlotI src) %{
// No match rule to avoid chain rule match.
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDF $src,$dst\t! stkI to regF" %}
opcode(Assembler::ldf_op3);
ins_encode(simple_form3_mem_reg(src, dst));
@@ -5208,7 +5235,6 @@ instruct stkL_to_regD(regD dst, stackSlotL src) %{
// No match rule to avoid chain rule match.
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDDF $src,$dst\t! stkL to regD" %}
opcode(Assembler::lddf_op3);
ins_encode(simple_form3_mem_reg(src, dst));
@@ -5219,7 +5245,6 @@ instruct regF_to_stkI(stackSlotI dst, regF src) %{
// No match rule to avoid chain rule match.
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STF $src,$dst\t! regF to stkI" %}
opcode(Assembler::stf_op3);
ins_encode(simple_form3_mem_reg(dst, src));
@@ -5230,7 +5255,6 @@ instruct regD_to_stkL(stackSlotL dst, regD src) %{
// No match rule to avoid chain rule match.
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STDF $src,$dst\t! regD to stkL" %}
opcode(Assembler::stdf_op3);
ins_encode(simple_form3_mem_reg(dst, src));
@@ -5240,7 +5264,6 @@ instruct regD_to_stkL(stackSlotL dst, regD src) %{
instruct regI_to_stkLHi(stackSlotL dst, iRegI src) %{
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST*2);
- size(8);
format %{ "STW $src,$dst.hi\t! long\n\t"
"STW R_G0,$dst.lo" %}
opcode(Assembler::stw_op3);
@@ -5252,7 +5275,6 @@ instruct regL_to_stkD(stackSlotD dst, iRegL src) %{
// No match rule to avoid chain rule match.
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$dst\t! regL to stkD" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( dst, src ) );
@@ -5266,7 +5288,6 @@ instruct stkI_to_regI( iRegI dst, stackSlotI src ) %{
match(Set dst src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDUW $src,$dst\t!stk" %}
opcode(Assembler::lduw_op3);
ins_encode(simple_form3_mem_reg( src, dst ) );
@@ -5278,7 +5299,6 @@ instruct regI_to_stkI( stackSlotI dst, iRegI src ) %{
match(Set dst src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STW $src,$dst\t!stk" %}
opcode(Assembler::stw_op3);
ins_encode(simple_form3_mem_reg( dst, src ) );
@@ -5290,7 +5310,6 @@ instruct stkL_to_regL( iRegL dst, stackSlotL src ) %{
match(Set dst src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDX $src,$dst\t! long" %}
opcode(Assembler::ldx_op3);
ins_encode(simple_form3_mem_reg( src, dst ) );
@@ -5302,7 +5321,6 @@ instruct regL_to_stkL(stackSlotL dst, iRegL src) %{
match(Set dst src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$dst\t! long" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( dst, src ) );
@@ -5314,7 +5332,6 @@ instruct regL_to_stkL(stackSlotL dst, iRegL src) %{
instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{
match(Set dst src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDX $src,$dst\t!ptr" %}
opcode(Assembler::ldx_op3);
ins_encode(simple_form3_mem_reg( src, dst ) );
@@ -5325,7 +5342,6 @@ instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{
instruct regP_to_stkP(stackSlotP dst, iRegP src) %{
match(Set dst src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$dst\t!ptr" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( dst, src ) );
@@ -5771,7 +5787,6 @@ instruct loadL_unaligned(iRegL dst, memory mem, o7RegI tmp) %{
match(Set dst (LoadL_unaligned mem));
effect(KILL tmp);
ins_cost(MEMORY_REF_COST*2+DEFAULT_COST);
- size(16);
format %{ "LDUW $mem+4,R_O7\t! misaligned long\n"
"\tLDUW $mem ,$dst\n"
"\tSLLX #32, $dst, $dst\n"
@@ -5786,7 +5801,6 @@ instruct loadRange(iRegI dst, memory mem) %{
match(Set dst (LoadRange mem));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDUW $mem,$dst\t! range" %}
opcode(Assembler::lduw_op3);
ins_encode(simple_form3_mem_reg( mem, dst ) );
@@ -5797,7 +5811,6 @@ instruct loadRange(iRegI dst, memory mem) %{
instruct loadI_freg(regF dst, memory mem) %{
match(Set dst (LoadI mem));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDF $mem,$dst\t! for fitos/fitod" %}
opcode(Assembler::ldf_op3);
@@ -5876,7 +5889,6 @@ instruct loadD(regD dst, memory mem) %{
match(Set dst (LoadD mem));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDDF $mem,$dst" %}
opcode(Assembler::lddf_op3);
ins_encode(simple_form3_mem_reg( mem, dst ) );
@@ -5887,7 +5899,6 @@ instruct loadD(regD dst, memory mem) %{
instruct loadD_unaligned(regD_low dst, memory mem ) %{
match(Set dst (LoadD_unaligned mem));
ins_cost(MEMORY_REF_COST*2+DEFAULT_COST);
- size(8);
format %{ "LDF $mem ,$dst.hi\t! misaligned double\n"
"\tLDF $mem+4,$dst.lo\t!" %}
opcode(Assembler::ldf_op3);
@@ -5900,7 +5911,6 @@ instruct loadF(regF dst, memory mem) %{
match(Set dst (LoadF mem));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDF $mem,$dst" %}
opcode(Assembler::ldf_op3);
ins_encode(simple_form3_mem_reg( mem, dst ) );
@@ -6119,7 +6129,6 @@ instruct prefetchAlloc( memory mem ) %{
predicate(AllocatePrefetchInstr == 0);
match( PrefetchAllocation mem );
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "PREFETCH $mem,2\t! Prefetch allocation" %}
opcode(Assembler::prefetch_op3);
@@ -6175,7 +6184,6 @@ instruct storeB(memory mem, iRegI src) %{
match(Set mem (StoreB mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STB $src,$mem\t! byte" %}
opcode(Assembler::stb_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6186,7 +6194,6 @@ instruct storeB0(memory mem, immI0 src) %{
match(Set mem (StoreB mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STB $src,$mem\t! byte" %}
opcode(Assembler::stb_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -6197,7 +6204,6 @@ instruct storeCM0(memory mem, immI0 src) %{
match(Set mem (StoreCM mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STB $src,$mem\t! CMS card-mark byte 0" %}
opcode(Assembler::stb_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -6209,7 +6215,6 @@ instruct storeC(memory mem, iRegI src) %{
match(Set mem (StoreC mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STH $src,$mem\t! short" %}
opcode(Assembler::sth_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6220,7 +6225,6 @@ instruct storeC0(memory mem, immI0 src) %{
match(Set mem (StoreC mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STH $src,$mem\t! short" %}
opcode(Assembler::sth_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -6232,7 +6236,6 @@ instruct storeI(memory mem, iRegI src) %{
match(Set mem (StoreI mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STW $src,$mem" %}
opcode(Assembler::stw_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6243,7 +6246,6 @@ instruct storeI(memory mem, iRegI src) %{
instruct storeL(memory mem, iRegL src) %{
match(Set mem (StoreL mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$mem\t! long" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6254,7 +6256,6 @@ instruct storeI0(memory mem, immI0 src) %{
match(Set mem (StoreI mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STW $src,$mem" %}
opcode(Assembler::stw_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -6265,7 +6266,6 @@ instruct storeL0(memory mem, immL0 src) %{
match(Set mem (StoreL mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$mem" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -6277,7 +6277,6 @@ instruct storeI_Freg(memory mem, regF src) %{
match(Set mem (StoreI mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STF $src,$mem\t! after fstoi/fdtoi" %}
opcode(Assembler::stf_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6288,7 +6287,6 @@ instruct storeI_Freg(memory mem, regF src) %{
instruct storeP(memory dst, sp_ptr_RegP src) %{
match(Set dst (StoreP dst src));
ins_cost(MEMORY_REF_COST);
- size(4);
#ifndef _LP64
format %{ "STW $src,$dst\t! ptr" %}
@@ -6304,7 +6302,6 @@ instruct storeP(memory dst, sp_ptr_RegP src) %{
instruct storeP0(memory dst, immP0 src) %{
match(Set dst (StoreP dst src));
ins_cost(MEMORY_REF_COST);
- size(4);
#ifndef _LP64
format %{ "STW $src,$dst\t! ptr" %}
@@ -6379,7 +6376,6 @@ instruct storeD( memory mem, regD src) %{
match(Set mem (StoreD mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STDF $src,$mem" %}
opcode(Assembler::stdf_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6390,7 +6386,6 @@ instruct storeD0( memory mem, immD0 src) %{
match(Set mem (StoreD mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$mem" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -6402,7 +6397,6 @@ instruct storeF( memory mem, regF src) %{
match(Set mem (StoreF mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STF $src,$mem" %}
opcode(Assembler::stf_op3);
ins_encode(simple_form3_mem_reg( mem, src ) );
@@ -6413,7 +6407,6 @@ instruct storeF0( memory mem, immF0 src) %{
match(Set mem (StoreF mem src));
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STW $src,$mem\t! storeF0" %}
opcode(Assembler::stw_op3);
ins_encode(simple_form3_mem_reg( mem, R_G0 ) );
@@ -7068,7 +7061,6 @@ instruct loadPLocked(iRegP dst, memory mem) %{
ins_cost(MEMORY_REF_COST);
#ifndef _LP64
- size(4);
format %{ "LDUW $mem,$dst\t! ptr" %}
opcode(Assembler::lduw_op3, 0, REGP_OP);
#else
@@ -8138,7 +8130,6 @@ instruct MoveF2I_stack_reg(iRegI dst, stackSlotF src) %{
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDUW $src,$dst\t! MoveF2I" %}
opcode(Assembler::lduw_op3);
ins_encode(simple_form3_mem_reg( src, dst ) );
@@ -8150,7 +8141,6 @@ instruct MoveI2F_stack_reg(regF dst, stackSlotI src) %{
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDF $src,$dst\t! MoveI2F" %}
opcode(Assembler::ldf_op3);
ins_encode(simple_form3_mem_reg(src, dst));
@@ -8162,7 +8152,6 @@ instruct MoveD2L_stack_reg(iRegL dst, stackSlotD src) %{
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDX $src,$dst\t! MoveD2L" %}
opcode(Assembler::ldx_op3);
ins_encode(simple_form3_mem_reg( src, dst ) );
@@ -8174,7 +8163,6 @@ instruct MoveL2D_stack_reg(regD dst, stackSlotL src) %{
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "LDDF $src,$dst\t! MoveL2D" %}
opcode(Assembler::lddf_op3);
ins_encode(simple_form3_mem_reg(src, dst));
@@ -8186,7 +8174,6 @@ instruct MoveF2I_reg_stack(stackSlotI dst, regF src) %{
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STF $src,$dst\t! MoveF2I" %}
opcode(Assembler::stf_op3);
ins_encode(simple_form3_mem_reg(dst, src));
@@ -8198,7 +8185,6 @@ instruct MoveI2F_reg_stack(stackSlotF dst, iRegI src) %{
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STW $src,$dst\t! MoveI2F" %}
opcode(Assembler::stw_op3);
ins_encode(simple_form3_mem_reg( dst, src ) );
@@ -8210,7 +8196,6 @@ instruct MoveD2L_reg_stack(stackSlotL dst, regD src) %{
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STDF $src,$dst\t! MoveD2L" %}
opcode(Assembler::stdf_op3);
ins_encode(simple_form3_mem_reg(dst, src));
@@ -8222,7 +8207,6 @@ instruct MoveL2D_reg_stack(stackSlotD dst, iRegL src) %{
effect(DEF dst, USE src);
ins_cost(MEMORY_REF_COST);
- size(4);
format %{ "STX $src,$dst\t! MoveL2D" %}
opcode(Assembler::stx_op3);
ins_encode(simple_form3_mem_reg( dst, src ) );
@@ -8427,7 +8411,6 @@ instruct convI2D_reg(regD_low dst, iRegI src) %{
instruct convI2D_mem(regD_low dst, memory mem) %{
match(Set dst (ConvI2D (LoadI mem)));
ins_cost(DEFAULT_COST + MEMORY_REF_COST);
- size(8);
format %{ "LDF $mem,$dst\n\t"
"FITOD $dst,$dst" %}
opcode(Assembler::ldf_op3, Assembler::fitod_opf);
@@ -8468,7 +8451,6 @@ instruct convI2F_reg(regF dst, iRegI src) %{
instruct convI2F_mem( regF dst, memory mem ) %{
match(Set dst (ConvI2F (LoadI mem)));
ins_cost(DEFAULT_COST + MEMORY_REF_COST);
- size(8);
format %{ "LDF $mem,$dst\n\t"
"FITOS $dst,$dst" %}
opcode(Assembler::ldf_op3, Assembler::fitos_opf);
From f9a6dbd5fd802b319c897b00c3cfda3e1e397d8a Mon Sep 17 00:00:00 2001
From: Christian Thalinger
Date: Fri, 26 Feb 2016 11:13:25 -1000
Subject: [PATCH 026/311] 8150738: [JVMCI]
runtime/CommandLine/TraceExceptionsTest.java fails with:
java.lang.RuntimeException: '' missing
Reviewed-by: coleenp
---
hotspot/src/share/vm/jvmci/jvmciRuntime.cpp | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp
index 716f73c06b1..d5a10f4660f 100644
--- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp
+++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp
@@ -293,13 +293,11 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t
// tracing
if (log_is_enabled(Info, exceptions)) {
ResourceMark rm;
- log_info(exceptions)("Exception <%s> (" INTPTR_FORMAT ") thrown in"
- " compiled method <%s> at PC " INTPTR_FORMAT
- " for thread " INTPTR_FORMAT,
- exception->print_value_string(),
- p2i((address)exception()),
- nm->method()->print_value_string(), p2i(pc),
- p2i(thread));
+ stringStream tempst;
+ tempst.print("compiled method <%s>\n"
+ " at PC" INTPTR_FORMAT " for thread " INTPTR_FORMAT,
+ nm->method()->print_value_string(), p2i(pc), p2i(thread));
+ Exceptions::log_exception(exception, tempst);
}
// for AbortVMOnException flag
NOT_PRODUCT(Exceptions::debug_check_abort(exception));
From babca8523287e182f5683992935c11bce2d754d6 Mon Sep 17 00:00:00 2001
From: Zoltan Majo
Date: Mon, 29 Feb 2016 13:02:10 +0100
Subject: [PATCH 027/311] 8150349: Reduce the execution time of the
hotspot_compiler_3 group
Exclude long-running intrinsic-related tests that check functionality that is not likely to be changed soon.
Reviewed-by: kvn, neliasso
---
hotspot/test/TEST.groups | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups
index f7d983f5a8f..11b95da776b 100644
--- a/hotspot/test/TEST.groups
+++ b/hotspot/test/TEST.groups
@@ -297,7 +297,8 @@ hotspot_compiler_3 = \
compiler/types/ \
compiler/uncommontrap/ \
compiler/unsafe/ \
- -compiler/intrinsics/bmi/verifycode \
+ -compiler/intrinsics/adler32 \
+ -compiler/intrinsics/bmi \
-compiler/intrinsics/mathexact \
-compiler/intrinsics/multiplytolen \
-compiler/intrinsics/sha \
From ea5a3565b8618fd0746082e0d82e423f47fcd7ce Mon Sep 17 00:00:00 2001
From: Claes Redestad
Date: Mon, 29 Feb 2016 15:05:45 +0100
Subject: [PATCH 028/311] 8150720: Cleanup code around PrintOptoStatistics
Reviewed-by: kvn, shade, vlivanov
---
hotspot/src/share/vm/opto/graphKit.cpp | 17 ++++++----
hotspot/src/share/vm/opto/ifnode.cpp | 20 ++++++++----
hotspot/src/share/vm/opto/lcm.cpp | 2 ++
hotspot/src/share/vm/opto/matcher.cpp | 2 ++
hotspot/src/share/vm/opto/node.cpp | 28 ++--------------
hotspot/src/share/vm/opto/parse.hpp | 10 ------
hotspot/src/share/vm/opto/parse1.cpp | 45 ++++++++++++--------------
hotspot/src/share/vm/opto/parse2.cpp | 8 +++--
8 files changed, 56 insertions(+), 76 deletions(-)
diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp
index a47897db8c1..73f7c3e1254 100644
--- a/hotspot/src/share/vm/opto/graphKit.cpp
+++ b/hotspot/src/share/vm/opto/graphKit.cpp
@@ -1179,8 +1179,10 @@ Node* GraphKit::load_array_length(Node* array) {
// Helper function to do a NULL pointer check. Returned value is
// the incoming address with NULL casted away. You are allowed to use the
// not-null value only if you are control dependent on the test.
+#ifndef PRODUCT
extern int explicit_null_checks_inserted,
explicit_null_checks_elided;
+#endif
Node* GraphKit::null_check_common(Node* value, BasicType type,
// optional arguments for variations:
bool assert_null,
@@ -1193,7 +1195,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
value = cast_not_null(value); // Make it appear to be non-null (4962416).
return value;
}
- explicit_null_checks_inserted++;
+ NOT_PRODUCT(explicit_null_checks_inserted++);
// Construct NULL check
Node *chk = NULL;
@@ -1233,7 +1235,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
// See if the type is contained in NULL_PTR.
// If so, then the value is already null.
if (t->higher_equal(TypePtr::NULL_PTR)) {
- explicit_null_checks_elided++;
+ NOT_PRODUCT(explicit_null_checks_elided++);
return value; // Elided null assert quickly!
}
} else {
@@ -1242,7 +1244,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
// type. In other words, "value" was not-null.
if (t->meet(TypePtr::NULL_PTR) != t->remove_speculative()) {
// same as: if (!TypePtr::NULL_PTR->higher_equal(t)) ...
- explicit_null_checks_elided++;
+ NOT_PRODUCT(explicit_null_checks_elided++);
return value; // Elided null check quickly!
}
}
@@ -1282,7 +1284,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
set_control(cfg);
Node *res = cast_not_null(value);
set_control(oldcontrol);
- explicit_null_checks_elided++;
+ NOT_PRODUCT(explicit_null_checks_elided++);
return res;
}
cfg = IfNode::up_one_dom(cfg, /*linear_only=*/ true);
@@ -1326,15 +1328,18 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
IfNode* iff = create_and_map_if(control(), tst, ok_prob, COUNT_UNKNOWN);
Node* null_true = _gvn.transform( new IfFalseNode(iff));
set_control( _gvn.transform( new IfTrueNode(iff)));
- if (null_true == top())
+#ifndef PRODUCT
+ if (null_true == top()) {
explicit_null_checks_elided++;
+ }
+#endif
(*null_control) = null_true;
} else {
BuildCutout unless(this, tst, ok_prob);
// Check for optimizer eliding test at parse time
if (stopped()) {
// Failure not possible; do not bother making uncommon trap.
- explicit_null_checks_elided++;
+ NOT_PRODUCT(explicit_null_checks_elided++);
} else if (assert_null) {
uncommon_trap(reason,
Deoptimization::Action_make_not_entrant,
diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp
index a2cea88273f..9e315739008 100644
--- a/hotspot/src/share/vm/opto/ifnode.cpp
+++ b/hotspot/src/share/vm/opto/ifnode.cpp
@@ -40,7 +40,9 @@
// Optimization - Graph Style
+#ifndef PRODUCT
extern int explicit_null_checks_elided;
+#endif
//=============================================================================
//------------------------------Value------------------------------------------
@@ -1504,24 +1506,28 @@ Node* IfNode::search_identical(int dist) {
Node* prev_dom = this;
int op = Opcode();
// Search up the dominator tree for an If with an identical test
- while( dom->Opcode() != op || // Not same opcode?
+ while (dom->Opcode() != op || // Not same opcode?
dom->in(1) != in(1) || // Not same input 1?
(req() == 3 && dom->in(2) != in(2)) || // Not same input 2?
- prev_dom->in(0) != dom ) { // One path of test does not dominate?
- if( dist < 0 ) return NULL;
+ prev_dom->in(0) != dom) { // One path of test does not dominate?
+ if (dist < 0) return NULL;
dist--;
prev_dom = dom;
- dom = up_one_dom( dom );
- if( !dom ) return NULL;
+ dom = up_one_dom(dom);
+ if (!dom) return NULL;
}
// Check that we did not follow a loop back to ourselves
- if( this == dom )
+ if (this == dom) {
return NULL;
+ }
- if( dist > 2 ) // Add to count of NULL checks elided
+#ifndef PRODUCT
+ if (dist > 2) { // Add to count of NULL checks elided
explicit_null_checks_elided++;
+ }
+#endif
return prev_dom;
}
diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp
index 3edfc5e0ef0..431bba14c7e 100644
--- a/hotspot/src/share/vm/opto/lcm.cpp
+++ b/hotspot/src/share/vm/opto/lcm.cpp
@@ -348,8 +348,10 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo
}
// ---- Found an implicit null check
+#ifndef PRODUCT
extern int implicit_null_checks;
implicit_null_checks++;
+#endif
if( is_decoden ) {
// Check if we need to hoist decodeHeapOop_not_null first.
diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp
index edb69afb43d..1df9f7ca1c0 100644
--- a/hotspot/src/share/vm/opto/matcher.cpp
+++ b/hotspot/src/share/vm/opto/matcher.cpp
@@ -2415,8 +2415,10 @@ void Matcher::collect_null_checks( Node *proj, Node *orig_proj ) {
bool push_it = false;
if( proj->Opcode() == Op_IfTrue ) {
+#ifndef PRODUCT
extern int all_null_checks_found;
all_null_checks_found++;
+#endif
if( b->_test._test == BoolTest::ne ) {
push_it = true;
}
diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp
index 42ca23d212a..78dcacc550b 100644
--- a/hotspot/src/share/vm/opto/node.cpp
+++ b/hotspot/src/share/vm/opto/node.cpp
@@ -576,17 +576,11 @@ void Node::setup_is_top() {
//------------------------------~Node------------------------------------------
// Fancy destructor; eagerly attempt to reclaim Node numberings and storage
-extern int reclaim_idx ;
-extern int reclaim_in ;
-extern int reclaim_node;
void Node::destruct() {
// Eagerly reclaim unique Node numberings
Compile* compile = Compile::current();
if ((uint)_idx+1 == compile->unique()) {
compile->set_unique(compile->unique()-1);
-#ifdef ASSERT
- reclaim_idx++;
-#endif
}
// Clear debug info:
Node_Notes* nn = compile->node_notes_at(_idx);
@@ -604,43 +598,25 @@ void Node::destruct() {
int out_edge_size = _outmax*sizeof(void*);
char *edge_end = ((char*)_in) + edge_size;
char *out_array = (char*)(_out == NO_OUT_ARRAY? NULL: _out);
- char *out_edge_end = out_array + out_edge_size;
int node_size = size_of();
// Free the output edge array
if (out_edge_size > 0) {
-#ifdef ASSERT
- if( out_edge_end == compile->node_arena()->hwm() )
- reclaim_in += out_edge_size; // count reclaimed out edges with in edges
-#endif
compile->node_arena()->Afree(out_array, out_edge_size);
}
// Free the input edge array and the node itself
if( edge_end == (char*)this ) {
-#ifdef ASSERT
- if( edge_end+node_size == compile->node_arena()->hwm() ) {
- reclaim_in += edge_size;
- reclaim_node+= node_size;
- }
-#else
// It was; free the input array and object all in one hit
+#ifndef ASSERT
compile->node_arena()->Afree(_in,edge_size+node_size);
#endif
} else {
-
// Free just the input array
-#ifdef ASSERT
- if( edge_end == compile->node_arena()->hwm() )
- reclaim_in += edge_size;
-#endif
compile->node_arena()->Afree(_in,edge_size);
// Free just the object
-#ifdef ASSERT
- if( ((char*)this) + node_size == compile->node_arena()->hwm() )
- reclaim_node+= node_size;
-#else
+#ifndef ASSERT
compile->node_arena()->Afree(this,node_size);
#endif
}
diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp
index c8a35c9ba53..b26a59f8497 100644
--- a/hotspot/src/share/vm/opto/parse.hpp
+++ b/hotspot/src/share/vm/opto/parse.hpp
@@ -104,13 +104,6 @@ public:
// For temporary (stack-allocated, stateless) ilts:
InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, float site_invoke_ratio, int max_inline_level);
- // InlineTree enum
- enum InlineStyle {
- Inline_do_not_inline = 0, //
- Inline_cha_is_monomorphic = 1, //
- Inline_type_profile_monomorphic = 2 //
- };
-
// See if it is OK to inline.
// The receiver is the inline tree for the caller.
//
@@ -349,9 +342,6 @@ class Parse : public GraphKit {
Block* _block; // block currently getting parsed
ciBytecodeStream _iter; // stream of this method's bytecodes
- int _blocks_merged; // Progress meter: state merges from BB preds
- int _blocks_parsed; // Progress meter: BBs actually parsed
-
const FastLockNode* _synch_lock; // FastLockNode for synchronized method
#ifndef PRODUCT
diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp
index e051b5e1e5c..503f3c7f400 100644
--- a/hotspot/src/share/vm/opto/parse1.cpp
+++ b/hotspot/src/share/vm/opto/parse1.cpp
@@ -45,6 +45,7 @@
// the most. Some of the non-static variables are needed in bytecodeInfo.cpp
// and eventually should be encapsulated in a proper class (gri 8/18/98).
+#ifndef PRODUCT
int nodes_created = 0;
int methods_parsed = 0;
int methods_seen = 0;
@@ -53,42 +54,42 @@ int blocks_seen = 0;
int explicit_null_checks_inserted = 0;
int explicit_null_checks_elided = 0;
-int all_null_checks_found = 0, implicit_null_checks = 0;
-int implicit_null_throws = 0;
+int all_null_checks_found = 0;
+int implicit_null_checks = 0;
-int reclaim_idx = 0;
-int reclaim_in = 0;
-int reclaim_node = 0;
-
-#ifndef PRODUCT
bool Parse::BytecodeParseHistogram::_initialized = false;
uint Parse::BytecodeParseHistogram::_bytecodes_parsed [Bytecodes::number_of_codes];
uint Parse::BytecodeParseHistogram::_nodes_constructed[Bytecodes::number_of_codes];
uint Parse::BytecodeParseHistogram::_nodes_transformed[Bytecodes::number_of_codes];
uint Parse::BytecodeParseHistogram::_new_values [Bytecodes::number_of_codes];
-#endif
//------------------------------print_statistics-------------------------------
-#ifndef PRODUCT
void Parse::print_statistics() {
tty->print_cr("--- Compiler Statistics ---");
tty->print("Methods seen: %d Methods parsed: %d", methods_seen, methods_parsed);
tty->print(" Nodes created: %d", nodes_created);
tty->cr();
- if (methods_seen != methods_parsed)
+ if (methods_seen != methods_parsed) {
tty->print_cr("Reasons for parse failures (NOT cumulative):");
+ }
tty->print_cr("Blocks parsed: %d Blocks seen: %d", blocks_parsed, blocks_seen);
- if( explicit_null_checks_inserted )
- tty->print_cr("%d original NULL checks - %d elided (%2d%%); optimizer leaves %d,", explicit_null_checks_inserted, explicit_null_checks_elided, (100*explicit_null_checks_elided)/explicit_null_checks_inserted, all_null_checks_found);
- if( all_null_checks_found )
+ if (explicit_null_checks_inserted) {
+ tty->print_cr("%d original NULL checks - %d elided (%2d%%); optimizer leaves %d,",
+ explicit_null_checks_inserted, explicit_null_checks_elided,
+ (100*explicit_null_checks_elided)/explicit_null_checks_inserted,
+ all_null_checks_found);
+ }
+ if (all_null_checks_found) {
tty->print_cr("%d made implicit (%2d%%)", implicit_null_checks,
(100*implicit_null_checks)/all_null_checks_found);
- if( implicit_null_throws )
+ }
+ if (SharedRuntime::_implicit_null_throws) {
tty->print_cr("%d implicit null exceptions at runtime",
- implicit_null_throws);
+ SharedRuntime::_implicit_null_throws);
+ }
- if( PrintParseStatistics && BytecodeParseHistogram::initialized() ) {
+ if (PrintParseStatistics && BytecodeParseHistogram::initialized()) {
BytecodeParseHistogram::print();
}
}
@@ -495,7 +496,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
C->dependencies()->assert_evol_method(method());
}
- methods_seen++;
+ NOT_PRODUCT(methods_seen++);
// Do some special top-level things.
if (depth() == 1 && C->is_osr_compilation()) {
@@ -530,8 +531,8 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
}
#endif
- methods_parsed++;
#ifndef PRODUCT
+ methods_parsed++;
// add method size here to guarantee that inlined methods are added too
if (CITime)
_total_bytes_compiled += method()->code_size();
@@ -652,7 +653,7 @@ void Parse::do_all_blocks() {
continue;
}
- blocks_parsed++;
+ NOT_PRODUCT(blocks_parsed++);
progress = true;
if (block->is_loop_head() || block->is_handler() || has_irreducible && !block->is_ready()) {
@@ -712,9 +713,9 @@ void Parse::do_all_blocks() {
}
}
+#ifndef PRODUCT
blocks_seen += block_count();
-#ifndef PRODUCT
// Make sure there are no half-processed blocks remaining.
// Every remaining unprocessed block is dead and may be ignored now.
for (int rpo = 0; rpo < block_count(); rpo++) {
@@ -1446,7 +1447,6 @@ void Parse::do_one_block() {
assert(block()->is_merged(), "must be merged before being parsed");
block()->mark_parsed();
- ++_blocks_parsed;
// Set iterator to start of block.
iter().reset_to_bci(block()->start());
@@ -1596,9 +1596,6 @@ void Parse::merge_common(Parse::Block* target, int pnum) {
return;
}
- // Record that a new block has been merged.
- ++_blocks_merged;
-
// Make a region if we know there are multiple or unpredictable inputs.
// (Also, if this is a plain fall-through, we might see another region,
// which must not be allowed into this block's map.)
diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp
index e03abd4f931..8004ef246e5 100644
--- a/hotspot/src/share/vm/opto/parse2.cpp
+++ b/hotspot/src/share/vm/opto/parse2.cpp
@@ -44,8 +44,10 @@
#include "runtime/deoptimization.hpp"
#include "runtime/sharedRuntime.hpp"
+#ifndef PRODUCT
extern int explicit_null_checks_inserted,
explicit_null_checks_elided;
+#endif
//---------------------------------array_load----------------------------------
void Parse::array_load(BasicType elem_type) {
@@ -997,7 +999,7 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) {
return;
}
- explicit_null_checks_inserted++;
+ NOT_PRODUCT(explicit_null_checks_inserted++);
// Generate real control flow
Node *tst = _gvn.transform( new BoolNode( c, btest ) );
@@ -1013,7 +1015,7 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) {
set_control(iftrue);
if (stopped()) { // Path is dead?
- explicit_null_checks_elided++;
+ NOT_PRODUCT(explicit_null_checks_elided++);
if (C->eliminate_boxing()) {
// Mark the successor block as parsed
branch_block->next_path_num();
@@ -1033,7 +1035,7 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) {
set_control(iffalse);
if (stopped()) { // Path is dead?
- explicit_null_checks_elided++;
+ NOT_PRODUCT(explicit_null_checks_elided++);
if (C->eliminate_boxing()) {
// Mark the successor block as parsed
next_block->next_path_num();
From bb51ea7a06a1c95184940b26e45957731b2ae5f1 Mon Sep 17 00:00:00 2001
From: Vladimir Ivanov
Date: Mon, 29 Feb 2016 23:46:55 +0300
Subject: [PATCH 029/311] 8150543: Mismatched access detection is inaccurate
Reviewed-by: kvn, shade
---
hotspot/src/share/vm/opto/library_call.cpp | 8 +-
hotspot/src/share/vm/opto/memnode.cpp | 18 +-
.../unsafe/UnsafeGetConstantField.java | 3 +
.../unsafe/UnsafeGetStableArrayElement.java | 278 +++++++++++++++++-
4 files changed, 284 insertions(+), 23 deletions(-)
diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp
index de751bc1a97..240321cb231 100644
--- a/hotspot/src/share/vm/opto/library_call.cpp
+++ b/hotspot/src/share/vm/opto/library_call.cpp
@@ -2541,10 +2541,12 @@ bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_stor
if (alias_type->element() != NULL || alias_type->field() != NULL) {
BasicType bt;
if (alias_type->element() != NULL) {
- const Type* element = alias_type->element();
+ // Use address type to get the element type. Alias type doesn't provide
+ // enough information (e.g., doesn't differentiate between byte[] and boolean[]).
+ const Type* element = adr_type->is_aryptr()->elem();
bt = element->isa_narrowoop() ? T_OBJECT : element->array_element_basic_type();
} else {
- bt = alias_type->field()->type()->basic_type();
+ bt = alias_type->field()->layout_type();
}
if (bt == T_ARRAY) {
// accessing an array field with getObject is not a mismatch
@@ -2561,7 +2563,7 @@ bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_stor
// Try to constant fold a load from a constant field
ciField* field = alias_type->field();
if (heap_base_oop != top() &&
- field != NULL && field->is_constant() && field->layout_type() == type) {
+ field != NULL && field->is_constant() && !mismatched) {
// final or stable field
const Type* con_type = Type::make_constant(alias_type->field(), heap_base_oop);
if (con_type != NULL) {
diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp
index 55ca4581485..2d2b40d334e 100644
--- a/hotspot/src/share/vm/opto/memnode.cpp
+++ b/hotspot/src/share/vm/opto/memnode.cpp
@@ -1582,14 +1582,22 @@ LoadNode::load_array_final_field(const TypeKlassPtr *tkls,
return NULL;
}
+#ifdef ASSERT
static bool is_mismatched_access(ciConstant con, BasicType loadbt) {
BasicType conbt = con.basic_type();
- assert(conbt != T_NARROWOOP, "sanity");
- if (loadbt == T_NARROWOOP || loadbt == T_ARRAY) {
- loadbt = T_OBJECT;
+ switch (conbt) {
+ case T_BOOLEAN: conbt = T_BYTE; break;
+ case T_ARRAY: conbt = T_OBJECT; break;
+ }
+ switch (loadbt) {
+ case T_BOOLEAN: loadbt = T_BYTE; break;
+ case T_NARROWOOP: loadbt = T_OBJECT; break;
+ case T_ARRAY: loadbt = T_OBJECT; break;
+ case T_ADDRESS: loadbt = T_OBJECT; break;
}
return (conbt != loadbt);
}
+#endif // ASSERT
// Try to constant-fold a stable array element.
static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicType loadbt) {
@@ -1599,7 +1607,9 @@ static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicTyp
// Decode the results of GraphKit::array_element_address.
ciArray* aobj = ary->const_oop()->as_array();
ciConstant con = aobj->element_value_by_offset(off);
- if (con.basic_type() != T_ILLEGAL && !is_mismatched_access(con, loadbt) && !con.is_null_or_zero()) {
+ if (con.basic_type() != T_ILLEGAL && !con.is_null_or_zero()) {
+ assert(!is_mismatched_access(con, loadbt),
+ "conbt=%s; loadbt=%s", type2name(con.basic_type()), type2name(loadbt));
const Type* con_type = Type::make_from_constant(con);
if (con_type != NULL) {
if (con_type->isa_aryptr()) {
diff --git a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java
index 8c144143d62..c1d6b057e14 100644
--- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java
+++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java
@@ -27,6 +27,9 @@
* @test
* @summary tests on constant folding of unsafe get operations
* @library /testlibrary /test/lib
+ *
+ * @requires vm.flavor != "client"
+ *
* @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions
* -Xbatch -XX:-TieredCompilation
* -XX:+FoldStableValues
diff --git a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java
index afdb1a6e7a3..0cf5f44dc85 100644
--- a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java
+++ b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java
@@ -25,17 +25,15 @@
/*
* @test
- * @summary tests on constant folding of unsafe get operations
+ * @summary tests on constant folding of unsafe get operations from stable arrays
* @library /testlibrary /test/lib
*
+ * @requires vm.flavor != "client"
+ *
* @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions
* -Xbatch -XX:-TieredCompilation
* -XX:+FoldStableValues
- * UnsafeGetStableArrayElement
- *
- * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions
- * -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1
- * -XX:+FoldStableValues
+ * -XX:CompileCommand=dontinline,*Test::test*
* UnsafeGetStableArrayElement
*/
import jdk.internal.misc.Unsafe;
@@ -46,23 +44,271 @@ import static jdk.internal.misc.Unsafe.*;
import static jdk.test.lib.Asserts.*;
public class UnsafeGetStableArrayElement {
- @Stable static final byte[] STABLE_BYTE_ARRAY = new byte[] { 0, 1, -128, 127};
+ @Stable static final boolean[] STABLE_BOOLEAN_ARRAY = new boolean[16];
+ @Stable static final byte[] STABLE_BYTE_ARRAY = new byte[16];
+ @Stable static final short[] STABLE_SHORT_ARRAY = new short[8];
+ @Stable static final char[] STABLE_CHAR_ARRAY = new char[8];
+ @Stable static final int[] STABLE_INT_ARRAY = new int[4];
+ @Stable static final long[] STABLE_LONG_ARRAY = new long[2];
+ @Stable static final float[] STABLE_FLOAT_ARRAY = new float[4];
+ @Stable static final double[] STABLE_DOUBLE_ARRAY = new double[2];
+ @Stable static final Object[] STABLE_OBJECT_ARRAY = new Object[4];
+ static {
+ Setter.reset();
+ }
static final Unsafe U = Unsafe.getUnsafe();
- static int testChar() {
- return U.getChar(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET + 0 * ARRAY_CHAR_INDEX_SCALE) +
- U.getChar(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET + 1 * ARRAY_CHAR_INDEX_SCALE);
- }
+ static class Setter {
+ private static void setZ(boolean defaultVal) { STABLE_BOOLEAN_ARRAY[0] = defaultVal ? false : true; }
+ private static void setB(boolean defaultVal) { STABLE_BYTE_ARRAY[0] = defaultVal ? 0 : Byte.MAX_VALUE; }
+ private static void setS(boolean defaultVal) { STABLE_SHORT_ARRAY[0] = defaultVal ? 0 : Short.MAX_VALUE; }
+ private static void setC(boolean defaultVal) { STABLE_CHAR_ARRAY[0] = defaultVal ? 0 : Character.MAX_VALUE; }
+ private static void setI(boolean defaultVal) { STABLE_INT_ARRAY[0] = defaultVal ? 0 : Integer.MAX_VALUE; }
+ private static void setJ(boolean defaultVal) { STABLE_LONG_ARRAY[0] = defaultVal ? 0 : Long.MAX_VALUE; }
+ private static void setF(boolean defaultVal) { STABLE_FLOAT_ARRAY[0] = defaultVal ? 0 : Float.MAX_VALUE; }
+ private static void setD(boolean defaultVal) { STABLE_DOUBLE_ARRAY[0] = defaultVal ? 0 : Double.MAX_VALUE; }
+ private static void setL(boolean defaultVal) { STABLE_OBJECT_ARRAY[0] = defaultVal ? null : new Object(); }
- static void run(Callable c) throws Exception {
- Object first = c.call();
- for (int i = 0; i < 20_000; i++) {
- assertEQ(first, c.call());
+ static void reset() {
+ setZ(false);
+ setB(false);
+ setS(false);
+ setC(false);
+ setI(false);
+ setJ(false);
+ setF(false);
+ setD(false);
+ setL(false);
}
}
+ static class Test {
+ static void changeZ() { Setter.setZ(true); }
+ static void changeB() { Setter.setB(true); }
+ static void changeS() { Setter.setS(true); }
+ static void changeC() { Setter.setC(true); }
+ static void changeI() { Setter.setI(true); }
+ static void changeJ() { Setter.setJ(true); }
+ static void changeF() { Setter.setF(true); }
+ static void changeD() { Setter.setD(true); }
+ static void changeL() { Setter.setL(true); }
+
+ static boolean testZ_Z() { return U.getBoolean(STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static byte testZ_B() { return U.getByte( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static short testZ_S() { return U.getShort( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static char testZ_C() { return U.getChar( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static int testZ_I() { return U.getInt( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static long testZ_J() { return U.getLong( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static float testZ_F() { return U.getFloat( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+ static double testZ_D() { return U.getDouble( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); }
+
+ static boolean testB_Z() { return U.getBoolean(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static byte testB_B() { return U.getByte( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static short testB_S() { return U.getShort( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static char testB_C() { return U.getChar( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static int testB_I() { return U.getInt( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static long testB_J() { return U.getLong( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static float testB_F() { return U.getFloat( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+ static double testB_D() { return U.getDouble( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); }
+
+ static boolean testS_Z() { return U.getBoolean(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static byte testS_B() { return U.getByte( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static short testS_S() { return U.getShort( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static char testS_C() { return U.getChar( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static int testS_I() { return U.getInt( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static long testS_J() { return U.getLong( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static float testS_F() { return U.getFloat( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+ static double testS_D() { return U.getDouble( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); }
+
+ static boolean testC_Z() { return U.getBoolean(STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static byte testC_B() { return U.getByte( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static short testC_S() { return U.getShort( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static char testC_C() { return U.getChar( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static int testC_I() { return U.getInt( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static long testC_J() { return U.getLong( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static float testC_F() { return U.getFloat( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+ static double testC_D() { return U.getDouble( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); }
+
+ static boolean testI_Z() { return U.getBoolean(STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static byte testI_B() { return U.getByte( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static short testI_S() { return U.getShort( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static char testI_C() { return U.getChar( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static int testI_I() { return U.getInt( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static long testI_J() { return U.getLong( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static float testI_F() { return U.getFloat( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+ static double testI_D() { return U.getDouble( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); }
+
+ static boolean testJ_Z() { return U.getBoolean(STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static byte testJ_B() { return U.getByte( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static short testJ_S() { return U.getShort( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static char testJ_C() { return U.getChar( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static int testJ_I() { return U.getInt( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static long testJ_J() { return U.getLong( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static float testJ_F() { return U.getFloat( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+ static double testJ_D() { return U.getDouble( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); }
+
+ static boolean testF_Z() { return U.getBoolean(STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static byte testF_B() { return U.getByte( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static short testF_S() { return U.getShort( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static char testF_C() { return U.getChar( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static int testF_I() { return U.getInt( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static long testF_J() { return U.getLong( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static float testF_F() { return U.getFloat( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+ static double testF_D() { return U.getDouble( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); }
+
+ static boolean testD_Z() { return U.getBoolean(STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static byte testD_B() { return U.getByte( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static short testD_S() { return U.getShort( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static char testD_C() { return U.getChar( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static int testD_I() { return U.getInt( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static long testD_J() { return U.getLong( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static float testD_F() { return U.getFloat( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+ static double testD_D() { return U.getDouble( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); }
+
+ static Object testL_L() { return U.getObject( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static boolean testL_Z() { return U.getBoolean(STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static byte testL_B() { return U.getByte( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static short testL_S() { return U.getShort( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static char testL_C() { return U.getChar( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static int testL_I() { return U.getInt( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static long testL_J() { return U.getLong( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static float testL_F() { return U.getFloat( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+ static double testL_D() { return U.getDouble( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); }
+
+ static short testS_U() { return U.getShortUnaligned(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET + 1); }
+ static char testC_U() { return U.getCharUnaligned( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET + 1); }
+ static int testI_U() { return U.getIntUnaligned( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET + 1); }
+ static long testJ_U() { return U.getLongUnaligned( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET + 1); }
+ }
+
+ static void run(Callable> c, Runnable sameResultAction, Runnable changeResultAction) throws Exception {
+ Object first = c.call();
+
+ // Trigger compilation.
+ for (int i = 0; i < 20_000; i++) {
+ // Don't compare results here, since most of Test::testL_* results vary across iterations (due to GC).
+ c.call();
+ }
+
+ if (sameResultAction != null) {
+ sameResultAction.run();
+ assertEQ(first, c.call());
+ }
+
+ if (changeResultAction != null) {
+ changeResultAction.run();
+ assertNE(first, c.call());
+ assertEQ(c.call(), c.call());
+ }
+ }
+
+ static void testMatched(Callable> c, Runnable setDefaultAction) throws Exception {
+ run(c, setDefaultAction, null);
+ Setter.reset();
+ }
+
+ static void testMismatched(Callable> c, Runnable setDefaultAction) throws Exception {
+ run(c, null, setDefaultAction);
+ Setter.reset();
+ }
+
public static void main(String[] args) throws Exception {
- run(UnsafeGetStableArrayElement::testChar);
+ // boolean[], aligned accesses
+ testMatched( Test::testZ_Z, Test::changeZ);
+ testMismatched(Test::testZ_B, Test::changeZ);
+ testMismatched(Test::testZ_S, Test::changeZ);
+ testMismatched(Test::testZ_C, Test::changeZ);
+ testMismatched(Test::testZ_I, Test::changeZ);
+ testMismatched(Test::testZ_J, Test::changeZ);
+ testMismatched(Test::testZ_F, Test::changeZ);
+ testMismatched(Test::testZ_D, Test::changeZ);
+
+ // byte[], aligned accesses
+ testMismatched(Test::testB_Z, Test::changeB);
+ testMatched( Test::testB_B, Test::changeB);
+ testMismatched(Test::testB_S, Test::changeB);
+ testMismatched(Test::testB_C, Test::changeB);
+ testMismatched(Test::testB_I, Test::changeB);
+ testMismatched(Test::testB_J, Test::changeB);
+ testMismatched(Test::testB_F, Test::changeB);
+ testMismatched(Test::testB_D, Test::changeB);
+
+ // short[], aligned accesses
+ testMismatched(Test::testS_Z, Test::changeS);
+ testMismatched(Test::testS_B, Test::changeS);
+ testMatched( Test::testS_S, Test::changeS);
+ testMismatched(Test::testS_C, Test::changeS);
+ testMismatched(Test::testS_I, Test::changeS);
+ testMismatched(Test::testS_J, Test::changeS);
+ testMismatched(Test::testS_F, Test::changeS);
+ testMismatched(Test::testS_D, Test::changeS);
+
+ // char[], aligned accesses
+ testMismatched(Test::testC_Z, Test::changeC);
+ testMismatched(Test::testC_B, Test::changeC);
+ testMismatched(Test::testC_S, Test::changeC);
+ testMatched( Test::testC_C, Test::changeC);
+ testMismatched(Test::testC_I, Test::changeC);
+ testMismatched(Test::testC_J, Test::changeC);
+ testMismatched(Test::testC_F, Test::changeC);
+ testMismatched(Test::testC_D, Test::changeC);
+
+ // int[], aligned accesses
+ testMismatched(Test::testI_Z, Test::changeI);
+ testMismatched(Test::testI_B, Test::changeI);
+ testMismatched(Test::testI_S, Test::changeI);
+ testMismatched(Test::testI_C, Test::changeI);
+ testMatched( Test::testI_I, Test::changeI);
+ testMismatched(Test::testI_J, Test::changeI);
+ testMismatched(Test::testI_F, Test::changeI);
+ testMismatched(Test::testI_D, Test::changeI);
+
+ // long[], aligned accesses
+ testMismatched(Test::testJ_Z, Test::changeJ);
+ testMismatched(Test::testJ_B, Test::changeJ);
+ testMismatched(Test::testJ_S, Test::changeJ);
+ testMismatched(Test::testJ_C, Test::changeJ);
+ testMismatched(Test::testJ_I, Test::changeJ);
+ testMatched( Test::testJ_J, Test::changeJ);
+ testMismatched(Test::testJ_F, Test::changeJ);
+ testMismatched(Test::testJ_D, Test::changeJ);
+
+ // float[], aligned accesses
+ testMismatched(Test::testF_Z, Test::changeF);
+ testMismatched(Test::testF_B, Test::changeF);
+ testMismatched(Test::testF_S, Test::changeF);
+ testMismatched(Test::testF_C, Test::changeF);
+ testMismatched(Test::testF_I, Test::changeF);
+ testMismatched(Test::testF_J, Test::changeF);
+ testMatched( Test::testF_F, Test::changeF);
+ testMismatched(Test::testF_D, Test::changeF);
+
+ // double[], aligned accesses
+ testMismatched(Test::testD_Z, Test::changeD);
+ testMismatched(Test::testD_B, Test::changeD);
+ testMismatched(Test::testD_S, Test::changeD);
+ testMismatched(Test::testD_C, Test::changeD);
+ testMismatched(Test::testD_I, Test::changeD);
+ testMismatched(Test::testD_J, Test::changeD);
+ testMismatched(Test::testD_F, Test::changeD);
+ testMatched( Test::testD_D, Test::changeD);
+
+ // Object[], aligned accesses
+ testMismatched(Test::testL_Z, Test::changeL);
+ testMismatched(Test::testL_B, Test::changeL);
+ testMismatched(Test::testL_S, Test::changeL);
+ testMismatched(Test::testL_C, Test::changeL);
+ testMismatched(Test::testL_I, Test::changeL);
+ testMismatched(Test::testL_J, Test::changeL);
+ testMismatched(Test::testL_F, Test::changeL);
+ testMismatched(Test::testL_D, Test::changeL);
+ testMatched( Test::testL_L, Test::changeL);
+
+ // Unaligned accesses
+ testMismatched(Test::testS_U, Test::changeS);
+ testMismatched(Test::testC_U, Test::changeC);
+ testMismatched(Test::testI_U, Test::changeI);
+ testMismatched(Test::testJ_U, Test::changeJ);
}
}
From f73f7433d015641095e8a10b5f2c6ea15153214e Mon Sep 17 00:00:00 2001
From: Hui Shi
Date: Wed, 24 Feb 2016 04:45:50 -0800
Subject: [PATCH 030/311] 8149733: AArch64: refactor array_equals/string_equals
Combine similar code for string_equals/char_array_equals/byte_array_equals into same implemenation
Reviewed-by: aph, shade
---
hotspot/src/cpu/aarch64/vm/aarch64.ad | 25 +-
.../cpu/aarch64/vm/macroAssembler_aarch64.cpp | 297 ++++++------------
.../cpu/aarch64/vm/macroAssembler_aarch64.hpp | 12 +-
3 files changed, 118 insertions(+), 216 deletions(-)
diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad
index 18ba1e44cf3..e980a2332f3 100644
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad
@@ -14783,19 +14783,19 @@ instruct string_indexof_con(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
%}
instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt,
- iRegI_R0 result, iRegP_R10 tmp, rFlagsReg cr)
+ iRegI_R0 result, rFlagsReg cr)
%{
predicate(!CompactStrings);
match(Set result (StrEquals (Binary str1 str2) cnt));
- effect(KILL tmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr);
+ effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr);
- format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %}
+ format %{ "String Equals $str1,$str2,$cnt -> $result" %}
ins_encode %{
// Count is in 8-bit bytes; non-Compact chars are 16 bits.
__ asrw($cnt$$Register, $cnt$$Register, 1);
- __ string_equals($str1$$Register, $str2$$Register,
- $cnt$$Register, $result$$Register,
- $tmp$$Register);
+ __ arrays_equals($str1$$Register, $str2$$Register,
+ $result$$Register, $cnt$$Register,
+ 2, /*is_string*/true);
%}
ins_pipe(pipe_class_memory);
%}
@@ -14809,9 +14809,10 @@ instruct array_equalsB(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result,
format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %}
ins_encode %{
- __ byte_arrays_equals($ary1$$Register, $ary2$$Register,
- $result$$Register, $tmp$$Register);
- %}
+ __ arrays_equals($ary1$$Register, $ary2$$Register,
+ $result$$Register, $tmp$$Register,
+ 1, /*is_string*/false);
+ %}
ins_pipe(pipe_class_memory);
%}
@@ -14824,12 +14825,14 @@ instruct array_equalsC(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result,
format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %}
ins_encode %{
- __ char_arrays_equals($ary1$$Register, $ary2$$Register,
- $result$$Register, $tmp$$Register);
+ __ arrays_equals($ary1$$Register, $ary2$$Register,
+ $result$$Register, $tmp$$Register,
+ 2, /*is_string*/false);
%}
ins_pipe(pipe_class_memory);
%}
+
// encode char[] to byte[] in ISO_8859_1
instruct encode_iso_array(iRegP_R2 src, iRegP_R1 dst, iRegI_R3 len,
vRegD_V0 Vtmp1, vRegD_V1 Vtmp2,
diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
index 8c7f9465622..942518b116b 100644
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
@@ -4481,225 +4481,126 @@ void MacroAssembler::string_compare(Register str1, Register str2,
BLOCK_COMMENT("} string_compare");
}
+// Compare Strings or char/byte arrays.
-void MacroAssembler::string_equals(Register str1, Register str2,
- Register cnt, Register result,
- Register tmp1) {
- Label SAME_CHARS, DONE, SHORT_LOOP, SHORT_STRING,
- NEXT_WORD;
+// is_string is true iff this is a string comparison.
- const Register tmp2 = rscratch1;
- assert_different_registers(str1, str2, cnt, result, tmp1, tmp2, rscratch2);
+// For Strings we're passed the address of the first characters in a1
+// and a2 and the length in cnt1.
- BLOCK_COMMENT("string_equals {");
+// For byte and char arrays we're passed the arrays themselves and we
+// have to extract length fields and do null checks here.
- // Start by assuming that the strings are not equal.
- mov(result, zr);
+// elem_size is the element size in bytes: either 1 or 2.
- // A very short string
- cmpw(cnt, 4);
- br(Assembler::LT, SHORT_STRING);
+// There are two implementations. For arrays >= 8 bytes, all
+// comparisons (including the final one, which may overlap) are
+// performed 8 bytes at a time. For arrays < 8 bytes, we compare a
+// halfword, then a short, and then a byte.
- // Check if the strings start at the same location.
- cmp(str1, str2);
- br(Assembler::EQ, SAME_CHARS);
+void MacroAssembler::arrays_equals(Register a1, Register a2,
+ Register result, Register cnt1,
+ int elem_size, bool is_string)
+{
+ Label SAME, DONE, SHORT, NEXT_WORD, ONE;
+ Register tmp1 = rscratch1;
+ Register tmp2 = rscratch2;
+ Register cnt2 = tmp2; // cnt2 only used in array length compare
+ int elem_per_word = wordSize/elem_size;
+ int log_elem_size = exact_log2(elem_size);
+ int length_offset = arrayOopDesc::length_offset_in_bytes();
+ int base_offset
+ = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE);
- // Compare longwords
- {
- subw(cnt, cnt, 4); // The last longword is a special case
+ assert(elem_size == 1 || elem_size == 2, "must be char or byte");
+ assert_different_registers(a1, a2, result, cnt1, rscratch1, rscratch2);
- // Move both string pointers to the last longword of their
- // strings, negate the remaining count, and convert it to bytes.
- lea(str1, Address(str1, cnt, Address::uxtw(1)));
- lea(str2, Address(str2, cnt, Address::uxtw(1)));
- sub(cnt, zr, cnt, LSL, 1);
+ BLOCK_COMMENT(is_string ? "string_equals {" : "array_equals {");
- // Loop, loading longwords and comparing them into rscratch2.
- bind(NEXT_WORD);
- ldr(tmp1, Address(str1, cnt));
- ldr(tmp2, Address(str2, cnt));
- adds(cnt, cnt, wordSize);
- eor(rscratch2, tmp1, tmp2);
- cbnz(rscratch2, DONE);
- br(Assembler::LT, NEXT_WORD);
+ mov(result, false);
- // Last longword. In the case where length == 4 we compare the
- // same longword twice, but that's still faster than another
- // conditional branch.
+ if (!is_string) {
+ // if (a==a2)
+ // return true;
+ eor(rscratch1, a1, a2);
+ cbz(rscratch1, SAME);
+ // if (a==null || a2==null)
+ // return false;
+ cbz(a1, DONE);
+ cbz(a2, DONE);
+ // if (a1.length != a2.length)
+ // return false;
+ ldrw(cnt1, Address(a1, length_offset));
+ ldrw(cnt2, Address(a2, length_offset));
+ eorw(tmp1, cnt1, cnt2);
+ cbnzw(tmp1, DONE);
- ldr(tmp1, Address(str1));
- ldr(tmp2, Address(str2));
- eor(rscratch2, tmp1, tmp2);
- cbz(rscratch2, SAME_CHARS);
- b(DONE);
+ lea(a1, Address(a1, base_offset));
+ lea(a2, Address(a2, base_offset));
}
- bind(SHORT_STRING);
- // Is the length zero?
- cbz(cnt, SAME_CHARS);
-
- bind(SHORT_LOOP);
- load_unsigned_short(tmp1, Address(post(str1, 2)));
- load_unsigned_short(tmp2, Address(post(str2, 2)));
- subw(tmp1, tmp1, tmp2);
+ // Check for short strings, i.e. smaller than wordSize.
+ subs(cnt1, cnt1, elem_per_word);
+ br(Assembler::LT, SHORT);
+ // Main 8 byte comparison loop.
+ bind(NEXT_WORD); {
+ ldr(tmp1, Address(post(a1, wordSize)));
+ ldr(tmp2, Address(post(a2, wordSize)));
+ subs(cnt1, cnt1, elem_per_word);
+ eor(tmp1, tmp1, tmp2);
+ cbnz(tmp1, DONE);
+ } br(GT, NEXT_WORD);
+ // Last longword. In the case where length == 4 we compare the
+ // same longword twice, but that's still faster than another
+ // conditional branch.
+ // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when
+ // length == 4.
+ if (log_elem_size > 0)
+ lsl(cnt1, cnt1, log_elem_size);
+ ldr(tmp1, Address(a1, cnt1));
+ ldr(tmp2, Address(a2, cnt1));
+ eor(tmp1, tmp1, tmp2);
cbnz(tmp1, DONE);
- sub(cnt, cnt, 1);
- cbnz(cnt, SHORT_LOOP);
+ b(SAME);
- // Strings are equal.
- bind(SAME_CHARS);
+ bind(SHORT);
+ Label TAIL03, TAIL01;
+
+ tbz(cnt1, 2 - log_elem_size, TAIL03); // 0-7 bytes left.
+ {
+ ldrw(tmp1, Address(post(a1, 4)));
+ ldrw(tmp2, Address(post(a2, 4)));
+ eorw(tmp1, tmp1, tmp2);
+ cbnzw(tmp1, DONE);
+ }
+ bind(TAIL03);
+ tbz(cnt1, 1 - log_elem_size, TAIL01); // 0-3 bytes left.
+ {
+ ldrh(tmp1, Address(post(a1, 2)));
+ ldrh(tmp2, Address(post(a2, 2)));
+ eorw(tmp1, tmp1, tmp2);
+ cbnzw(tmp1, DONE);
+ }
+ bind(TAIL01);
+ if (elem_size == 1) { // Only needed when comparing byte arrays.
+ tbz(cnt1, 0, SAME); // 0-1 bytes left.
+ {
+ ldrb(tmp1, a1);
+ ldrb(tmp2, a2);
+ eorw(tmp1, tmp1, tmp2);
+ cbnzw(tmp1, DONE);
+ }
+ }
+ // Arrays are equal.
+ bind(SAME);
mov(result, true);
- // That's it
+ // That's it.
bind(DONE);
-
- BLOCK_COMMENT("} string_equals");
+ BLOCK_COMMENT(is_string ? "} string_equals" : "} array_equals");
}
-void MacroAssembler::byte_arrays_equals(Register ary1, Register ary2,
- Register result, Register tmp1)
-{
- Register cnt1 = rscratch1;
- Register cnt2 = rscratch2;
- Register tmp2 = rscratch2;
-
- Label SAME, DIFFER, NEXT, TAIL07, TAIL03, TAIL01;
-
- int length_offset = arrayOopDesc::length_offset_in_bytes();
- int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE);
-
- BLOCK_COMMENT("byte_arrays_equals {");
-
- // different until proven equal
- mov(result, false);
-
- // same array?
- cmp(ary1, ary2);
- br(Assembler::EQ, SAME);
-
- // ne if either null
- cbz(ary1, DIFFER);
- cbz(ary2, DIFFER);
-
- // lengths ne?
- ldrw(cnt1, Address(ary1, length_offset));
- ldrw(cnt2, Address(ary2, length_offset));
- cmp(cnt1, cnt2);
- br(Assembler::NE, DIFFER);
-
- lea(ary1, Address(ary1, base_offset));
- lea(ary2, Address(ary2, base_offset));
-
- subs(cnt1, cnt1, 8);
- br(LT, TAIL07);
-
- BIND(NEXT);
- ldr(tmp1, Address(post(ary1, 8)));
- ldr(tmp2, Address(post(ary2, 8)));
- subs(cnt1, cnt1, 8);
- eor(tmp1, tmp1, tmp2);
- cbnz(tmp1, DIFFER);
- br(GE, NEXT);
-
- BIND(TAIL07); // 0-7 bytes left, cnt1 = #bytes left - 4
- tst(cnt1, 0b100);
- br(EQ, TAIL03);
- ldrw(tmp1, Address(post(ary1, 4)));
- ldrw(tmp2, Address(post(ary2, 4)));
- cmp(tmp1, tmp2);
- br(NE, DIFFER);
-
- BIND(TAIL03); // 0-3 bytes left, cnt1 = #bytes left - 4
- tst(cnt1, 0b10);
- br(EQ, TAIL01);
- ldrh(tmp1, Address(post(ary1, 2)));
- ldrh(tmp2, Address(post(ary2, 2)));
- cmp(tmp1, tmp2);
- br(NE, DIFFER);
- BIND(TAIL01); // 0-1 byte left
- tst(cnt1, 0b01);
- br(EQ, SAME);
- ldrb(tmp1, ary1);
- ldrb(tmp2, ary2);
- cmp(tmp1, tmp2);
- br(NE, DIFFER);
-
- BIND(SAME);
- mov(result, true);
- BIND(DIFFER); // result already set
-
- BLOCK_COMMENT("} byte_arrays_equals");
-}
-
-// Compare char[] arrays aligned to 4 bytes
-void MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
- Register result, Register tmp1)
-{
- Register cnt1 = rscratch1;
- Register cnt2 = rscratch2;
- Register tmp2 = rscratch2;
-
- Label SAME, DIFFER, NEXT, TAIL03, TAIL01;
-
- int length_offset = arrayOopDesc::length_offset_in_bytes();
- int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
-
- BLOCK_COMMENT("char_arrays_equals {");
-
- // different until proven equal
- mov(result, false);
-
- // same array?
- cmp(ary1, ary2);
- br(Assembler::EQ, SAME);
-
- // ne if either null
- cbz(ary1, DIFFER);
- cbz(ary2, DIFFER);
-
- // lengths ne?
- ldrw(cnt1, Address(ary1, length_offset));
- ldrw(cnt2, Address(ary2, length_offset));
- cmp(cnt1, cnt2);
- br(Assembler::NE, DIFFER);
-
- lea(ary1, Address(ary1, base_offset));
- lea(ary2, Address(ary2, base_offset));
-
- subs(cnt1, cnt1, 4);
- br(LT, TAIL03);
-
- BIND(NEXT);
- ldr(tmp1, Address(post(ary1, 8)));
- ldr(tmp2, Address(post(ary2, 8)));
- subs(cnt1, cnt1, 4);
- eor(tmp1, tmp1, tmp2);
- cbnz(tmp1, DIFFER);
- br(GE, NEXT);
-
- BIND(TAIL03); // 0-3 chars left, cnt1 = #chars left - 4
- tst(cnt1, 0b10);
- br(EQ, TAIL01);
- ldrw(tmp1, Address(post(ary1, 4)));
- ldrw(tmp2, Address(post(ary2, 4)));
- cmp(tmp1, tmp2);
- br(NE, DIFFER);
- BIND(TAIL01); // 0-1 chars left
- tst(cnt1, 0b01);
- br(EQ, SAME);
- ldrh(tmp1, ary1);
- ldrh(tmp2, ary2);
- cmp(tmp1, tmp2);
- br(NE, DIFFER);
-
- BIND(SAME);
- mov(result, true);
- BIND(DIFFER); // result already set
-
- BLOCK_COMMENT("} char_arrays_equals");
-}
-
// encode char[] to byte[] in ISO_8859_1
void MacroAssembler::encode_iso_array(Register src, Register dst,
Register len, Register result,
diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
index d22c581bc41..e042b5055eb 100644
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
@@ -1186,13 +1186,11 @@ public:
void string_compare(Register str1, Register str2,
Register cnt1, Register cnt2, Register result,
Register tmp1);
- void string_equals(Register str1, Register str2,
- Register cnt, Register result,
- Register tmp1);
- void char_arrays_equals(Register ary1, Register ary2,
- Register result, Register tmp1);
- void byte_arrays_equals(Register ary1, Register ary2,
- Register result, Register tmp1);
+
+ void arrays_equals(Register a1, Register a2,
+ Register result, Register cnt1,
+ int elem_size, bool is_string);
+
void encode_iso_array(Register src, Register dst,
Register len, Register result,
FloatRegister Vtmp1, FloatRegister Vtmp2,
From a30c46aa74610773458947247315459e487ec9f3 Mon Sep 17 00:00:00 2001
From: Felix Yang
Date: Wed, 17 Feb 2016 20:19:24 +0800
Subject: [PATCH 031/311] 8150038: aarch64: make use of CBZ and CBNZ when
comparing narrow pointer with zero
Aarch64: c2 make use of CBZ and CBNZ when comparing narrow pointer with zero
Reviewed-by: aph
---
hotspot/src/cpu/aarch64/vm/aarch64.ad | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad
index e980a2332f3..8483c709564 100644
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad
@@ -14191,6 +14191,25 @@ instruct cmpP_imm0_branch(cmpOp cmp, iRegP op1, immP0 op2, label labl, rFlagsReg
ins_pipe(pipe_cmp_branch);
%}
+instruct cmpN_imm0_branch(cmpOp cmp, iRegN op1, immN0 op2, label labl, rFlagsReg cr) %{
+ match(If cmp (CmpN op1 op2));
+ predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
+ || n->in(1)->as_Bool()->_test._test == BoolTest::eq);
+ effect(USE labl);
+
+ ins_cost(BRANCH_COST);
+ format %{ "cbw$cmp $op1, $labl" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
+ if (cond == Assembler::EQ)
+ __ cbzw($op1$$Register, *L);
+ else
+ __ cbnzw($op1$$Register, *L);
+ %}
+ ins_pipe(pipe_cmp_branch);
+%}
+
instruct cmpP_narrowOop_imm0_branch(cmpOp cmp, iRegN oop, immP0 zero, label labl, rFlagsReg cr) %{
match(If cmp (CmpP (DecodeN oop) zero));
predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne
From 410f75949f5dd91000130189111d86ec62adfb68 Mon Sep 17 00:00:00 2001
From: Vladimir Ivanov
Date: Wed, 17 Feb 2016 18:49:38 +0300
Subject: [PATCH 032/311] 8148518: Unsafe.getCharUnaligned() loads aren't
folded in case of -XX:-UseUnalignedAccesses
Reviewed-by: kvn, shade
---
.../java.base/share/classes/jdk/internal/misc/Unsafe.java | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
index f130d383a84..e48e4ef9d6a 100644
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java
@@ -1159,7 +1159,12 @@ public final class Unsafe {
/** @see #getLongUnaligned(Object, long) */
@HotSpotIntrinsicCandidate
public final char getCharUnaligned(Object o, long offset) {
- return (char)getShortUnaligned(o, offset);
+ if ((offset & 1) == 0) {
+ return getChar(o, offset);
+ } else {
+ return (char)makeShort(getByte(o, offset),
+ getByte(o, offset + 1));
+ }
}
/** @see #getLongUnaligned(Object, long, boolean) */
From 92f9c27eec3b37339e9f1b04d920e155a3fb90fe Mon Sep 17 00:00:00 2001
From: Rachel Protacio
Date: Wed, 17 Feb 2016 14:03:18 -0500
Subject: [PATCH 033/311] 8148630: Convert TraceStartupTime to Unified Logging
The former -XX:+TraceStartupTime flag has been converted to the UL option -Xlog:startuptime=info
Reviewed-by: coleenp, dholmes
---
.../share/vm/interpreter/cppInterpreter.cpp | 3 +-
.../vm/interpreter/templateInterpreter.cpp | 3 +-
.../share/vm/interpreter/templateTable.cpp | 5 +-
hotspot/src/share/vm/logging/logTag.hpp | 3 +-
.../src/share/vm/memory/metaspaceShared.cpp | 144 +++++++++---------
hotspot/src/share/vm/memory/universe.cpp | 5 +-
hotspot/src/share/vm/prims/methodHandles.cpp | 5 +-
hotspot/src/share/vm/runtime/globals.hpp | 3 -
hotspot/src/share/vm/runtime/logTimer.hpp | 43 ++++++
hotspot/src/share/vm/runtime/stubRoutines.cpp | 8 +-
hotspot/src/share/vm/runtime/thread.cpp | 12 +-
hotspot/src/share/vm/runtime/timer.cpp | 35 +++--
hotspot/src/share/vm/runtime/timer.hpp | 12 +-
.../test/runtime/logging/StartupTimeTest.java | 68 +++++++++
14 files changed, 242 insertions(+), 107 deletions(-)
create mode 100644 hotspot/src/share/vm/runtime/logTimer.hpp
create mode 100644 hotspot/test/runtime/logging/StartupTimeTest.java
diff --git a/hotspot/src/share/vm/interpreter/cppInterpreter.cpp b/hotspot/src/share/vm/interpreter/cppInterpreter.cpp
index cbcfccbd759..2dcef77ef53 100644
--- a/hotspot/src/share/vm/interpreter/cppInterpreter.cpp
+++ b/hotspot/src/share/vm/interpreter/cppInterpreter.cpp
@@ -27,6 +27,7 @@
#include "interpreter/cppInterpreterGenerator.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterRuntime.hpp"
+#include "runtime/logTimer.hpp"
#ifdef CC_INTERP
@@ -42,7 +43,7 @@ void CppInterpreter::initialize() {
// generate interpreter
{ ResourceMark rm;
- TraceTime timer("Interpreter generation", TraceStartupTime);
+ TraceStartupTime timer("Interpreter generation");
int code_size = InterpreterCodeSize;
NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space
_code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL,
diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp
index c68f6858da6..8c2363be0d8 100644
--- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp
+++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp
@@ -31,6 +31,7 @@
#include "interpreter/templateInterpreterGenerator.hpp"
#include "interpreter/templateTable.hpp"
#include "memory/resourceArea.hpp"
+#include "runtime/logTimer.hpp"
#ifndef CC_INTERP
@@ -48,7 +49,7 @@ void TemplateInterpreter::initialize() {
// generate interpreter
{ ResourceMark rm;
- TraceTime timer("Interpreter generation", TraceStartupTime);
+ TraceStartupTime timer("Interpreter generation");
int code_size = InterpreterCodeSize;
NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space
#if INCLUDE_JVMTI
diff --git a/hotspot/src/share/vm/interpreter/templateTable.cpp b/hotspot/src/share/vm/interpreter/templateTable.cpp
index ddd7fc6470c..c71ebd28263 100644
--- a/hotspot/src/share/vm/interpreter/templateTable.cpp
+++ b/hotspot/src/share/vm/interpreter/templateTable.cpp
@@ -26,8 +26,7 @@
#include "gc/shared/collectedHeap.hpp"
#include "interpreter/interp_masm.hpp"
#include "interpreter/templateTable.hpp"
-#include "runtime/timer.hpp"
-
+#include "runtime/logTimer.hpp"
#ifdef CC_INTERP
@@ -246,7 +245,7 @@ void TemplateTable::initialize() {
if (_is_initialized) return;
// Initialize table
- TraceTime timer("TemplateTable initialization", TraceStartupTime);
+ TraceStartupTime timer("TemplateTable initialization");
_bs = Universe::heap()->barrier_set();
diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp
index d4ff40bd0dd..b4b72f20cfe 100644
--- a/hotspot/src/share/vm/logging/logTag.hpp
+++ b/hotspot/src/share/vm/logging/logTag.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -73,6 +73,7 @@
LOG_TAG(scavenge) \
LOG_TAG(scrub) \
LOG_TAG(start) \
+ LOG_TAG(startuptime) \
LOG_TAG(state) \
LOG_TAG(stats) \
LOG_TAG(stringdedup) \
diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp
index d71f9292511..3f10488bf7f 100644
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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
@@ -40,6 +40,7 @@
#include "memory/metaspaceShared.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
+#include "runtime/logTimer.hpp"
#include "runtime/os.hpp"
#include "runtime/signature.hpp"
#include "runtime/vmThread.hpp"
@@ -771,88 +772,89 @@ void MetaspaceShared::prepare_for_dumping() {
// Preload classes from a list, populate the shared spaces and dump to a
// file.
void MetaspaceShared::preload_and_dump(TRAPS) {
- TraceTime timer("Dump Shared Spaces", TraceStartupTime);
- ResourceMark rm;
- char class_list_path_str[JVM_MAXPATHLEN];
+ { TraceStartupTime timer("Dump Shared Spaces");
+ ResourceMark rm;
+ char class_list_path_str[JVM_MAXPATHLEN];
- tty->print_cr("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT,
- MetaspaceShared::shared_rs()->size(),
- p2i(MetaspaceShared::shared_rs()->base()));
+ tty->print_cr("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT,
+ MetaspaceShared::shared_rs()->size(),
+ p2i(MetaspaceShared::shared_rs()->base()));
- // Preload classes to be shared.
- // Should use some os:: method rather than fopen() here. aB.
- const char* class_list_path;
- if (SharedClassListFile == NULL) {
- // Construct the path to the class list (in jre/lib)
- // Walk up two directories from the location of the VM and
- // optionally tack on "lib" (depending on platform)
- os::jvm_path(class_list_path_str, sizeof(class_list_path_str));
- for (int i = 0; i < 3; i++) {
- char *end = strrchr(class_list_path_str, *os::file_separator());
- if (end != NULL) *end = '\0';
- }
- int class_list_path_len = (int)strlen(class_list_path_str);
- if (class_list_path_len >= 3) {
- if (strcmp(class_list_path_str + class_list_path_len - 3, "lib") != 0) {
- if (class_list_path_len < JVM_MAXPATHLEN - 4) {
- jio_snprintf(class_list_path_str + class_list_path_len,
- sizeof(class_list_path_str) - class_list_path_len,
- "%slib", os::file_separator());
- class_list_path_len += 4;
+ // Preload classes to be shared.
+ // Should use some os:: method rather than fopen() here. aB.
+ const char* class_list_path;
+ if (SharedClassListFile == NULL) {
+ // Construct the path to the class list (in jre/lib)
+ // Walk up two directories from the location of the VM and
+ // optionally tack on "lib" (depending on platform)
+ os::jvm_path(class_list_path_str, sizeof(class_list_path_str));
+ for (int i = 0; i < 3; i++) {
+ char *end = strrchr(class_list_path_str, *os::file_separator());
+ if (end != NULL) *end = '\0';
+ }
+ int class_list_path_len = (int)strlen(class_list_path_str);
+ if (class_list_path_len >= 3) {
+ if (strcmp(class_list_path_str + class_list_path_len - 3, "lib") != 0) {
+ if (class_list_path_len < JVM_MAXPATHLEN - 4) {
+ jio_snprintf(class_list_path_str + class_list_path_len,
+ sizeof(class_list_path_str) - class_list_path_len,
+ "%slib", os::file_separator());
+ class_list_path_len += 4;
+ }
}
}
+ if (class_list_path_len < JVM_MAXPATHLEN - 10) {
+ jio_snprintf(class_list_path_str + class_list_path_len,
+ sizeof(class_list_path_str) - class_list_path_len,
+ "%sclasslist", os::file_separator());
+ }
+ class_list_path = class_list_path_str;
+ } else {
+ class_list_path = SharedClassListFile;
}
- if (class_list_path_len < JVM_MAXPATHLEN - 10) {
- jio_snprintf(class_list_path_str + class_list_path_len,
- sizeof(class_list_path_str) - class_list_path_len,
- "%sclasslist", os::file_separator());
- }
- class_list_path = class_list_path_str;
- } else {
- class_list_path = SharedClassListFile;
- }
- int class_count = 0;
- GrowableArray* class_promote_order = new GrowableArray();
+ int class_count = 0;
+ GrowableArray* class_promote_order = new GrowableArray();
- // sun.io.Converters
- static const char obj_array_sig[] = "[[Ljava/lang/Object;";
- SymbolTable::new_permanent_symbol(obj_array_sig, THREAD);
+ // sun.io.Converters
+ static const char obj_array_sig[] = "[[Ljava/lang/Object;";
+ SymbolTable::new_permanent_symbol(obj_array_sig, THREAD);
- // java.util.HashMap
- static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;";
- SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD);
+ // java.util.HashMap
+ static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;";
+ SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD);
- // Need to allocate the op here:
- // op.misc_data_space_alloc() will be called during preload_and_dump().
- ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
- VM_PopulateDumpSharedSpace op(loader_data, class_promote_order);
+ // Need to allocate the op here:
+ // op.misc_data_space_alloc() will be called during preload_and_dump().
+ ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
+ VM_PopulateDumpSharedSpace op(loader_data, class_promote_order);
- tty->print_cr("Loading classes to share ...");
- _has_error_classes = false;
- class_count += preload_and_dump(class_list_path, class_promote_order,
- THREAD);
- if (ExtraSharedClassListFile) {
- class_count += preload_and_dump(ExtraSharedClassListFile, class_promote_order,
+ tty->print_cr("Loading classes to share ...");
+ _has_error_classes = false;
+ class_count += preload_and_dump(class_list_path, class_promote_order,
THREAD);
+ if (ExtraSharedClassListFile) {
+ class_count += preload_and_dump(ExtraSharedClassListFile, class_promote_order,
+ THREAD);
+ }
+ tty->print_cr("Loading classes to share: done.");
+
+ if (PrintSharedSpaces) {
+ tty->print_cr("Shared spaces: preloaded %d classes", class_count);
+ }
+
+ // Rewrite and link classes
+ tty->print_cr("Rewriting and linking classes ...");
+
+ // Link any classes which got missed. This would happen if we have loaded classes that
+ // were not explicitly specified in the classlist. E.g., if an interface implemented by class K
+ // fails verification, all other interfaces that were not specified in the classlist but
+ // are implemented by K are not verified.
+ link_and_cleanup_shared_classes(CATCH);
+ tty->print_cr("Rewriting and linking classes: done");
+
+ VMThread::execute(&op);
}
- tty->print_cr("Loading classes to share: done.");
-
- if (PrintSharedSpaces) {
- tty->print_cr("Shared spaces: preloaded %d classes", class_count);
- }
-
- // Rewrite and link classes
- tty->print_cr("Rewriting and linking classes ...");
-
- // Link any classes which got missed. This would happen if we have loaded classes that
- // were not explicitly specified in the classlist. E.g., if an interface implemented by class K
- // fails verification, all other interfaces that were not specified in the classlist but
- // are implemented by K are not verified.
- link_and_cleanup_shared_classes(CATCH);
- tty->print_cr("Rewriting and linking classes: done");
-
- VMThread::execute(&op);
// Since various initialization steps have been undone by this process,
// it is not reasonable to continue running a java process.
exit(0);
diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp
index ac36a988d97..3a7945768e8 100644
--- a/hotspot/src/share/vm/memory/universe.cpp
+++ b/hotspot/src/share/vm/memory/universe.cpp
@@ -64,6 +64,7 @@
#include "runtime/init.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
+#include "runtime/logTimer.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/thread.inline.hpp"
@@ -626,7 +627,9 @@ jint universe_init() {
guarantee(sizeof(oop) >= sizeof(HeapWord), "HeapWord larger than oop?");
guarantee(sizeof(oop) % sizeof(HeapWord) == 0,
"oop size is not not a multiple of HeapWord size");
- TraceTime timer("Genesis", TraceStartupTime);
+
+ TraceStartupTime timer("Genesis");
+
JavaClasses::compute_hard_coded_offsets();
jint status = Universe::initialize_heap();
diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp
index 00c33b644d3..24370f4c165 100644
--- a/hotspot/src/share/vm/prims/methodHandles.cpp
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, 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
@@ -40,6 +40,7 @@
#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/javaCalls.hpp"
+#include "runtime/logTimer.hpp"
#include "runtime/reflection.hpp"
#include "runtime/signature.hpp"
#include "runtime/stubRoutines.hpp"
@@ -76,7 +77,7 @@ bool MethodHandles::generate_adapters() {
assert(_adapter_code == NULL, "generate only once");
ResourceMark rm;
- TraceTime timer("MethodHandles adapters generation", TraceStartupTime);
+ TraceStartupTime timer("MethodHandles adapters generation");
_adapter_code = MethodHandlesAdapterBlob::create(adapter_code_size);
if (_adapter_code == NULL) {
return false;
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
index a15ea7db325..86cd7328dd2 100644
--- a/hotspot/src/share/vm/runtime/globals.hpp
+++ b/hotspot/src/share/vm/runtime/globals.hpp
@@ -1482,9 +1482,6 @@ public:
develop(bool, TraceCompiledIC, false, \
"Trace changes of compiled IC") \
\
- develop(bool, TraceStartupTime, false, \
- "Trace setup time") \
- \
develop(bool, TraceProtectionDomainVerification, false, \
"Trace protection domain verification") \
\
diff --git a/hotspot/src/share/vm/runtime/logTimer.hpp b/hotspot/src/share/vm/runtime/logTimer.hpp
new file mode 100644
index 00000000000..81bbd085eb3
--- /dev/null
+++ b/hotspot/src/share/vm/runtime/logTimer.hpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_LOG_TIMER_HPP
+#define SHARE_VM_RUNTIME_LOG_TIMER_HPP
+
+#include "logging/log.hpp"
+#include "runtime/timer.hpp"
+
+// TraceStartupTime is used for tracing the execution time of a block with logging
+// Usage:
+// { TraceStartupTime t("block time")
+// some_code();
+// }
+//
+
+class TraceStartupTime : public TraceTime {
+ public:
+ TraceStartupTime(const char* s) : TraceTime(s, log_is_enabled(Info, startuptime), LogTag::_startuptime) {}
+};
+
+#endif // SHARE_VM_RUNTIME_LOG_TIMER_HPP
diff --git a/hotspot/src/share/vm/runtime/stubRoutines.cpp b/hotspot/src/share/vm/runtime/stubRoutines.cpp
index 0f2c5b65e17..71080e5b76c 100644
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -28,9 +28,9 @@
#include "memory/resourceArea.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/interfaceSupport.hpp"
+#include "runtime/logTimer.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
-#include "runtime/timer.hpp"
#include "utilities/copy.hpp"
#ifdef COMPILER2
#include "opto/runtime.hpp"
@@ -183,7 +183,7 @@ extern void StubGenerator_generate(CodeBuffer* code, bool all); // only interfac
void StubRoutines::initialize1() {
if (_code1 == NULL) {
ResourceMark rm;
- TraceTime timer("StubRoutines generation 1", TraceStartupTime);
+ TraceStartupTime timer("StubRoutines generation 1");
_code1 = BufferBlob::create("StubRoutines (1)", code_size1);
if (_code1 == NULL) {
vm_exit_out_of_memory(code_size1, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (1)");
@@ -276,7 +276,7 @@ static void test_safefetchN() {
void StubRoutines::initialize2() {
if (_code2 == NULL) {
ResourceMark rm;
- TraceTime timer("StubRoutines generation 2", TraceStartupTime);
+ TraceStartupTime timer("StubRoutines generation 2");
_code2 = BufferBlob::create("StubRoutines (2)", code_size2);
if (_code2 == NULL) {
vm_exit_out_of_memory(code_size2, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (2)");
diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp
index b0fca00705a..5b9faf084d3 100644
--- a/hotspot/src/share/vm/runtime/thread.cpp
+++ b/hotspot/src/share/vm/runtime/thread.cpp
@@ -67,6 +67,7 @@
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/jniPeriodicChecker.hpp"
+#include "runtime/logTimer.hpp"
#include "runtime/memprofiler.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/objectMonitor.hpp"
@@ -3341,7 +3342,7 @@ void Threads::threads_do(ThreadClosure* tc) {
}
void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) {
- TraceTime timer("Initialize java.lang classes", TraceStartupTime);
+ TraceStartupTime timer("Initialize java.lang classes");
if (EagerXrunInit && Arguments::init_libraries_at_startup()) {
create_vm_init_libraries();
@@ -3388,6 +3389,8 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) {
}
void Threads::initialize_jsr292_core_classes(TRAPS) {
+ TraceStartupTime timer("Initialize java.lang.invoke classes");
+
initialize_class(vmSymbols::java_lang_invoke_MethodHandle(), CHECK);
initialize_class(vmSymbols::java_lang_invoke_MemberName(), CHECK);
initialize_class(vmSymbols::java_lang_invoke_MethodHandleNatives(), CHECK);
@@ -3457,7 +3460,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
HOTSPOT_VM_INIT_BEGIN();
// Timing (must come after argument parsing)
- TraceTime timer("Create VM", TraceStartupTime);
+ TraceStartupTime timer("Create VM");
// Initialize the os module after parsing the args
jint os_init_2_result = os::init_2();
@@ -3542,8 +3545,9 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
JvmtiExport::transition_pending_onload_raw_monitors();
// Create the VMThread
- { TraceTime timer("Start VMThread", TraceStartupTime);
- VMThread::create();
+ { TraceStartupTime timer("Start VMThread");
+
+ VMThread::create();
Thread* vmthread = VMThread::vm_thread();
if (!os::create_thread(vmthread, os::vm_thread)) {
diff --git a/hotspot/src/share/vm/runtime/timer.cpp b/hotspot/src/share/vm/runtime/timer.cpp
index ec4ec0fa662..dddf328b302 100644
--- a/hotspot/src/share/vm/runtime/timer.cpp
+++ b/hotspot/src/share/vm/runtime/timer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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,6 +23,7 @@
*/
#include "precompiled.hpp"
+#include "logging/log.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/timer.hpp"
#include "utilities/ostream.hpp"
@@ -114,14 +115,15 @@ jlong TimeStamp::ticks_since_update() const {
}
TraceTime::TraceTime(const char* title,
- bool doit) {
+ bool doit,
+ LogTagType tag) {
_active = doit;
_verbose = true;
+ _tag = tag;
+ _title = title;
if (_active) {
_accum = NULL;
- tty->print("[%s", title);
- tty->flush();
_t.start();
}
}
@@ -129,14 +131,14 @@ TraceTime::TraceTime(const char* title,
TraceTime::TraceTime(const char* title,
elapsedTimer* accumulator,
bool doit,
- bool verbose) {
- _active = doit;
- _verbose = verbose;
+ bool verbose,
+ LogTagType tag) {
+ _active = doit;
+ _verbose = verbose;
+ _tag = tag;
+ _title = title;
+
if (_active) {
- if (_verbose) {
- tty->print("[%s", title);
- tty->flush();
- }
_accum = accumulator;
_t.start();
}
@@ -147,8 +149,15 @@ TraceTime::~TraceTime() {
_t.stop();
if (_accum!=NULL) _accum->add(_t);
if (_verbose) {
- tty->print_cr(", %3.7f secs]", _t.seconds());
- tty->flush();
+ switch (_tag) {
+ case LogTag::_startuptime :
+ log_info(startuptime)("%s, %3.7f secs", _title, _t.seconds());
+ break;
+ case LogTag::__NO_TAG :
+ default :
+ tty->print_cr("[%s, %3.7f secs]", _title, _t.seconds());
+ tty->flush();
+ }
}
}
}
diff --git a/hotspot/src/share/vm/runtime/timer.hpp b/hotspot/src/share/vm/runtime/timer.hpp
index bd003eb40e6..c14e2522917 100644
--- a/hotspot/src/share/vm/runtime/timer.hpp
+++ b/hotspot/src/share/vm/runtime/timer.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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 @@
#ifndef SHARE_VM_RUNTIME_TIMER_HPP
#define SHARE_VM_RUNTIME_TIMER_HPP
+#include "logging/logTag.hpp"
#include "utilities/globalDefinitions.hpp"
// Timers for simple measurement.
@@ -85,14 +86,19 @@ class TraceTime: public StackObj {
bool _verbose; // report every timing
elapsedTimer _t; // timer
elapsedTimer* _accum; // accumulator
+ const char* _title; // name of timer
+ LogTagType _tag; // stream to print to
+
public:
// Constructors
TraceTime(const char* title,
- bool doit = true);
+ bool doit = true,
+ LogTagType tag = LogTag::__NO_TAG);
TraceTime(const char* title,
elapsedTimer* accumulator,
bool doit = true,
- bool verbose = false);
+ bool verbose = false,
+ LogTagType tag = LogTag::__NO_TAG);
~TraceTime();
// Accessors
diff --git a/hotspot/test/runtime/logging/StartupTimeTest.java b/hotspot/test/runtime/logging/StartupTimeTest.java
new file mode 100644
index 00000000000..1c8c0a0f87f
--- /dev/null
+++ b/hotspot/test/runtime/logging/StartupTimeTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 2016, 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.
+ */
+
+/*
+ * @test
+ * @bug 8148630
+ * @summary -Xlog:startuptime should produce logging from the source code
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * java.management
+ * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools
+ * @run driver StartupTimeTest
+ */
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+
+public class StartupTimeTest {
+ static void analyzeOutputOn(ProcessBuilder pb) throws Exception {
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldMatch("(Genesis, [0-9]+.[0-9]+ secs)");
+ output.shouldMatch("(Start VMThread, [0-9]+.[0-9]+ secs)");
+ output.shouldMatch("(Create VM, [0-9]+.[0-9]+ secs)");
+ output.shouldHaveExitValue(0);
+ }
+
+ static void analyzeOutputOff(ProcessBuilder pb) throws Exception {
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldNotContain("[startuptime]");
+ output.shouldHaveExitValue(0);
+ }
+
+ public static void main(String[] args) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:startuptime",
+ InnerClass.class.getName());
+ analyzeOutputOn(pb);
+
+ pb = ProcessTools.createJavaProcessBuilder("-Xlog:startuptime=off",
+ InnerClass.class.getName());
+ analyzeOutputOff(pb);
+ }
+
+ public static class InnerClass {
+ public static void main(String[] args) throws Exception {
+ System.out.println("Testing startuptime.");
+ }
+ }
+}
From 7c684d52497b1ad72ecedfda0a6bfd14ce2bd1d8 Mon Sep 17 00:00:00 2001
From: Kim Barrett
Date: Wed, 17 Feb 2016 16:00:27 -0500
Subject: [PATCH 034/311] 8149793:
DirtyCardQueueSet::apply_closure_to_completed_buffer_helper isn't helpful
Merge helper into sole caller.
Reviewed-by: brutisso, jwilhelm, tschatzl
---
.../vm/gc/g1/concurrentG1RefineThread.cpp | 5 ++-
hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp | 45 ++++++++-----------
hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp | 13 ++----
3 files changed, 27 insertions(+), 36 deletions(-)
diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp
index dc1b5ea1352..df9de0ee337 100644
--- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp
@@ -154,7 +154,10 @@ void ConcurrentG1RefineThread::run_service() {
if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
_next->activate();
}
- } while (dcqs.apply_closure_to_completed_buffer(_refine_closure, _worker_id + _worker_id_offset, cg1r()->green_zone()));
+ } while (dcqs.apply_closure_to_completed_buffer(_refine_closure,
+ _worker_id + _worker_id_offset,
+ cg1r()->green_zone(),
+ false /* during_pause */));
// We can exit the loop above while being active if there was a yield request.
if (is_active()) {
diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp
index 155faa0be5a..4c33fb9b211 100644
--- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp
+++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -228,37 +228,30 @@ BufferNode* DirtyCardQueueSet::get_completed_buffer(int stop_at) {
return nd;
}
-bool DirtyCardQueueSet::apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
- uint worker_i,
- BufferNode* nd) {
- if (nd != NULL) {
- void **buf = BufferNode::make_buffer_from_node(nd);
- size_t index = nd->index();
- bool b =
- DirtyCardQueue::apply_closure_to_buffer(cl, buf,
- index, _sz,
- true, worker_i);
- if (b) {
- deallocate_buffer(buf);
- return true; // In normal case, go on to next buffer.
- } else {
- enqueue_complete_buffer(buf, index);
- return false;
- }
- } else {
- return false;
- }
-}
-
bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
uint worker_i,
int stop_at,
bool during_pause) {
assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause");
BufferNode* nd = get_completed_buffer(stop_at);
- bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd);
- if (res) Atomic::inc(&_processed_buffers_rs_thread);
- return res;
+ if (nd == NULL) {
+ return false;
+ } else {
+ void** buf = BufferNode::make_buffer_from_node(nd);
+ size_t index = nd->index();
+ if (DirtyCardQueue::apply_closure_to_buffer(cl,
+ buf, index, _sz,
+ true, worker_i)) {
+ // Done with fully processed buffer.
+ deallocate_buffer(buf);
+ Atomic::inc(&_processed_buffers_rs_thread);
+ return true;
+ } else {
+ // Return partially processed buffer to the queue.
+ enqueue_complete_buffer(buf, index);
+ return false;
+ }
+ }
}
void DirtyCardQueueSet::apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) {
diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp
index 9fa3c3da069..17c92bb8ecf 100644
--- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp
+++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -133,14 +133,9 @@ public:
// partially completed buffer (with its processed elements set to NULL)
// is returned to the completed buffer set, and this call returns false.
bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl,
- uint worker_i = 0,
- int stop_at = 0,
- bool during_pause = false);
-
- // Helper routine for the above.
- bool apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl,
- uint worker_i,
- BufferNode* nd);
+ uint worker_i,
+ int stop_at,
+ bool during_pause);
BufferNode* get_completed_buffer(int stop_at);
From 3a99569b6f6c3b712ef4b74a561f00861bba4111 Mon Sep 17 00:00:00 2001
From: Severin Gehwolf
Date: Wed, 17 Feb 2016 17:03:31 -0500
Subject: [PATCH 035/311] 8143245: Zero build requires disabled warnings
Reviewed-by: dholmes, coleenp
---
hotspot/make/linux/makefiles/zeroshark.make | 8 +-------
hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp | 2 +-
hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp | 4 ++--
.../src/os_cpu/linux_zero/vm/os_linux_zero.cpp | 17 ++++++++++++++---
.../os_cpu/linux_zero/vm/thread_linux_zero.hpp | 3 ++-
5 files changed, 20 insertions(+), 14 deletions(-)
diff --git a/hotspot/make/linux/makefiles/zeroshark.make b/hotspot/make/linux/makefiles/zeroshark.make
index 240946fee3a..4f9a70c98fa 100644
--- a/hotspot/make/linux/makefiles/zeroshark.make
+++ b/hotspot/make/linux/makefiles/zeroshark.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
# Copyright 2007, 2008 Red Hat, Inc.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
@@ -29,12 +29,6 @@
ifeq ($(USE_CLANG), true)
WARNING_FLAGS += -Wno-undef
endif
-# Suppress some warning flags that are normally turned on for hotspot,
-# because some of the zero code has not been updated accordingly.
-WARNING_FLAGS += -Wno-return-type \
- -Wno-format-nonliteral -Wno-format-security \
- -Wno-maybe-uninitialized
-
# The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized
OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT)
diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
index 387733de06d..4dc68335b6a 100644
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
@@ -773,7 +773,7 @@ InterpreterFrame *InterpreterFrame::build(int size, TRAPS) {
}
BasicType CppInterpreter::result_type_of(Method* method) {
- BasicType t;
+ BasicType t = T_ILLEGAL; // silence compiler warnings
switch (method->result_index()) {
case 0 : t = T_BOOLEAN; break;
case 1 : t = T_CHAR; break;
diff --git a/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp b/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp
index 8fb45375262..2e2dc3cab60 100644
--- a/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp
+++ b/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -62,7 +62,7 @@ void InterpreterRuntime::SignatureHandlerGeneratorBase::pass_object() {
}
void InterpreterRuntime::SignatureHandlerGeneratorBase::push(BasicType type) {
- ffi_type *ftype;
+ ffi_type *ftype = NULL;
switch (type) {
case T_VOID:
ftype = &ffi_type_void;
diff --git a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
index f57f89ad02f..b1e93a82dc8 100644
--- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
+++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -65,6 +65,7 @@ address os::current_stack_pointer() {
frame os::get_sender_for_C_frame(frame* fr) {
ShouldNotCallThis();
+ return frame(NULL, NULL); // silence compile warning.
}
frame os::current_frame() {
@@ -102,6 +103,7 @@ void os::initialize_thread(Thread * thr){
address os::Linux::ucontext_get_pc(const ucontext_t* uc) {
ShouldNotCallThis();
+ return NULL; // silence compile warnings
}
void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) {
@@ -112,10 +114,12 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid,
intptr_t** ret_sp,
intptr_t** ret_fp) {
ShouldNotCallThis();
+ return NULL; // silence compile warnings
}
frame os::fetch_frame_from_context(const void* ucVoid) {
ShouldNotCallThis();
+ return frame(NULL, NULL); // silence compile warnings
}
extern "C" JNIEXPORT int
@@ -262,11 +266,16 @@ JVM_handle_linux_signal(int sig,
}
#endif // !PRODUCT
- const char *fmt = "caught unhandled signal %d";
char buf[64];
- sprintf(buf, fmt, sig);
+ sprintf(buf, "caught unhandled signal %d", sig);
+
+// Silence -Wformat-security warning for fatal()
+PRAGMA_DIAG_PUSH
+PRAGMA_FORMAT_NONLITERAL_IGNORED
fatal(buf);
+PRAGMA_DIAG_POP
+ return true; // silence compiler warnings
}
void os::Linux::init_thread_fpu_state(void) {
@@ -275,6 +284,7 @@ void os::Linux::init_thread_fpu_state(void) {
int os::Linux::get_fpu_control_word() {
ShouldNotCallThis();
+ return -1; // silence compile warnings
}
void os::Linux::set_fpu_control_word(int fpu) {
@@ -419,6 +429,7 @@ void os::print_register_info(outputStream *st, const void *context) {
extern "C" {
int SpinPause() {
+ return -1; // silence compile warnings
}
diff --git a/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp b/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp
index 39f77f858d0..b9c73dc48c1 100644
--- a/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp
+++ b/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright 2007, 2008, 2009, 2010 Red Hat, Inc.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -110,6 +110,7 @@
void* ucontext,
bool isInJava) {
ShouldNotCallThis();
+ return false; // silence compile warning
}
// These routines are only used on cpu architectures that
From a5c5a3b6096b9248db46d028128b973e51ccdce7 Mon Sep 17 00:00:00 2001
From: Volker Simonis
Date: Wed, 17 Feb 2016 22:17:49 -0500
Subject: [PATCH 036/311] 8150079: MSVC prior to VS 2013 doesn't know the
'va_copy' macro
Reviewed-by: dholmes
---
hotspot/src/share/vm/prims/jni.cpp | 6 ------
hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp | 2 ++
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp
index d4808682944..419963ef412 100644
--- a/hotspot/src/share/vm/prims/jni.cpp
+++ b/hotspot/src/share/vm/prims/jni.cpp
@@ -930,13 +930,7 @@ class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher {
_arguments->push_oop(Handle((oop *)l, false)); }
inline void set_ap(va_list rap) {
-#ifdef va_copy
va_copy(_ap, rap);
-#elif defined (__va_copy)
- __va_copy(_ap, rap);
-#else
- _ap = rap;
-#endif
}
public:
diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp
index f594bafbc2f..038f348a434 100644
--- a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp
@@ -174,6 +174,8 @@ const jlong max_jlong = CONST64(0x7fffffffffffffff);
#if _MSC_VER < 1800
// Visual Studio 2013 introduced strtoull(); before, one has to use _strtoui64() instead.
#define strtoull _strtoui64
+// Visual Studio prior to 2013 had no va_copy, but could safely copy va_list by assignement
+#define va_copy(dest, src) dest = src
// Fixes some wrong warnings about 'this' : used in base member initializer list
#pragma warning( disable : 4355 )
#endif
From af854404be490ce59847fc0e502ec24366279806 Mon Sep 17 00:00:00 2001
From: Alexander Kulyakhtin
Date: Thu, 18 Feb 2016 14:56:53 +0300
Subject: [PATCH 037/311] 8150067: Quarantine
serviceability/tmtools/jstat/GcCapacityTest.java
Quarantine a falsely failing test until the test issue is fixed
Reviewed-by: sla
---
hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java
index 3b63e0210d1..6ec4db9829b 100644
--- a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java
+++ b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java
@@ -27,6 +27,7 @@ import utils.*;
* @test
* @summary Test checks the consistency of the output
* displayed with jstat -gccapacity.
+ * @ignore 8149778
* @library /test/lib/share/classes
* @library ../share
* @requires vm.opt.ExplicitGCInvokesConcurrent != true
From 3cf4e3909cb5592b657c7f271274dae75889ff65 Mon Sep 17 00:00:00 2001
From: Rachel Protacio
Date: Thu, 18 Feb 2016 17:10:48 -0500
Subject: [PATCH 038/311] 8149383: Convert TraceBiasedLocking to Unified
Logging
The former -XX:+TraceBiasedLocking flag has been converted to the UL option -Xlog:biasedlocking=info and =trace, with the old option being aliased.
Reviewed-by: dholmes, dcubed
---
hotspot/src/share/vm/logging/logTag.hpp | 1 +
hotspot/src/share/vm/runtime/arguments.cpp | 1 +
.../src/share/vm/runtime/biasedLocking.cpp | 121 ++++++++++--------
hotspot/src/share/vm/runtime/globals.hpp | 3 -
hotspot/src/share/vm/runtime/thread.cpp | 9 +-
.../runtime/logging/BiasedLockingTest.java | 78 +++++++++++
6 files changed, 153 insertions(+), 60 deletions(-)
create mode 100644 hotspot/test/runtime/logging/BiasedLockingTest.java
diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp
index b4b72f20cfe..60e39f710f5 100644
--- a/hotspot/src/share/vm/logging/logTag.hpp
+++ b/hotspot/src/share/vm/logging/logTag.hpp
@@ -34,6 +34,7 @@
LOG_TAG(alloc) \
LOG_TAG(age) \
LOG_TAG(barrier) \
+ LOG_TAG(biasedlocking) \
LOG_TAG(bot) \
LOG_TAG(census) \
LOG_TAG(classhisto) \
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index fc891394d4a..f43a7a1372f 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -409,6 +409,7 @@ static AliasedLoggingFlag const aliased_logging_flags[] = {
{ "TraceClassResolution", LogLevel::Info, true, LogTag::_classresolve },
{ "TraceExceptions", LogLevel::Info, true, LogTag::_exceptions },
{ "TraceMonitorInflation", LogLevel::Debug, true, LogTag::_monitorinflation },
+ { "TraceBiasedLocking", LogLevel::Info, true, LogTag::_biasedlocking },
{ NULL, LogLevel::Off, false, LogTag::__NO_TAG }
};
diff --git a/hotspot/src/share/vm/runtime/biasedLocking.cpp b/hotspot/src/share/vm/runtime/biasedLocking.cpp
index c02d232139b..1be0d111e56 100644
--- a/hotspot/src/share/vm/runtime/biasedLocking.cpp
+++ b/hotspot/src/share/vm/runtime/biasedLocking.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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,6 +23,8 @@
*/
#include "precompiled.hpp"
+#include "logging/log.hpp"
+#include "memory/resourceArea.hpp"
#include "oops/klass.inline.hpp"
#include "oops/markOop.hpp"
#include "oops/oop.inline.hpp"
@@ -60,9 +62,7 @@ class VM_EnableBiasedLocking: public VM_Operation {
// Indicate that future instances should enable it as well
_biased_locking_enabled = true;
- if (TraceBiasedLocking) {
- tty->print_cr("Biased locking enabled");
- }
+ log_info(biasedlocking)("Biased locking enabled");
}
bool allow_nested_vm_operations() const { return false; }
@@ -144,14 +144,14 @@ static GrowableArray* get_or_compute_monitor_info(JavaThread* thre
return info;
}
-
static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) {
markOop mark = obj->mark();
if (!mark->has_bias_pattern()) {
- if (TraceBiasedLocking) {
+ if (log_is_enabled(Info, biasedlocking)) {
ResourceMark rm;
- tty->print_cr(" (Skipping revocation of object of type %s because it's no longer biased)",
- obj->klass()->external_name());
+ log_info(biasedlocking)(" (Skipping revocation of object of type %s "
+ "because it's no longer biased)",
+ obj->klass()->external_name());
}
return BiasedLocking::NOT_BIASED;
}
@@ -160,10 +160,29 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_
markOop biased_prototype = markOopDesc::biased_locking_prototype()->set_age(age);
markOop unbiased_prototype = markOopDesc::prototype()->set_age(age);
- if (TraceBiasedLocking && (Verbose || !is_bulk)) {
+ // Log at "info" level if not bulk, else "trace" level
+ if (!is_bulk) {
ResourceMark rm;
- tty->print_cr("Revoking bias of object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT " , allow rebias %d , requesting thread " INTPTR_FORMAT,
- p2i((void *)obj), (intptr_t) mark, obj->klass()->external_name(), (intptr_t) obj->klass()->prototype_header(), (allow_rebias ? 1 : 0), (intptr_t) requesting_thread);
+ log_info(biasedlocking)("Revoking bias of object " INTPTR_FORMAT " , mark "
+ INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT
+ " , allow rebias %d , requesting thread " INTPTR_FORMAT,
+ p2i((void *)obj),
+ (intptr_t) mark,
+ obj->klass()->external_name(),
+ (intptr_t) obj->klass()->prototype_header(),
+ (allow_rebias ? 1 : 0),
+ (intptr_t) requesting_thread);
+ } else {
+ ResourceMark rm;
+ log_trace(biasedlocking)("Revoking bias of object " INTPTR_FORMAT " , mark "
+ INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT
+ " , allow rebias %d , requesting thread " INTPTR_FORMAT,
+ p2i((void *)obj),
+ (intptr_t) mark,
+ obj->klass()->external_name(),
+ (intptr_t) obj->klass()->prototype_header(),
+ (allow_rebias ? 1 : 0),
+ (intptr_t) requesting_thread);
}
JavaThread* biased_thread = mark->biased_locker();
@@ -174,8 +193,11 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_
if (!allow_rebias) {
obj->set_mark(unbiased_prototype);
}
- if (TraceBiasedLocking && (Verbose || !is_bulk)) {
- tty->print_cr(" Revoked bias of anonymously-biased object");
+ // Log at "info" level if not bulk, else "trace" level
+ if (!is_bulk) {
+ log_info(biasedlocking)(" Revoked bias of anonymously-biased object");
+ } else {
+ log_trace(biasedlocking)(" Revoked bias of anonymously-biased object");
}
return BiasedLocking::BIAS_REVOKED;
}
@@ -198,8 +220,11 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_
} else {
obj->set_mark(unbiased_prototype);
}
- if (TraceBiasedLocking && (Verbose || !is_bulk)) {
- tty->print_cr(" Revoked bias of object biased toward dead thread");
+ // Log at "info" level if not bulk, else "trace" level
+ if (!is_bulk) {
+ log_info(biasedlocking)(" Revoked bias of object biased toward dead thread");
+ } else {
+ log_trace(biasedlocking)(" Revoked bias of object biased toward dead thread");
}
return BiasedLocking::BIAS_REVOKED;
}
@@ -214,21 +239,17 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_
for (int i = 0; i < cached_monitor_info->length(); i++) {
MonitorInfo* mon_info = cached_monitor_info->at(i);
if (mon_info->owner() == obj) {
- if (TraceBiasedLocking && Verbose) {
- tty->print_cr(" mon_info->owner (" PTR_FORMAT ") == obj (" PTR_FORMAT ")",
- p2i((void *) mon_info->owner()),
- p2i((void *) obj));
- }
+ log_trace(biasedlocking)(" mon_info->owner (" PTR_FORMAT ") == obj (" PTR_FORMAT ")",
+ p2i((void *) mon_info->owner()),
+ p2i((void *) obj));
// Assume recursive case and fix up highest lock later
markOop mark = markOopDesc::encode((BasicLock*) NULL);
highest_lock = mon_info->lock();
highest_lock->set_displaced_header(mark);
} else {
- if (TraceBiasedLocking && Verbose) {
- tty->print_cr(" mon_info->owner (" PTR_FORMAT ") != obj (" PTR_FORMAT ")",
- p2i((void *) mon_info->owner()),
- p2i((void *) obj));
- }
+ log_trace(biasedlocking)(" mon_info->owner (" PTR_FORMAT ") != obj (" PTR_FORMAT ")",
+ p2i((void *) mon_info->owner()),
+ p2i((void *) obj));
}
}
if (highest_lock != NULL) {
@@ -240,12 +261,18 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_
// ordering (e.g. ppc).
obj->release_set_mark(markOopDesc::encode(highest_lock));
assert(!obj->mark()->has_bias_pattern(), "illegal mark state: stack lock used bias bit");
- if (TraceBiasedLocking && (Verbose || !is_bulk)) {
- tty->print_cr(" Revoked bias of currently-locked object");
+ // Log at "info" level if not bulk, else "trace" level
+ if (!is_bulk) {
+ log_info(biasedlocking)(" Revoked bias of currently-locked object");
+ } else {
+ log_trace(biasedlocking)(" Revoked bias of currently-locked object");
}
} else {
- if (TraceBiasedLocking && (Verbose || !is_bulk)) {
- tty->print_cr(" Revoked bias of currently-unlocked object");
+ // Log at "info" level if not bulk, else "trace" level
+ if (!is_bulk) {
+ log_info(biasedlocking)(" Revoked bias of currently-unlocked object");
+ } else {
+ log_trace(biasedlocking)(" Revoked bias of currently-unlocked object");
}
if (allow_rebias) {
obj->set_mark(biased_prototype);
@@ -326,12 +353,12 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o,
JavaThread* requesting_thread) {
assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint");
- if (TraceBiasedLocking) {
- tty->print_cr("* Beginning bulk revocation (kind == %s) because of object "
- INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
- (bulk_rebias ? "rebias" : "revoke"),
- p2i((void *) o), (intptr_t) o->mark(), o->klass()->external_name());
- }
+ log_info(biasedlocking)("* Beginning bulk revocation (kind == %s) because of object "
+ INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
+ (bulk_rebias ? "rebias" : "revoke"),
+ p2i((void *) o),
+ (intptr_t) o->mark(),
+ o->klass()->external_name());
jlong cur_time = os::javaTimeMillis();
o->klass()->set_last_biased_lock_bulk_revocation_time(cur_time);
@@ -377,9 +404,9 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o,
// adjust the header of the given object to revoke its bias.
revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread);
} else {
- if (TraceBiasedLocking) {
+ if (log_is_enabled(Info, biasedlocking)) {
ResourceMark rm;
- tty->print_cr("* Disabling biased locking for type %s", klass->external_name());
+ log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name());
}
// Disable biased locking for this data type. Not only will this
@@ -407,9 +434,7 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o,
revoke_bias(o, false, true, requesting_thread);
}
- if (TraceBiasedLocking) {
- tty->print_cr("* Ending bulk revocation");
- }
+ log_info(biasedlocking)("* Ending bulk revocation");
BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED;
@@ -420,9 +445,7 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o,
klass->prototype_header()->bias_epoch());
o->set_mark(new_mark);
status_code = BiasedLocking::BIAS_REVOKED_AND_REBIASED;
- if (TraceBiasedLocking) {
- tty->print_cr(" Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread);
- }
+ log_info(biasedlocking)(" Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread);
}
assert(!o->mark()->has_bias_pattern() ||
@@ -485,16 +508,12 @@ public:
virtual void doit() {
if (_obj != NULL) {
- if (TraceBiasedLocking) {
- tty->print_cr("Revoking bias with potentially per-thread safepoint:");
- }
+ log_info(biasedlocking)("Revoking bias with potentially per-thread safepoint:");
_status_code = revoke_bias((*_obj)(), false, false, _requesting_thread);
clean_up_cached_monitor_info();
return;
} else {
- if (TraceBiasedLocking) {
- tty->print_cr("Revoking bias with global safepoint:");
- }
+ log_info(biasedlocking)("Revoking bias with global safepoint:");
BiasedLocking::revoke_at_safepoint(_objs);
}
}
@@ -608,9 +627,7 @@ BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attem
// can come in with a CAS to steal the bias of an object that has a
// stale epoch.
ResourceMark rm;
- if (TraceBiasedLocking) {
- tty->print_cr("Revoking bias by walking my own stack:");
- }
+ log_info(biasedlocking)("Revoking bias by walking my own stack:");
BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD);
((JavaThread*) THREAD)->set_cached_monitor_info(NULL);
assert(cond == BIAS_REVOKED, "why not?");
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
index 86cd7328dd2..ce36ff1db49 100644
--- a/hotspot/src/share/vm/runtime/globals.hpp
+++ b/hotspot/src/share/vm/runtime/globals.hpp
@@ -1488,9 +1488,6 @@ public:
develop(bool, TraceClearedExceptions, false, \
"Print when an exception is forcibly cleared") \
\
- product(bool, TraceBiasedLocking, false, \
- "Trace biased locking in JVM") \
- \
/* gc */ \
\
product(bool, UseSerialGC, false, \
diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp
index 5b9faf084d3..9f5bab030a6 100644
--- a/hotspot/src/share/vm/runtime/thread.cpp
+++ b/hotspot/src/share/vm/runtime/thread.cpp
@@ -170,11 +170,10 @@ void* Thread::allocate(size_t size, bool throw_excpt, MEMFLAGS flags) {
assert(((uintptr_t) aligned_addr + (uintptr_t) size) <=
((uintptr_t) real_malloc_addr + (uintptr_t) aligned_size),
"JavaThread alignment code overflowed allocated storage");
- if (TraceBiasedLocking) {
- if (aligned_addr != real_malloc_addr) {
- tty->print_cr("Aligned thread " INTPTR_FORMAT " to " INTPTR_FORMAT,
- p2i(real_malloc_addr), p2i(aligned_addr));
- }
+ if (aligned_addr != real_malloc_addr) {
+ log_info(biasedlocking)("Aligned thread " INTPTR_FORMAT " to " INTPTR_FORMAT,
+ p2i(real_malloc_addr),
+ p2i(aligned_addr));
}
((Thread*) aligned_addr)->_real_malloc_address = real_malloc_addr;
return aligned_addr;
diff --git a/hotspot/test/runtime/logging/BiasedLockingTest.java b/hotspot/test/runtime/logging/BiasedLockingTest.java
new file mode 100644
index 00000000000..36afcea3c75
--- /dev/null
+++ b/hotspot/test/runtime/logging/BiasedLockingTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+/*
+ * @test
+ * @bug 8149383
+ * @summary -Xlog:biasedlocking should have logging from statements in the source code
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * java.management
+ * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools
+ * @run driver BiasedLockingTest
+ */
+
+import jdk.test.lib.OutputAnalyzer;
+import jdk.test.lib.ProcessTools;
+
+public class BiasedLockingTest {
+ static void analyzeOutputOn(ProcessBuilder pb) throws Exception {
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldContain("Biased locking enabled");
+ output.shouldHaveExitValue(0);
+ }
+
+ static void analyzeOutputOff(ProcessBuilder pb) throws Exception {
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldNotContain("[biasedlocking]");
+ output.shouldHaveExitValue(0);
+ }
+
+ public static void main(String[] args) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:biasedlocking",
+ "-XX:BiasedLockingStartupDelay=0",
+ InnerClass.class.getName());
+ analyzeOutputOn(pb);
+
+ pb = ProcessTools.createJavaProcessBuilder("-XX:+TraceBiasedLocking",
+ "-XX:BiasedLockingStartupDelay=0",
+ InnerClass.class.getName());
+ analyzeOutputOn(pb);
+
+ pb = ProcessTools.createJavaProcessBuilder("-Xlog:biasedlocking=off",
+ "-XX:BiasedLockingStartupDelay=0",
+ InnerClass.class.getName());
+ analyzeOutputOff(pb);
+
+ pb = ProcessTools.createJavaProcessBuilder("-XX:-TraceBiasedLocking",
+ "-XX:BiasedLockingStartupDelay=0",
+ InnerClass.class.getName());
+ analyzeOutputOff(pb);
+ }
+
+ public static class InnerClass {
+ public static void main(String[] args) {
+ System.out.println("Biased Locking test");
+ }
+ }
+}
From 98289a12c931713c41c367d9a96a50cb94b5aff0 Mon Sep 17 00:00:00 2001
From: Derek White
Date: Wed, 17 Feb 2016 18:02:03 -0500
Subject: [PATCH 039/311] 8149837: String.intern creates morre work than
necessary for G1
Only use the SATB read barrier when reading existing strings from string table, not when adding new strings.
Reviewed-by: stefank, kbarrett
---
hotspot/src/share/vm/classfile/stringTable.cpp | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/hotspot/src/share/vm/classfile/stringTable.cpp b/hotspot/src/share/vm/classfile/stringTable.cpp
index ee303426f3c..167ec28449c 100644
--- a/hotspot/src/share/vm/classfile/stringTable.cpp
+++ b/hotspot/src/share/vm/classfile/stringTable.cpp
@@ -200,7 +200,6 @@ oop StringTable::lookup(jchar* name, int len) {
return string;
}
-
oop StringTable::intern(Handle string_or_null, jchar* name,
int len, TRAPS) {
oop found_string = lookup_shared(name, len);
@@ -214,7 +213,9 @@ oop StringTable::intern(Handle string_or_null, jchar* name,
// Found
if (found_string != NULL) {
- ensure_string_alive(found_string);
+ if (found_string != string_or_null()) {
+ ensure_string_alive(found_string);
+ }
return found_string;
}
@@ -249,7 +250,9 @@ oop StringTable::intern(Handle string_or_null, jchar* name,
hashValue, CHECK_NULL);
}
- ensure_string_alive(added_or_found);
+ if (added_or_found != string()) {
+ ensure_string_alive(added_or_found);
+ }
return added_or_found;
}
From 40cdd7a181d53e5a533b1a6644fdcc58a2601664 Mon Sep 17 00:00:00 2001
From: Felix Yang
Date: Thu, 18 Feb 2016 21:53:24 +0800
Subject: [PATCH 040/311] 8149907: aarch64: use load/store pair instructions in
call_stub
Aarch64: make use of load/store pair instructions in call_stub to save space
Reviewed-by: aph
---
.../cpu/aarch64/vm/stubGenerator_aarch64.cpp | 94 +++++--------------
1 file changed, 26 insertions(+), 68 deletions(-)
diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
index 64833c5ccc4..942d7bc5cb7 100644
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
@@ -163,30 +163,20 @@ class StubGenerator: public StubCodeGenerator {
sp_after_call_off = -26,
d15_off = -26,
- d14_off = -25,
d13_off = -24,
- d12_off = -23,
d11_off = -22,
- d10_off = -21,
d9_off = -20,
- d8_off = -19,
r28_off = -18,
- r27_off = -17,
r26_off = -16,
- r25_off = -15,
r24_off = -14,
- r23_off = -13,
r22_off = -12,
- r21_off = -11,
r20_off = -10,
- r19_off = -9,
call_wrapper_off = -8,
result_off = -7,
result_type_off = -6,
method_off = -5,
entry_point_off = -4,
- parameters_off = -3,
parameter_size_off = -2,
thread_off = -1,
fp_f = 0,
@@ -208,30 +198,20 @@ class StubGenerator: public StubCodeGenerator {
const Address result_type (rfp, result_type_off * wordSize);
const Address method (rfp, method_off * wordSize);
const Address entry_point (rfp, entry_point_off * wordSize);
- const Address parameters (rfp, parameters_off * wordSize);
const Address parameter_size(rfp, parameter_size_off * wordSize);
const Address thread (rfp, thread_off * wordSize);
const Address d15_save (rfp, d15_off * wordSize);
- const Address d14_save (rfp, d14_off * wordSize);
const Address d13_save (rfp, d13_off * wordSize);
- const Address d12_save (rfp, d12_off * wordSize);
const Address d11_save (rfp, d11_off * wordSize);
- const Address d10_save (rfp, d10_off * wordSize);
const Address d9_save (rfp, d9_off * wordSize);
- const Address d8_save (rfp, d8_off * wordSize);
const Address r28_save (rfp, r28_off * wordSize);
- const Address r27_save (rfp, r27_off * wordSize);
const Address r26_save (rfp, r26_off * wordSize);
- const Address r25_save (rfp, r25_off * wordSize);
const Address r24_save (rfp, r24_off * wordSize);
- const Address r23_save (rfp, r23_off * wordSize);
const Address r22_save (rfp, r22_off * wordSize);
- const Address r21_save (rfp, r21_off * wordSize);
const Address r20_save (rfp, r20_off * wordSize);
- const Address r19_save (rfp, r19_off * wordSize);
// stub code
@@ -254,31 +234,20 @@ class StubGenerator: public StubCodeGenerator {
// rthread because we want to sanity check rthread later
__ str(c_rarg7, thread);
__ strw(c_rarg6, parameter_size);
- __ str(c_rarg5, parameters);
- __ str(c_rarg4, entry_point);
- __ str(c_rarg3, method);
- __ str(c_rarg2, result_type);
- __ str(c_rarg1, result);
- __ str(c_rarg0, call_wrapper);
- __ str(r19, r19_save);
- __ str(r20, r20_save);
- __ str(r21, r21_save);
- __ str(r22, r22_save);
- __ str(r23, r23_save);
- __ str(r24, r24_save);
- __ str(r25, r25_save);
- __ str(r26, r26_save);
- __ str(r27, r27_save);
- __ str(r28, r28_save);
+ __ stp(c_rarg4, c_rarg5, entry_point);
+ __ stp(c_rarg2, c_rarg3, result_type);
+ __ stp(c_rarg0, c_rarg1, call_wrapper);
- __ strd(v8, d8_save);
- __ strd(v9, d9_save);
- __ strd(v10, d10_save);
- __ strd(v11, d11_save);
- __ strd(v12, d12_save);
- __ strd(v13, d13_save);
- __ strd(v14, d14_save);
- __ strd(v15, d15_save);
+ __ stp(r20, r19, r20_save);
+ __ stp(r22, r21, r22_save);
+ __ stp(r24, r23, r24_save);
+ __ stp(r26, r25, r26_save);
+ __ stp(r28, r27, r28_save);
+
+ __ stpd(v9, v8, d9_save);
+ __ stpd(v11, v10, d11_save);
+ __ stpd(v13, v12, d13_save);
+ __ stpd(v15, v14, d15_save);
// install Java thread in global register now we have saved
// whatever value it held
@@ -385,33 +354,22 @@ class StubGenerator: public StubCodeGenerator {
#endif
// restore callee-save registers
- __ ldrd(v15, d15_save);
- __ ldrd(v14, d14_save);
- __ ldrd(v13, d13_save);
- __ ldrd(v12, d12_save);
- __ ldrd(v11, d11_save);
- __ ldrd(v10, d10_save);
- __ ldrd(v9, d9_save);
- __ ldrd(v8, d8_save);
+ __ ldpd(v15, v14, d15_save);
+ __ ldpd(v13, v12, d13_save);
+ __ ldpd(v11, v10, d11_save);
+ __ ldpd(v9, v8, d9_save);
- __ ldr(r28, r28_save);
- __ ldr(r27, r27_save);
- __ ldr(r26, r26_save);
- __ ldr(r25, r25_save);
- __ ldr(r24, r24_save);
- __ ldr(r23, r23_save);
- __ ldr(r22, r22_save);
- __ ldr(r21, r21_save);
- __ ldr(r20, r20_save);
- __ ldr(r19, r19_save);
- __ ldr(c_rarg0, call_wrapper);
- __ ldr(c_rarg1, result);
+ __ ldp(r28, r27, r28_save);
+ __ ldp(r26, r25, r26_save);
+ __ ldp(r24, r23, r24_save);
+ __ ldp(r22, r21, r22_save);
+ __ ldp(r20, r19, r20_save);
+
+ __ ldp(c_rarg0, c_rarg1, call_wrapper);
__ ldrw(c_rarg2, result_type);
__ ldr(c_rarg3, method);
- __ ldr(c_rarg4, entry_point);
- __ ldr(c_rarg5, parameters);
- __ ldr(c_rarg6, parameter_size);
- __ ldr(c_rarg7, thread);
+ __ ldp(c_rarg4, c_rarg5, entry_point);
+ __ ldp(c_rarg6, c_rarg7, parameter_size);
#ifndef PRODUCT
// tell the simulator we are about to end Java execution
From 2cfe5a01c4f351fc19e662a4d28d611e9e1845d1 Mon Sep 17 00:00:00 2001
From: Yasumasa Suenaga
Date: Thu, 18 Feb 2016 23:26:43 +0900
Subject: [PATCH 041/311] 8147388: Add diagnostic commands to attach JVMTI
agent
Reviewed-by: jbachorik, sspitsyn
---
hotspot/src/share/vm/prims/jvmtiExport.cpp | 15 ++-
hotspot/src/share/vm/prims/jvmtiExport.hpp | 1 +
.../share/vm/services/diagnosticCommand.cpp | 61 ++++++++++
.../share/vm/services/diagnosticCommand.hpp | 20 ++++
.../dcmd/jvmti/LoadAgentDcmdTest.java | 111 ++++++++++++++++++
.../dcmd/jvmti/LoadJavaAgentDcmdTest.java | 81 +++++++++++++
.../dcmd/jvmti/SimpleJvmtiAgent.java | 29 +++++
7 files changed, 313 insertions(+), 5 deletions(-)
create mode 100644 hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java
create mode 100644 hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java
create mode 100644 hotspot/test/serviceability/dcmd/jvmti/SimpleJvmtiAgent.java
diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp
index 2c352044f02..7ad054138c6 100644
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp
@@ -2200,6 +2200,16 @@ extern "C" {
}
jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) {
+ // get agent name and options
+ const char* agent = op->arg(0);
+ const char* absParam = op->arg(1);
+ const char* options = op->arg(2);
+
+ return load_agent_library(agent, absParam, options, st);
+}
+
+jint JvmtiExport::load_agent_library(const char *agent, const char *absParam,
+ const char *options, outputStream* st) {
char ebuf[1024];
char buffer[JVM_MAXPATHLEN];
void* library = NULL;
@@ -2207,11 +2217,6 @@ jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) {
const char *on_attach_symbols[] = AGENT_ONATTACH_SYMBOLS;
size_t num_symbol_entries = ARRAY_SIZE(on_attach_symbols);
- // get agent name and options
- const char* agent = op->arg(0);
- const char* absParam = op->arg(1);
- const char* options = op->arg(2);
-
// The abs paramter should be "true" or "false"
bool is_absolute_path = (absParam != NULL) && (strcmp(absParam,"true")==0);
diff --git a/hotspot/src/share/vm/prims/jvmtiExport.hpp b/hotspot/src/share/vm/prims/jvmtiExport.hpp
index 4b1ff34cf61..8b06d62104b 100644
--- a/hotspot/src/share/vm/prims/jvmtiExport.hpp
+++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp
@@ -372,6 +372,7 @@ class JvmtiExport : public AllStatic {
static void transition_pending_onload_raw_monitors() NOT_JVMTI_RETURN;
// attach support
+ static jint load_agent_library(const char *agent, const char *absParam, const char *options, outputStream* out) NOT_JVMTI_RETURN_(JNI_ERR);
static jint load_agent_library(AttachOperation* op, outputStream* out) NOT_JVMTI_RETURN_(JNI_ERR);
// SetNativeMethodPrefix support
diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp
index d6dde5eef83..2a81ae7bfad 100644
--- a/hotspot/src/share/vm/services/diagnosticCommand.cpp
+++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp
@@ -71,6 +71,7 @@ void DCmdRegistrant::register_dcmds(){
#endif // INCLUDE_SERVICES
#if INCLUDE_JVMTI
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false));
#endif // INCLUDE_JVMTI
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false));
@@ -254,6 +255,66 @@ void JVMTIDataDumpDCmd::execute(DCmdSource source, TRAPS) {
}
}
+JVMTIAgentLoadDCmd::JVMTIAgentLoadDCmd(outputStream* output, bool heap) :
+ DCmdWithParser(output, heap),
+ _libpath("library path", "Absolute path of the JVMTI agent to load.",
+ "STRING", true),
+ _option("agent option", "Option string to pass the agent.", "STRING", false) {
+ _dcmdparser.add_dcmd_argument(&_libpath);
+ _dcmdparser.add_dcmd_argument(&_option);
+}
+
+void JVMTIAgentLoadDCmd::execute(DCmdSource source, TRAPS) {
+
+ if (_libpath.value() == NULL) {
+ output()->print_cr("JVMTI.agent_load dcmd needs library path.");
+ return;
+ }
+
+ char *suffix = strrchr(_libpath.value(), '.');
+ bool is_java_agent = (suffix != NULL) && (strncmp(".jar", suffix, 4) == 0);
+
+ if (is_java_agent) {
+ if (_option.value() == NULL) {
+ JvmtiExport::load_agent_library("instrument", "false",
+ _libpath.value(), output());
+ } else {
+ size_t opt_len = strlen(_libpath.value()) + strlen(_option.value()) + 2;
+ if (opt_len > 4096) {
+ output()->print_cr("JVMTI agent attach failed: Options is too long.");
+ return;
+ }
+
+ char *opt = (char *)os::malloc(opt_len, mtInternal);
+ if (opt == NULL) {
+ output()->print_cr("JVMTI agent attach failed: "
+ "Could not allocate %zu bytes for argument.",
+ opt_len);
+ return;
+ }
+
+ jio_snprintf(opt, opt_len, "%s=%s", _libpath.value(), _option.value());
+ JvmtiExport::load_agent_library("instrument", "false", opt, output());
+
+ os::free(opt);
+ }
+ } else {
+ JvmtiExport::load_agent_library(_libpath.value(), "true",
+ _option.value(), output());
+ }
+}
+
+int JVMTIAgentLoadDCmd::num_arguments() {
+ ResourceMark rm;
+ JVMTIAgentLoadDCmd* dcmd = new JVMTIAgentLoadDCmd(NULL, false);
+ if (dcmd != NULL) {
+ DCmdMark mark(dcmd);
+ return dcmd->_dcmdparser.num_arguments();
+ } else {
+ return 0;
+ }
+}
+
void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) {
// load sun.misc.VMSupport
Symbol* klass = vmSymbols::sun_misc_VMSupport();
diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp
index ea3ddfe588a..8f5dc9172ae 100644
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp
@@ -174,6 +174,26 @@ public:
virtual void execute(DCmdSource source, TRAPS);
};
+class JVMTIAgentLoadDCmd : public DCmdWithParser {
+protected:
+ DCmdArgument _libpath;
+ DCmdArgument _option;
+public:
+ JVMTIAgentLoadDCmd(outputStream* output, bool heap);
+ static const char* name() { return "JVMTI.agent_load"; }
+ static const char* description() {
+ return "Load JVMTI native agent.";
+ }
+ static const char* impact() { return "Low"; }
+ static const JavaPermission permission() {
+ JavaPermission p = {"java.lang.management.ManagementPermission",
+ "control", NULL};
+ return p;
+ }
+ static int num_arguments();
+ virtual void execute(DCmdSource source, TRAPS);
+};
+
class VMDynamicLibrariesDCmd : public DCmd {
public:
VMDynamicLibrariesDCmd(outputStream* output, bool heap);
diff --git a/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java
new file mode 100644
index 00000000000..ad4d5871a20
--- /dev/null
+++ b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+import java.io.*;
+import java.nio.file.*;
+import jdk.test.lib.*;
+import jdk.test.lib.dcmd.*;
+import org.testng.annotations.Test;
+
+/*
+ * Test to attach JVMTI java agent.
+ *
+ * @test
+ * @bug 8147388
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * java.compiler
+ * java.instrument
+ * java.management
+ * jdk.jvmstat/sun.jvmstat.monitor
+ * @build ClassFileInstaller jdk.test.lib.* SimpleJvmtiAgent
+ * @run main ClassFileInstaller SimpleJvmtiAgent
+ * @run testng LoadAgentDcmdTest
+ */
+public class LoadAgentDcmdTest {
+
+ public String getLibInstrumentPath() throws FileNotFoundException {
+ String jdkPath = System.getProperty("test.jdk");
+
+ if (jdkPath == null) {
+ throw new RuntimeException(
+ "System property 'test.jdk' not set. " +
+ "This property is normally set by jtreg. " +
+ "When running test separately, set this property using " +
+ "'-Dtest.jdk=/path/to/jdk'.");
+ }
+
+ Path libpath;
+ if (Platform.isWindows()) {
+ libpath = Paths.get(jdkPath, "bin", "instrument.dll");
+ } else {
+ libpath = Paths.get(jdkPath, "lib", Platform.getOsArch(), "libinstrument.so");
+ }
+
+ if (!libpath.toFile().exists()) {
+ throw new FileNotFoundException(
+ "Could not find " + libpath.toAbsolutePath());
+ }
+
+ return libpath.toAbsolutePath().toString();
+ }
+
+ public void run(CommandExecutor executor) {
+ try{
+ PrintWriter pw = new PrintWriter("MANIFEST.MF");
+ pw.println("Agent-Class: SimpleJvmtiAgent");
+ pw.close();
+
+ ProcessBuilder pb = new ProcessBuilder();
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jar"),
+ "cmf",
+ "MANIFEST.MF",
+ "agent.jar",
+ "SimpleJvmtiAgent.class"});
+ pb.start().waitFor();
+
+ String libpath = getLibInstrumentPath();
+
+ // Test 1: No argument
+ OutputAnalyzer output = executor.execute("JVMTI.agent_load " +
+ libpath + " agent.jar");
+ output.stderrShouldBeEmpty();
+
+ // Test 2: With argument
+ output = executor.execute("JVMTI.agent_load " +
+ libpath + " \"agent.jar=foo=bar\"");
+ output.stderrShouldBeEmpty();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void jmx() throws Throwable {
+ run(new JMXExecutor());
+ }
+
+ @Test
+ public void cli() throws Throwable {
+ run(new PidJcmdExecutor());
+ }
+}
diff --git a/hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java b/hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java
new file mode 100644
index 00000000000..6c0c17760aa
--- /dev/null
+++ b/hotspot/test/serviceability/dcmd/jvmti/LoadJavaAgentDcmdTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+import java.io.*;
+import jdk.test.lib.*;
+import jdk.test.lib.dcmd.*;
+import org.testng.annotations.Test;
+
+/*
+ * Test to attach JVMTI java agent.
+ *
+ * @test
+ * @bug 8147388
+ * @library /testlibrary
+ * @modules java.base/sun.misc
+ * java.compiler
+ * java.instrument
+ * java.management
+ * jdk.jvmstat/sun.jvmstat.monitor
+ * @build ClassFileInstaller jdk.test.lib.* SimpleJvmtiAgent
+ * @run main ClassFileInstaller SimpleJvmtiAgent
+ * @run testng LoadJavaAgentDcmdTest
+ */
+public class LoadJavaAgentDcmdTest {
+ public void run(CommandExecutor executor) {
+ try{
+ PrintWriter pw = new PrintWriter("MANIFEST.MF");
+ pw.println("Agent-Class: SimpleJvmtiAgent");
+ pw.close();
+
+ ProcessBuilder pb = new ProcessBuilder();
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jar"),
+ "cmf",
+ "MANIFEST.MF",
+ "agent.jar",
+ "SimpleJvmtiAgent.class"});
+ pb.start().waitFor();
+
+ // Test 1: No argument
+ OutputAnalyzer output = executor.execute("JVMTI.agent_load " +
+ "agent.jar");
+ output.stderrShouldBeEmpty();
+
+ // Test 2: With argument
+ output = executor.execute("JVMTI.agent_load " +
+ "\"agent.jar=foo=bar\"");
+ output.stderrShouldBeEmpty();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ public void jmx() throws Throwable {
+ run(new JMXExecutor());
+ }
+
+ @Test
+ public void cli() throws Throwable {
+ run(new PidJcmdExecutor());
+ }
+}
diff --git a/hotspot/test/serviceability/dcmd/jvmti/SimpleJvmtiAgent.java b/hotspot/test/serviceability/dcmd/jvmti/SimpleJvmtiAgent.java
new file mode 100644
index 00000000000..6d92ff32f66
--- /dev/null
+++ b/hotspot/test/serviceability/dcmd/jvmti/SimpleJvmtiAgent.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+import java.lang.instrument.*;
+
+public class SimpleJvmtiAgent {
+ public static void agentmain(String agentArgs, Instrumentation instrumentation) {
+ System.out.println("attach succeeded (args: \"" + agentArgs + "\")");
+ }
+}
From 3a1062775ada000b51703c3c38acaf5f7eab3bdf Mon Sep 17 00:00:00 2001
From: Andreas Eriksson
Date: Thu, 18 Feb 2016 16:15:15 +0100
Subject: [PATCH 042/311] 8149743: JVM crash after debugger hotswap with
lambdas
Reviewed-by: sspitsyn, coleenp, dcubed
---
.../com/sun/jdi/RedefineAddPrivateMethod.sh | 77 +++++++++++++++++++
1 file changed, 77 insertions(+)
create mode 100644 jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh
diff --git a/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh b/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh
new file mode 100644
index 00000000000..bb9eefd8968
--- /dev/null
+++ b/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+#
+# Copyright (c) 2016, 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.
+#
+
+# @test
+# @bug 8149743
+# @summary crash when adding a breakpoint after redefining to add a private static method
+# @run shell RedefineAddPrivateMethod.sh
+
+compileOptions=-g
+
+createJavaFile()
+{
+ cat < $1.java.1
+public class $1 {
+ static public void main(String[] args) {
+ // @1 breakpoint @2 breakpoint
+ }
+
+ // @1 uncomment private static void test() {}
+}
+EOF
+}
+
+# This is called to feed cmds to jdb.
+dojdbCmds()
+{
+ setBkpts @1
+ runToBkpt @1
+ redefineClass @1
+ setBkpts @2
+ cmd allowExit cont
+}
+
+
+mysetup()
+{
+ if [ -z "$TESTSRC" ] ; then
+ TESTSRC=.
+ fi
+
+ for ii in . $TESTSRC $TESTSRC/.. ; do
+ if [ -r "$ii/ShellScaffold.sh" ] ; then
+ . $ii/ShellScaffold.sh
+ break
+ fi
+ done
+}
+
+# You could replace this next line with the contents
+# of ShellScaffold.sh and this script will run just the same.
+mysetup
+
+runit
+debuggeeFailIfPresent "Internal exception:"
+pass
From 35a916a2a186a093ef4c4b759edc1164793ef82a Mon Sep 17 00:00:00 2001
From: Andreas Eriksson
Date: Thu, 18 Feb 2016 16:15:28 +0100
Subject: [PATCH 043/311] 8149743: JVM crash after debugger hotswap with
lambdas
Reviewed-by: sspitsyn, coleenp, dcubed
---
hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp
index 8823e6670a6..6b176ec1f70 100644
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -3940,6 +3940,10 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
scratch_class->set_methods(_old_methods); // To prevent potential GCing of the old methods,
// and to be able to undo operation easily.
+ Array* old_ordering = the_class->method_ordering();
+ the_class->set_method_ordering(scratch_class->method_ordering());
+ scratch_class->set_method_ordering(old_ordering);
+
ConstantPool* old_constants = the_class->constants();
the_class->set_constants(scratch_class->constants());
scratch_class->set_constants(old_constants); // See the previous comment.
From 717ad7019c3aae78f4336c22fa2362f00dd1c763 Mon Sep 17 00:00:00 2001
From: Sergey Bylokhov
Date: Thu, 18 Feb 2016 22:11:29 +0300
Subject: [PATCH 044/311] 8038139: AudioInputStream.getFrameLength() returns
wrong value for floating-point WAV
Reviewed-by: prr, amenkov
---
.../com/sun/media/sound/AiffFileReader.java | 75 ++-----
.../com/sun/media/sound/AiffFileWriter.java | 37 +---
.../media/sound/WaveExtensibleFileReader.java | 9 +-
.../sun/media/sound/WaveFloatFileReader.java | 9 +-
.../FrameLengthAfterConversion.java | 209 ++++++++++++++++++
5 files changed, 244 insertions(+), 95 deletions(-)
create mode 100644 jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java
diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java
index 8c9dc3c78be..c0ac8bf6d40 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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,11 +26,11 @@
package com.sun.media.sound;
import java.io.DataInputStream;
-import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFileFormat.Type;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
@@ -49,11 +49,6 @@ public final class AiffFileReader extends SunFileReader {
throws UnsupportedAudioFileException, IOException {
DataInputStream dis = new DataInputStream(stream);
- // assumes a stream at the beginning of the file which has already
- // passed the magic number test...
- // leaves the input stream at the beginning of the audio data
- int fileRead = 0;
- int dataLength = 0;
AudioFormat format = null;
// Read the magic number
@@ -65,9 +60,9 @@ public final class AiffFileReader extends SunFileReader {
throw new UnsupportedAudioFileException("not an AIFF file");
}
+ int frameLength = 0;
int length = dis.readInt();
int iffType = dis.readInt();
- fileRead += 12;
int totallength;
if(length <= 0 ) {
@@ -91,7 +86,6 @@ public final class AiffFileReader extends SunFileReader {
// Read the chunk name
int chunkName = dis.readInt();
int chunkLen = dis.readInt();
- fileRead += 8;
int chunkRead = 0;
@@ -112,7 +106,13 @@ public final class AiffFileReader extends SunFileReader {
if (channels <= 0) {
throw new UnsupportedAudioFileException("Invalid number of channels");
}
- dis.readInt(); // numSampleFrames
+ frameLength = dis.readInt(); // numSampleFrames
+ if (frameLength < 0) {
+ // AiffFileFormat uses int, unlike AIS which uses long
+ //TODO this (negative) value should be passed as long to AIS
+ frameLength = AudioSystem.NOT_SPECIFIED;
+ }
+
int sampleSizeInBits = dis.readUnsignedShort();
if (sampleSizeInBits < 1 || sampleSizeInBits > 32) {
throw new UnsupportedAudioFileException("Invalid AIFF/COMM sampleSize");
@@ -149,38 +149,17 @@ public final class AiffFileReader extends SunFileReader {
break;
case AiffFileFormat.SSND_MAGIC:
// Data chunk.
- // we are getting *weird* numbers for chunkLen sometimes;
- // this really should be the size of the data chunk....
- int dataOffset = dis.readInt();
- int blocksize = dis.readInt();
+ int dataOffset = dis.readInt(); // for now unused in javasound
+ int blocksize = dis.readInt(); // for now unused in javasound
chunkRead += 8;
-
- // okay, now we are done reading the header. we need to set the size
- // of the data segment. we know that sometimes the value we get for
- // the chunksize is absurd. this is the best i can think of:if the
- // value seems okay, use it. otherwise, we get our value of
- // length by assuming that everything left is the data segment;
- // its length should be our original length (for all AIFF data chunks)
- // minus what we've read so far.
- // $$kk: we should be able to get length for the data chunk right after
- // we find "SSND." however, some aiff files give *weird* numbers. what
- // is going on??
-
- if (chunkLen < length) {
- dataLength = chunkLen - chunkRead;
- } else {
- // $$kk: 11.03.98: this seems dangerous!
- dataLength = length - (fileRead + chunkRead);
- }
ssndFound = true;
break;
} // switch
- fileRead += chunkRead;
// skip the remainder of this chunk
if (!ssndFound) {
int toSkip = chunkLen - chunkRead;
if (toSkip > 0) {
- fileRead += dis.skipBytes(toSkip);
+ dis.skipBytes(toSkip);
}
}
} // while
@@ -188,36 +167,12 @@ public final class AiffFileReader extends SunFileReader {
if (format == null) {
throw new UnsupportedAudioFileException("missing COMM chunk");
}
- AudioFileFormat.Type type = aifc?AudioFileFormat.Type.AIFC:AudioFileFormat.Type.AIFF;
+ Type type = aifc ? Type.AIFC : Type.AIFF;
- return new AiffFileFormat(type, totallength, format, dataLength / format.getFrameSize());
+ return new AiffFileFormat(type, totallength, format, frameLength);
}
// HELPER METHODS
- /** write_ieee_extended(DataOutputStream dos, double f) throws IOException {
- * Extended precision IEEE floating-point conversion routine.
- * @argument DataOutputStream
- * @argument double
- * @return void
- * @exception IOException
- */
- private void write_ieee_extended(DataOutputStream dos, double f) throws IOException {
-
- int exponent = 16398;
- double highMantissa = f;
-
- // For now write the integer portion of f
- // $$jb: 03.30.99: stay in synch with JMF on this!!!!
- while (highMantissa < 44000) {
- highMantissa *= 2;
- exponent--;
- }
- dos.writeShort(exponent);
- dos.writeInt( ((int) highMantissa) << 16);
- dos.writeInt(0); // low Mantissa
- }
-
-
/**
* read_ieee_extended
* Extended precision IEEE floating-point conversion routine.
diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java
index 0a4788df804..9b5ebac2f6b 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java
@@ -59,7 +59,6 @@ public final class AiffFileWriter extends SunFileWriter {
super(new AudioFileFormat.Type[]{AudioFileFormat.Type.AIFF});
}
-
// METHODS TO IMPLEMENT AudioFileWriter
@Override
@@ -83,7 +82,6 @@ public final class AiffFileWriter extends SunFileWriter {
return new AudioFileFormat.Type[0];
}
-
@Override
public int write(AudioInputStream stream, AudioFileFormat.Type fileType, OutputStream out) throws IOException {
Objects.requireNonNull(stream);
@@ -102,11 +100,9 @@ public final class AiffFileWriter extends SunFileWriter {
throw new IOException("stream length not specified");
}
- int bytesWritten = writeAiffFile(stream, aiffFileFormat, out);
- return bytesWritten;
+ return writeAiffFile(stream, aiffFileFormat, out);
}
-
@Override
public int write(AudioInputStream stream, AudioFileFormat.Type fileType, File out) throws IOException {
Objects.requireNonNull(stream);
@@ -129,12 +125,15 @@ public final class AiffFileWriter extends SunFileWriter {
// $$kk: 10.22.99: jan: please either implement this or throw an exception!
// $$fb: 2001-07-13: done. Fixes Bug 4479981
- int ssndBlockSize = (aiffFileFormat.getFormat().getChannels() * aiffFileFormat.getFormat().getSampleSizeInBits());
+ int channels = aiffFileFormat.getFormat().getChannels();
+ int sampleSize = aiffFileFormat.getFormat().getSampleSizeInBits();
+ int ssndBlockSize = channels * ((sampleSize + 7) / 8);
int aiffLength=bytesWritten;
int ssndChunkSize=aiffLength-aiffFileFormat.getHeaderSize()+16;
long dataSize=ssndChunkSize-16;
- int numFrames=(int) (dataSize*8/ssndBlockSize);
+ //TODO possibly incorrect round
+ int numFrames = (int) (dataSize / ssndBlockSize);
RandomAccessFile raf=new RandomAccessFile(out, "rw");
// skip FORM magic
@@ -173,12 +172,7 @@ public final class AiffFileWriter extends SunFileWriter {
AudioFormat streamFormat = stream.getFormat();
AudioFormat.Encoding streamEncoding = streamFormat.getEncoding();
-
- float sampleRate;
int sampleSizeInBits;
- int channels;
- int frameSize;
- float frameRate;
int fileSize;
boolean convert8to16 = false;
@@ -235,7 +229,6 @@ public final class AiffFileWriter extends SunFileWriter {
return fileFormat;
}
-
private int writeAiffFile(InputStream in, AiffFileFormat aiffFileFormat, OutputStream out) throws IOException {
int bytesRead = 0;
@@ -275,25 +268,20 @@ public final class AiffFileWriter extends SunFileWriter {
AudioFormat.Encoding encoding = null;
//$$fb a little bit nicer handling of constants
-
- //int headerSize = 54;
int headerSize = aiffFileFormat.getHeaderSize();
-
//int fverChunkSize = 0;
int fverChunkSize = aiffFileFormat.getFverChunkSize();
- //int commChunkSize = 26;
int commChunkSize = aiffFileFormat.getCommChunkSize();
int aiffLength = -1;
int ssndChunkSize = -1;
- //int ssndOffset = headerSize - 16;
int ssndOffset = aiffFileFormat.getSsndChunkOffset();
short channels = (short) format.getChannels();
short sampleSize = (short) format.getSampleSizeInBits();
- int ssndBlockSize = (channels * sampleSize);
- int numFrames = aiffFileFormat.getFrameLength();
- long dataSize = -1;
+ int ssndBlockSize = channels * ((sampleSize + 7) / 8);
+ int numFrames = aiffFileFormat.getFrameLength();
+ long dataSize = -1;
if( numFrames != AudioSystem.NOT_SPECIFIED) {
- dataSize = (long) numFrames * ssndBlockSize / 8;
+ dataSize = (long) numFrames * ssndBlockSize;
ssndChunkSize = (int)dataSize + 16;
aiffLength = (int)dataSize+headerSize;
}
@@ -403,9 +391,6 @@ public final class AiffFileWriter extends SunFileWriter {
}
-
-
-
// HELPER METHODS
private static final int DOUBLE_MANTISSA_LENGTH = 52;
@@ -452,6 +437,4 @@ public final class AiffFileWriter extends SunFileWriter {
dos.writeShort(extendedBits79To64);
dos.writeLong(extendedBits63To0);
}
-
-
}
diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java
index 240c6d27c58..9085c58b530 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java
@@ -255,16 +255,17 @@ public final class WaveExtensibleFileReader extends SunFileReader {
public AudioInputStream getAudioInputStream(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
- AudioFileFormat format = getAudioFileFormat(stream);
+ final AudioFileFormat format = getAudioFileFormat(stream);
// we've got everything, the stream is supported and it is at the
// beginning of the header, so find the data chunk again and return an
// AudioInputStream
- RIFFReader riffiterator = new RIFFReader(stream);
+ final RIFFReader riffiterator = new RIFFReader(stream);
while (riffiterator.hasNextChunk()) {
RIFFReader chunk = riffiterator.nextChunk();
if (chunk.getFormat().equals("data")) {
- return new AudioInputStream(chunk, format.getFormat(), chunk
- .getSize());
+ final AudioFormat af = format.getFormat();
+ final long length = chunk.getSize() / af.getFrameSize();
+ return new AudioInputStream(chunk, af, length);
}
}
throw new UnsupportedAudioFileException();
diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java
index afecd0e34be..6639cf040e8 100644
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java
@@ -95,16 +95,17 @@ public final class WaveFloatFileReader extends SunFileReader {
public AudioInputStream getAudioInputStream(final InputStream stream)
throws UnsupportedAudioFileException, IOException {
- AudioFileFormat format = getAudioFileFormat(stream);
+ final AudioFileFormat format = getAudioFileFormat(stream);
// we've got everything, the stream is supported and it is at the
// beginning of the header, so find the data chunk again and return an
// AudioInputStream
- RIFFReader riffiterator = new RIFFReader(stream);
+ final RIFFReader riffiterator = new RIFFReader(stream);
while (riffiterator.hasNextChunk()) {
RIFFReader chunk = riffiterator.nextChunk();
if (chunk.getFormat().equals("data")) {
- return new AudioInputStream(chunk, format.getFormat(),
- chunk.getSize());
+ final AudioFormat af = format.getFormat();
+ final long length = chunk.getSize() / af.getFrameSize();
+ return new AudioInputStream(chunk, af, length);
}
}
throw new UnsupportedAudioFileException();
diff --git a/jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java b/jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java
new file mode 100644
index 00000000000..e32e7723db5
--- /dev/null
+++ b/jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.UnsupportedAudioFileException;
+import javax.sound.sampled.spi.AudioFileWriter;
+import javax.sound.sampled.spi.FormatConversionProvider;
+
+import static java.util.ServiceLoader.load;
+import static javax.sound.sampled.AudioFileFormat.Type.AIFC;
+import static javax.sound.sampled.AudioFileFormat.Type.AIFF;
+import static javax.sound.sampled.AudioFileFormat.Type.AU;
+import static javax.sound.sampled.AudioFileFormat.Type.SND;
+import static javax.sound.sampled.AudioFileFormat.Type.WAVE;
+import static javax.sound.sampled.AudioSystem.NOT_SPECIFIED;
+
+/**
+ * @test
+ * @bug 8038139
+ */
+public final class FrameLengthAfterConversion {
+
+ /**
+ * We will try to use all formats, in this case all our providers will be
+ * covered by supported/unsupported formats.
+ */
+ private static final List formats = new ArrayList<>(23000);
+
+ private static final AudioFormat.Encoding[] encodings = {
+ AudioFormat.Encoding.ALAW, AudioFormat.Encoding.ULAW,
+ AudioFormat.Encoding.PCM_SIGNED, AudioFormat.Encoding.PCM_UNSIGNED,
+ AudioFormat.Encoding.PCM_FLOAT, new AudioFormat.Encoding("Test")
+ };
+
+ private static final int[] sampleBits = {
+ 1, 4, 8, 11, 16, 20, 24, 32
+ };
+
+ private static final int[] channels = {
+ 1, 2, 3, 4, 5
+ };
+
+ private static final AudioFileFormat.Type[] types = {
+ WAVE, AU, AIFF, AIFC, SND,
+ new AudioFileFormat.Type("TestName", "TestExt")
+ };
+
+ private static final int FRAME_LENGTH = 10;
+
+ static {
+ for (final int sampleSize : sampleBits) {
+ for (final int channel : channels) {
+ for (final AudioFormat.Encoding enc : encodings) {
+ final int frameSize = ((sampleSize + 7) / 8) * channel;
+ formats.add(new AudioFormat(enc, 44100, sampleSize, channel,
+ frameSize, 44100, true));
+ formats.add(new AudioFormat(enc, 44100, sampleSize, channel,
+ frameSize, 44100, false));
+ }
+ }
+ }
+ }
+
+ public static void main(final String[] args) {
+ for (final FormatConversionProvider fcp : load(
+ FormatConversionProvider.class)) {
+ System.out.println("fcp = " + fcp);
+ for (final AudioFormat from : formats) {
+ for (final AudioFormat to : formats) {
+ testAfterConversion(fcp, to, getStream(from, true));
+ }
+ }
+ }
+
+ for (final AudioFileWriter afw : load(AudioFileWriter.class)) {
+ System.out.println("afw = " + afw);
+ for (final AudioFileFormat.Type type : types) {
+ for (final AudioFormat from : formats) {
+ testAfterSaveToStream(afw, type, getStream(from, true));
+ }
+ }
+ }
+
+ for (final AudioFileWriter afw : load(AudioFileWriter.class)) {
+ System.out.println("afw = " + afw);
+ for (final AudioFileFormat.Type type : types) {
+ for (final AudioFormat from : formats) {
+ testAfterSaveToFile(afw, type, getStream(from, true));
+ }
+ }
+ }
+
+ for (final AudioFileWriter afw : load(AudioFileWriter.class)) {
+ System.out.println("afw = " + afw);
+ for (final AudioFileFormat.Type type : types) {
+ for (final AudioFormat from : formats) {
+ testAfterSaveToFile(afw, type, getStream(from, false));
+ }
+ }
+ }
+ }
+
+ /**
+ * Verifies the frame length after the stream was saved/read to/from
+ * stream.
+ */
+ private static void testAfterSaveToStream(final AudioFileWriter afw,
+ final AudioFileFormat.Type type,
+ final AudioInputStream ais) {
+ try {
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ afw.write(ais, type, out);
+ final InputStream input = new ByteArrayInputStream(
+ out.toByteArray());
+ validate(AudioSystem.getAudioInputStream(input).getFrameLength());
+ } catch (IllegalArgumentException | UnsupportedAudioFileException
+ | IOException ignored) {
+ }
+ }
+
+ /**
+ * Verifies the frame length after the stream was saved/read to/from file.
+ */
+ private static void testAfterSaveToFile(final AudioFileWriter afw,
+ final AudioFileFormat.Type type,
+ AudioInputStream ais) {
+ try {
+ final File temp = File.createTempFile("sound", ".tmp");
+ temp.deleteOnExit();
+ afw.write(ais, type, temp);
+ ais = AudioSystem.getAudioInputStream(temp);
+ final long frameLength = ais.getFrameLength();
+ ais.close();
+ temp.delete();
+ validate(frameLength);
+ } catch (IllegalArgumentException | UnsupportedAudioFileException
+ | IOException ignored) {
+ }
+ }
+
+ /**
+ * Verifies the frame length after the stream was converted to other
+ * stream.
+ *
+ * @see FormatConversionProvider#getAudioInputStream(AudioFormat,
+ * AudioInputStream)
+ */
+ private static void testAfterConversion(final FormatConversionProvider fcp,
+ final AudioFormat to,
+ final AudioInputStream ais) {
+ if (fcp.isConversionSupported(to, ais.getFormat())) {
+ validate(fcp.getAudioInputStream(to, ais).getFrameLength());
+ }
+ }
+
+ /**
+ * Throws an exception if the frameLength is specified and is not equal to
+ * the gold value.
+ */
+ private static void validate(final long frameLength) {
+ if (frameLength != FRAME_LENGTH) {
+ System.err.println("Expected: " + FRAME_LENGTH);
+ System.err.println("Actual: " + frameLength);
+ throw new RuntimeException();
+ }
+ }
+
+ private static AudioInputStream getStream(final AudioFormat format,
+ final boolean frameLength) {
+ final int dataSize = FRAME_LENGTH * format.getFrameSize();
+ final InputStream in = new ByteArrayInputStream(new byte[dataSize]);
+ if (frameLength) {
+ return new AudioInputStream(in, format, FRAME_LENGTH);
+ } else {
+ return new AudioInputStream(in, format, NOT_SPECIFIED);
+ }
+ }
+}
From d466ce4948fd6b5099da43453621a1437a40fc18 Mon Sep 17 00:00:00 2001
From: Felix Yang
Date: Fri, 19 Feb 2016 17:12:14 +0800
Subject: [PATCH 045/311] 8150229: aarch64: pipeline class for several
instructions is not set correctly
Aarch64: c2 fix pipeline class for several instructions.
Reviewed-by: aph
---
hotspot/src/cpu/aarch64/vm/aarch64.ad | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad
index 8483c709564..acc65080e2f 100644
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad
@@ -13281,7 +13281,7 @@ instruct MoveF2I_reg_reg(iRegINoSp dst, vRegF src) %{
__ fmovs($dst$$Register, as_FloatRegister($src$$reg));
%}
- ins_pipe(pipe_class_memory);
+ ins_pipe(fp_f2i);
%}
@@ -13299,7 +13299,7 @@ instruct MoveI2F_reg_reg(vRegF dst, iRegI src) %{
__ fmovs(as_FloatRegister($dst$$reg), $src$$Register);
%}
- ins_pipe(pipe_class_memory);
+ ins_pipe(fp_i2f);
%}
@@ -13317,7 +13317,7 @@ instruct MoveD2L_reg_reg(iRegLNoSp dst, vRegD src) %{
__ fmovd($dst$$Register, as_FloatRegister($src$$reg));
%}
- ins_pipe(pipe_class_memory);
+ ins_pipe(fp_d2l);
%}
@@ -13335,7 +13335,7 @@ instruct MoveL2D_reg_reg(vRegD dst, iRegL src) %{
__ fmovd(as_FloatRegister($dst$$reg), $src$$Register);
%}
- ins_pipe(pipe_class_memory);
+ ins_pipe(fp_l2d);
%}
@@ -16502,7 +16502,7 @@ instruct vsll2I(vecD dst, vecD src, vecX shift) %{
as_FloatRegister($src$$reg),
as_FloatRegister($shift$$reg));
%}
- ins_pipe(vshift64_imm);
+ ins_pipe(vshift64);
%}
instruct vsll4I(vecX dst, vecX src, vecX shift) %{
@@ -16516,7 +16516,7 @@ instruct vsll4I(vecX dst, vecX src, vecX shift) %{
as_FloatRegister($src$$reg),
as_FloatRegister($shift$$reg));
%}
- ins_pipe(vshift128_imm);
+ ins_pipe(vshift128);
%}
instruct vsrl2I(vecD dst, vecD src, vecX shift) %{
@@ -16529,7 +16529,7 @@ instruct vsrl2I(vecD dst, vecD src, vecX shift) %{
as_FloatRegister($src$$reg),
as_FloatRegister($shift$$reg));
%}
- ins_pipe(vshift64_imm);
+ ins_pipe(vshift64);
%}
instruct vsrl4I(vecX dst, vecX src, vecX shift) %{
@@ -16542,7 +16542,7 @@ instruct vsrl4I(vecX dst, vecX src, vecX shift) %{
as_FloatRegister($src$$reg),
as_FloatRegister($shift$$reg));
%}
- ins_pipe(vshift128_imm);
+ ins_pipe(vshift128);
%}
instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{
@@ -16660,7 +16660,7 @@ instruct vsll2L_imm(vecX dst, vecX src, immI shift) %{
as_FloatRegister($src$$reg),
(int)$shift$$constant & 63);
%}
- ins_pipe(vshift128);
+ ins_pipe(vshift128_imm);
%}
instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{
From 04d2edfca3b5f342a694c2bb88bfea7266c88dfc Mon Sep 17 00:00:00 2001
From: Dmitry Dmitriev
Date: Fri, 19 Feb 2016 13:24:21 +0300
Subject: [PATCH 046/311] 8146187: Print develop and nonproduct flags by
-XX:+PrintFlags* options in debug build
Reviewed-by: gtriantafill, gziemski, dholmes
---
hotspot/src/share/vm/runtime/globals.cpp | 28 ++++++-------------
.../TestOptionsWithRanges.java | 2 +-
2 files changed, 10 insertions(+), 20 deletions(-)
diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp
index 638b15eaffc..ade6900975b 100644
--- a/hotspot/src/share/vm/runtime/globals.cpp
+++ b/hotspot/src/share/vm/runtime/globals.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -403,25 +403,20 @@ void Flag::print_on(outputStream* st, bool withComments, bool printRanges) {
st->cr();
} else if (!is_bool() && !is_ccstr()) {
+ st->print("%9s %-50s ", _type, _name);
- if (printRanges) {
+ CommandLineFlagRangeList::print(_name, st, true);
- st->print("%9s %-50s ", _type, _name);
-
- CommandLineFlagRangeList::print(_name, st, true);
-
- st->print(" %-20s", " ");
- print_kind(st);
+ st->print(" %-20s", " ");
+ print_kind(st);
#ifndef PRODUCT
- if (withComments) {
- st->print("%s", _doc);
- }
+ if (withComments) {
+ st->print("%s", _doc);
+ }
#endif
- st->cr();
-
- }
+ st->cr();
}
}
@@ -1255,8 +1250,6 @@ void CommandLineFlags::verify() {
#endif // PRODUCT
-#define ONLY_PRINT_PRODUCT_FLAGS
-
void CommandLineFlags::printFlags(outputStream* out, bool withComments, bool printRanges) {
// Print the flags sorted by name
// note: this method is called before the thread structure is in place
@@ -1281,9 +1274,6 @@ void CommandLineFlags::printFlags(outputStream* out, bool withComments, bool pri
for (size_t i = 0; i < length; i++) {
if (array[i]->is_unlocked()) {
-#ifdef ONLY_PRINT_PRODUCT_FLAGS
- if (!array[i]->is_notproduct() && !array[i]->is_develop())
-#endif // ONLY_PRINT_PRODUCT_FLAGS
array[i]->print_on(out, withComments, printRanges);
}
}
diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java
index 24f7ad70a53..27ccc5d546b 100644
--- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java
+++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java
@@ -75,7 +75,7 @@ public class TestOptionsWithRanges {
int failedTests;
List allOptions;
- allOptionsAsMap = JVMOptionsUtils.getOptionsWithRangeAsMap();
+ allOptionsAsMap = JVMOptionsUtils.getOptionsWithRangeAsMap(origin -> (!(origin.contains("develop") || origin.contains("notproduct"))));
/* Shared flags can cause JVM to exit with error code 2 */
setAllowedExitCodes("SharedReadWriteSize", 2);
From f1812d9e9f20aeb50403eb0ab51ec4d2adc3d414 Mon Sep 17 00:00:00 2001
From: Magnus Ihse Bursie
Date: Fri, 19 Feb 2016 14:04:20 +0100
Subject: [PATCH 047/311] 8150201: Restore missing -g flags to files with
OPT_CFLAGS/per-file
Reviewed-by: dholmes, erikj
---
hotspot/make/bsd/makefiles/amd64.make | 10 +++++++++-
hotspot/make/bsd/makefiles/gcc.make | 9 ++++++++-
hotspot/make/linux/makefiles/amd64.make | 10 +++++++++-
hotspot/make/linux/makefiles/gcc.make | 12 +++++++++++-
hotspot/make/linux/makefiles/i486.make | 10 +++++++++-
hotspot/make/solaris/makefiles/amd64.make | 10 +++++++++-
hotspot/make/solaris/makefiles/product.make | 18 +++++++++++++++++-
hotspot/make/solaris/makefiles/sparcWorks.make | 11 +++++++++++
8 files changed, 83 insertions(+), 7 deletions(-)
diff --git a/hotspot/make/bsd/makefiles/amd64.make b/hotspot/make/bsd/makefiles/amd64.make
index ecdac17ee3a..6512375259e 100644
--- a/hotspot/make/bsd/makefiles/amd64.make
+++ b/hotspot/make/bsd/makefiles/amd64.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2016, 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,3 +37,11 @@ ifndef USE_SUNCC
endif
OPT_CFLAGS/compactingPermGenGen.o = -O1
+
+# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides
+# of OPT_CFLAGS. Restore it here.
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ OPT_CFLAGS/sharedRuntimeTrig.o += -g
+ OPT_CFLAGS/sharedRuntimeTrans.o += -g
+ OPT_CFLAGS/compactingPermGenGen.o += -g
+endif
diff --git a/hotspot/make/bsd/makefiles/gcc.make b/hotspot/make/bsd/makefiles/gcc.make
index 05a07052963..1bf6521a892 100644
--- a/hotspot/make/bsd/makefiles/gcc.make
+++ b/hotspot/make/bsd/makefiles/gcc.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2016, 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
@@ -330,6 +330,13 @@ ifeq ($(USE_CLANG), true)
), 1)
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
OPT_CFLAGS/unsafe.o += -O1
+
+ # The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides
+ # of OPT_CFLAGS. Restore it here.
+ ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ OPT_CFLAGS/loopTransform.o += -g
+ OPT_CFLAGS/unsafe.o += -g
+ endif
else
$(error "Update compiler workarounds for Clang $(CC_VER_MAJOR).$(CC_VER_MINOR)")
endif
diff --git a/hotspot/make/linux/makefiles/amd64.make b/hotspot/make/linux/makefiles/amd64.make
index 2b77dbab605..c98a5827820 100644
--- a/hotspot/make/linux/makefiles/amd64.make
+++ b/hotspot/make/linux/makefiles/amd64.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2016, 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
@@ -32,3 +32,11 @@ CFLAGS += -DVM_LITTLE_ENDIAN
CFLAGS += -D_LP64=1
OPT_CFLAGS/compactingPermGenGen.o = -O1
+
+# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides
+# of OPT_CFLAGS. Restore it here.
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ OPT_CFLAGS/sharedRuntimeTrig.o += -g
+ OPT_CFLAGS/sharedRuntimeTrans.o += -g
+ OPT_CFLAGS/compactingPermGenGen.o += -g
+endif
diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make
index c8ee95d932b..a2e5c6c03b6 100644
--- a/hotspot/make/linux/makefiles/gcc.make
+++ b/hotspot/make/linux/makefiles/gcc.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2016, 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
@@ -265,6 +265,11 @@ ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \&
# GCC >= 4.3
# Gcc 4.1.2 does not support this flag, nor does it have problems compiling the file.
OPT_CFLAGS/vmStructs.o += -fno-var-tracking-assignments
+ # The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides
+ # of OPT_CFLAGS. Restore it here.
+ ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ OPT_CFLAGS/vmStructs.o += -g
+ endif
endif
# The gcc compiler segv's on ia64 when compiling bytecodeInterpreter.cpp
@@ -277,6 +282,11 @@ endif
ifeq ($(USE_CLANG), true)
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 2), 1)
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
+ # The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides
+ # of OPT_CFLAGS. Restore it here.
+ ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ OPT_CFLAGS/loopTransform.o += -g
+ endif
endif
else
# Do not allow GCC 4.1.1
diff --git a/hotspot/make/linux/makefiles/i486.make b/hotspot/make/linux/makefiles/i486.make
index 86e825d3e9d..a1adda6477c 100644
--- a/hotspot/make/linux/makefiles/i486.make
+++ b/hotspot/make/linux/makefiles/i486.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2016, 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
@@ -32,3 +32,11 @@ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT)
CFLAGS += -DVM_LITTLE_ENDIAN
OPT_CFLAGS/compactingPermGenGen.o = -O1
+
+# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides
+# of OPT_CFLAGS. Restore it here.
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ OPT_CFLAGS/sharedRuntimeTrig.o += -g
+ OPT_CFLAGS/sharedRuntimeTrans.o += -g
+ OPT_CFLAGS/compactingPermGenGen.o += -g
+endif
diff --git a/hotspot/make/solaris/makefiles/amd64.make b/hotspot/make/solaris/makefiles/amd64.make
index f88d743fe7c..7b1bdf3d8b3 100644
--- a/hotspot/make/solaris/makefiles/amd64.make
+++ b/hotspot/make/solaris/makefiles/amd64.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2004, 2016, 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,6 +34,14 @@ ifeq ("${Platform_compiler}", "sparcWorks")
OPT_CFLAGS/generateOptoStub.o = -xO2
# Temporary util SS12u1 C++ compiler is fixed
OPT_CFLAGS/c1_LinearScan.o = -xO2
+
+# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides
+# of OPT_CFLAGS. Restore it here.
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ OPT_CFLAGS/generateOptoStub.o += -g0 -xs
+ OPT_CFLAGS/LinearScan.o += -g0 -xs
+endif
+
else
ifeq ("${Platform_compiler}", "gcc")
diff --git a/hotspot/make/solaris/makefiles/product.make b/hotspot/make/solaris/makefiles/product.make
index 7f378b17d95..b36159fdcc8 100644
--- a/hotspot/make/solaris/makefiles/product.make
+++ b/hotspot/make/solaris/makefiles/product.make
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2016, 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,11 +35,21 @@ OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@))
# for this method for now. (fix this when dtrace bug 6258412 is fixed)
ifndef USE_GCC
OPT_CFLAGS/ciEnv.o = $(OPT_CFLAGS) -xinline=no%__1cFciEnvbFpost_compiled_method_load_event6MpnHnmethod__v_
+# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides
+# of OPT_CFLAGS. Restore it here.
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ OPT_CFLAGS/ciEnv.o += -g0 -xs
+endif
endif
# Need extra inlining to get oop_ps_push_contents functions to perform well enough.
ifndef USE_GCC
OPT_CFLAGS/psPromotionManager.o = $(OPT_CFLAGS) -W2,-Ainline:inc=1000
+# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides
+# of OPT_CFLAGS. Restore it here.
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ OPT_CFLAGS/psPromotionManager.o += -g0 -xs
+endif
endif
# (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files)
@@ -55,6 +65,12 @@ endif # COMPILER_REV_NUMERIC == 510
ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1)
# dtrace cannot handle tail call optimization (6672627, 6693876)
OPT_CFLAGS/jni.o = $(OPT_CFLAGS/DEFAULT) $(OPT_CCFLAGS/NO_TAIL_CALL_OPT)
+# The -g0 -xs flag is added to OPT_CFLAGS in sparcWorks.make, but lost in case of
+# per-file overrides of OPT_CFLAGS. Restore it here. This is mainly needed
+# to provide a good baseline to compare the new build against.
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ OPT_CFLAGS/jni.o += -g0 -xs
+endif
endif # COMPILER_NUMERIC_REV >= 509
# Workaround SS11 bug 6345274 (all platforms) (Fixed in SS11 patch and SS12)
diff --git a/hotspot/make/solaris/makefiles/sparcWorks.make b/hotspot/make/solaris/makefiles/sparcWorks.make
index cbd902ef0fe..5c66b2f3d20 100644
--- a/hotspot/make/solaris/makefiles/sparcWorks.make
+++ b/hotspot/make/solaris/makefiles/sparcWorks.make
@@ -158,9 +158,20 @@ OPT_CFLAGS/NO_TAIL_CALL_OPT = -Wu,-O~yz
OPT_CCFLAGS/NO_TAIL_CALL_OPT = -Qoption ube -O~yz
OPT_CFLAGS/stubGenerator_x86_32.o = $(OPT_CFLAGS) -xspace
OPT_CFLAGS/stubGenerator_x86_64.o = $(OPT_CFLAGS) -xspace
+# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides
+# of OPT_CFLAGS. Restore it here.
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ OPT_CFLAGS/stubGenerator_x86_32.o += -g0 -xs
+ OPT_CFLAGS/stubGenerator_x86_64.o += -g0 -xs
+endif
endif # Platform_arch == x86
ifeq ("${Platform_arch}", "sparc")
OPT_CFLAGS/stubGenerator_sparc.o = $(OPT_CFLAGS) -xspace
+# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides
+# of OPT_CFLAGS. Restore it here.
+ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
+ OPT_CFLAGS/stubGenerator_sparc.o += -g0 -xs
+endif
endif
endif # COMPILER_REV_NUMERIC >= 509
From 390295caf1b807dc9b32eafcef372be62171d84f Mon Sep 17 00:00:00 2001
From: Kim Barrett
Date: Fri, 19 Feb 2016 15:14:59 -0500
Subject: [PATCH 048/311] 8150134: Simplify concurrent refinement thread
deactivation
Remove explicit deactivation and use green stop_at value.
Reviewed-by: jmasa, tschatzl
---
.../vm/gc/g1/concurrentG1RefineThread.cpp | 29 +++++++------------
1 file changed, 10 insertions(+), 19 deletions(-)
diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp
index df9de0ee337..cefcab3065b 100644
--- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp
+++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp
@@ -89,8 +89,6 @@ bool ConcurrentG1RefineThread::is_active() {
void ConcurrentG1RefineThread::activate() {
MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
if (!is_primary()) {
- log_debug(gc, refine)("G1-Refine-activated worker %d, on threshold %d, current %d",
- _worker_id, _threshold, JavaThread::dirty_card_queue_set().completed_buffers_num());
set_active(true);
} else {
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
@@ -102,8 +100,6 @@ void ConcurrentG1RefineThread::activate() {
void ConcurrentG1RefineThread::deactivate() {
MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
if (!is_primary()) {
- log_debug(gc, refine)("G1-Refine-deactivated worker %d, off threshold %d, current %d",
- _worker_id, _deactivation_threshold, JavaThread::dirty_card_queue_set().completed_buffers_num());
set_active(false);
} else {
DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
@@ -130,9 +126,12 @@ void ConcurrentG1RefineThread::run_service() {
break;
}
+ DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+ log_debug(gc, refine)("Activated %d, on threshold: %d, current: %d",
+ _worker_id, _threshold, dcqs.completed_buffers_num());
+
{
SuspendibleThreadSetJoiner sts_join;
- DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
do {
int curr_buffer_num = (int)dcqs.completed_buffers_num();
@@ -142,27 +141,19 @@ void ConcurrentG1RefineThread::run_service() {
dcqs.set_completed_queue_padding(0);
}
- if (!is_primary() && curr_buffer_num <= _deactivation_threshold) {
- // If the number of the buffer has fallen below our threshold
- // we should deactivate. The predecessor will reactivate this
- // thread should the number of the buffers cross the threshold again.
- deactivate();
- break;
- }
-
// Check if we need to activate the next thread.
if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
_next->activate();
}
} while (dcqs.apply_closure_to_completed_buffer(_refine_closure,
_worker_id + _worker_id_offset,
- cg1r()->green_zone(),
+ _deactivation_threshold,
false /* during_pause */));
- // We can exit the loop above while being active if there was a yield request.
- if (is_active()) {
- deactivate();
- }
+ deactivate();
+ log_debug(gc, refine)("Deactivated %d, off threshold: %d, current: %d",
+ _worker_id, _deactivation_threshold,
+ dcqs.completed_buffers_num());
}
if (os::supports_vtime()) {
@@ -172,7 +163,7 @@ void ConcurrentG1RefineThread::run_service() {
}
}
- log_debug(gc, refine)("G1-Refine-stop");
+ log_debug(gc, refine)("Stopping %d", _worker_id);
}
void ConcurrentG1RefineThread::stop() {
From 5d04cc8e61dee4a8621863f1eae550ea963ac24a Mon Sep 17 00:00:00 2001
From: Christoph Langer
Date: Fri, 19 Feb 2016 10:44:54 +0100
Subject: [PATCH 049/311] 8150232: AIX cleanup: Integrate changes of 7178026
and others
Reviewed-by: simonis
---
hotspot/src/os/aix/vm/attachListener_aix.cpp | 12 ++--
hotspot/src/os/aix/vm/perfMemory_aix.cpp | 59 +++++++++++---------
2 files changed, 39 insertions(+), 32 deletions(-)
diff --git a/hotspot/src/os/aix/vm/attachListener_aix.cpp b/hotspot/src/os/aix/vm/attachListener_aix.cpp
index cb56efc26f7..4e69822008a 100644
--- a/hotspot/src/os/aix/vm/attachListener_aix.cpp
+++ b/hotspot/src/os/aix/vm/attachListener_aix.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016 SAP SE. 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
@@ -225,7 +225,7 @@ int AixAttachListener::init() {
// We must call bind with the actual socketaddr length. This is obligatory for AS400.
int res = ::bind(listener, (struct sockaddr*)&addr, SUN_LEN(&addr));
if (res == -1) {
- RESTARTABLE(::close(listener), res);
+ ::close(listener);
return -1;
}
@@ -238,7 +238,7 @@ int AixAttachListener::init() {
}
}
if (res == -1) {
- RESTARTABLE(::close(listener), res);
+ ::close(listener);
::unlink(initial_path);
return -1;
}
@@ -400,7 +400,7 @@ AixAttachOperation* AixAttachListener::dequeue() {
AixAttachOperation* op = read_request(s);
if (op == NULL) {
int res;
- RESTARTABLE(::close(s), res);
+ ::close(s);
continue;
} else {
return op;
@@ -452,7 +452,7 @@ void AixAttachOperation::complete(jint result, bufferedStream* st) {
}
// done
- RESTARTABLE(::close(this->socket()), rc);
+ ::close(this->socket());
// were we externally suspended while we were waiting?
thread->check_and_wait_while_suspended();
diff --git a/hotspot/src/os/aix/vm/perfMemory_aix.cpp b/hotspot/src/os/aix/vm/perfMemory_aix.cpp
index 2604a03dae8..c2e7c0e4e90 100644
--- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp
+++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2013 SAP SE. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016 SAP SE. 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
@@ -121,7 +121,7 @@ static void save_memory_to_file(char* addr, size_t size) {
addr += result;
}
- RESTARTABLE(::close(fd), result);
+ result = ::close(fd);
if (PrintMiscellaneous && Verbose) {
if (result == OS_ERR) {
warning("Could not close %s: %s\n", destfile, strerror(errno));
@@ -299,10 +299,13 @@ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool u
bool create;
int error;
int fd;
+ int result;
create = false;
- if (lstat(path, &orig_st) != 0) {
+ RESTARTABLE(::lstat(path, &orig_st), result);
+
+ if (result == OS_ERR) {
if (errno == ENOENT && (oflag & O_CREAT) != 0) {
// File doesn't exist, but_we want to create it, add O_EXCL flag
// to make sure no-one creates it (or a symlink) before us
@@ -316,7 +319,7 @@ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool u
return OS_ERR;
}
} else {
- // Lstat success, check if existing file is a link.
+ // lstat success, check if existing file is a link.
if ((orig_st.st_mode & S_IFMT) == S_IFLNK) {
// File is a symlink.
errno = ELOOP;
@@ -325,9 +328,9 @@ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool u
}
if (use_mode == true) {
- fd = open(path, oflag, mode);
+ RESTARTABLE(::open(path, oflag, mode), fd);
} else {
- fd = open(path, oflag);
+ RESTARTABLE(::open(path, oflag), fd);
}
if (fd == OS_ERR) {
@@ -336,7 +339,8 @@ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool u
// Can't do inode checks on before/after if we created the file.
if (create == false) {
- if (fstat(fd, &new_st) != 0) {
+ RESTARTABLE(::fstat(fd, &new_st), result);
+ if (result == OS_ERR) {
// Keep errno from fstat, in case close also fails.
error = errno;
::close(fd);
@@ -384,7 +388,7 @@ static DIR *open_directory_secure(const char* dirname) {
RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
#else
// workaround (jdk6 coding)
- RESTARTABLE(::open_o_nofollow(dirname, O_RDONLY), result);
+ result = open_o_nofollow(dirname, O_RDONLY);
#endif
if (result == OS_ERR) {
@@ -888,7 +892,7 @@ static int create_sharedmem_resources(const char* dirname, const char* filename,
RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
#else
// workaround function (jdk6 code)
- RESTARTABLE(::open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE), result);
+ result = open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE);
#endif
if (result == OS_ERR) {
@@ -931,7 +935,7 @@ static int create_sharedmem_resources(const char* dirname, const char* filename,
if (PrintMiscellaneous && Verbose) {
warning("could not set shared memory file size: %s\n", strerror(errno));
}
- RESTARTABLE(::close(fd), result);
+ ::close(fd);
return -1;
}
@@ -951,7 +955,7 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) {
#ifdef O_NOFOLLOW
RESTARTABLE(::open(filename, oflags), result);
#else
- RESTARTABLE(::open_o_nofollow(filename, oflags), result);
+ open_o_nofollow(filename, oflags);
#endif
if (result == OS_ERR) {
@@ -1006,8 +1010,7 @@ static char* mmap_create_shared(size_t size) {
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
-
- // Get the short filename.
+ // get the short filename.
char* short_filename = strrchr(filename, '/');
if (short_filename == NULL) {
short_filename = filename;
@@ -1033,9 +1036,7 @@ static char* mmap_create_shared(size_t size) {
mapAddress = (char*)::mmap((char*)0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- // attempt to close the file - restart it if it was interrupted,
- // but ignore other failures
- RESTARTABLE(::close(fd), result);
+ result = ::close(fd);
assert(result != OS_ERR, "could not close file");
if (mapAddress == MAP_FAILED) {
@@ -1142,7 +1143,6 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
-
// No O_NOFOLLOW defined at buildtime, and it is not documented for open.
#ifdef O_NOFOLLOW
file_flags = O_RDONLY | O_NOFOLLOW;
@@ -1205,21 +1205,28 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
FREE_C_HEAP_ARRAY(char, filename);
// open the shared memory file for the give vmid
- fd = open_sharedmem_file(rfilename, file_flags, CHECK);
- assert(fd != OS_ERR, "unexpected value");
+ fd = open_sharedmem_file(rfilename, file_flags, THREAD);
+
+ if (fd == OS_ERR) {
+ return;
+ }
+
+ if (HAS_PENDING_EXCEPTION) {
+ ::close(fd);
+ return;
+ }
if (*sizep == 0) {
size = sharedmem_filesize(fd, CHECK);
- assert(size != 0, "unexpected size");
} else {
size = *sizep;
}
+ assert(size > 0, "unexpected size <= 0");
+
mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0);
- // attempt to close the file - restart if it gets interrupted,
- // but ignore other failures
- RESTARTABLE(::close(fd), result);
+ result = ::close(fd);
assert(result != OS_ERR, "could not close file");
if (mapAddress == MAP_FAILED) {
@@ -1230,7 +1237,7 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
"Could not map PerfMemory");
}
- // It does not go through os api, the operation has to record from here.
+ // it does not go through os api, the operation has to record from here.
MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
*addr = mapAddress;
@@ -1238,7 +1245,7 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
if (PerfTraceMemOps) {
tty->print("mapped " SIZE_FORMAT " bytes for vmid %d at "
- INTPTR_FORMAT "\n", size, vmid, (void*)mapAddress);
+ INTPTR_FORMAT "\n", size, vmid, p2i((void*)mapAddress));
}
}
From 516438f368d53be93596baaf2d1f35d26770934c Mon Sep 17 00:00:00 2001
From: Konstantin Shefov
Date: Sat, 20 Feb 2016 11:43:13 +0300
Subject: [PATCH 050/311] 8141616: Add new methods to the java Whitebox API
Reviewed-by: kvn, dpochepk
---
test/lib/sun/hotspot/WhiteBox.java | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java
index 6b7863ad938..9964831c3c9 100644
--- a/test/lib/sun/hotspot/WhiteBox.java
+++ b/test/lib/sun/hotspot/WhiteBox.java
@@ -119,6 +119,28 @@ public class WhiteBox {
return getConstantPool0(aClass);
}
+ private native int getConstantPoolCacheIndexTag0();
+ public int getConstantPoolCacheIndexTag() {
+ return getConstantPoolCacheIndexTag0();
+ }
+
+ private native int getConstantPoolCacheLength0(Class> aClass);
+ public int getConstantPoolCacheLength(Class> aClass) {
+ Objects.requireNonNull(aClass);
+ return getConstantPoolCacheLength0(aClass);
+ }
+
+ private native int remapInstructionOperandFromCPCache0(Class> aClass, int index);
+ public int remapInstructionOperandFromCPCache(Class> aClass, int index) {
+ Objects.requireNonNull(aClass);
+ return remapInstructionOperandFromCPCache0(aClass, index);
+ }
+
+ private native int encodeConstantPoolIndyIndex0(int index);
+ public int encodeConstantPoolIndyIndex(int index) {
+ return encodeConstantPoolIndyIndex0(index);
+ }
+
// JVMTI
private native void addToBootstrapClassLoaderSearch0(String segment);
public void addToBootstrapClassLoaderSearch(String segment){
From 694727f144557feb6d568d1777b21d61488dfc68 Mon Sep 17 00:00:00 2001
From: Pavel Punegov
Date: Tue, 1 Mar 2016 20:17:27 +0300
Subject: [PATCH 051/311] 8148563:
compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java timesout
Decrease amount of directives and threads
Reviewed-by: neliasso
---
.../jcmd/StressAddJcmdBase.java | 79 ++++++++++++-------
.../jcmd/StressAddMultiThreadedTest.java | 29 +++----
.../jcmd/StressAddSequentiallyTest.java | 55 -------------
3 files changed, 63 insertions(+), 100 deletions(-)
delete mode 100644 hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java
diff --git a/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java b/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java
index 1da46dedf00..580d9b614ff 100644
--- a/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java
+++ b/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java
@@ -32,74 +32,99 @@ import jdk.test.lib.TimeLimitedRunner;
import jdk.test.lib.Utils;
import pool.PoolHelper;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
public abstract class StressAddJcmdBase {
private static final int DIRECTIVES_AMOUNT = Integer.getInteger(
"compiler.compilercontrol.jcmd.StressAddJcmdBase.directivesAmount",
- 1000);
- private static final int DIRECTIVE_FILES = Integer.getInteger(
- "compiler.compilercontrol.jcmd.StressAddJcmdBase.directiveFiles",
- 5);
+ 200);
+ private static final int TIMEOUT = Integer.getInteger(
+ "compiler.compilercontrol.jcmd.StressAddJcmdBase.timeout",
+ 30);
private static final List DESCRIPTORS = new PoolHelper()
.getAllMethods().stream()
.map(pair -> AbstractTestBase
.getValidMethodDescriptor(pair.first))
.collect(Collectors.toList());
+ private static final String DIRECTIVE_FILE = "directives.json";
+ private static final List VM_OPTIONS = new ArrayList<>();
+ private static final Random RANDOM = Utils.getRandomInstance();
+
+ static {
+ VM_OPTIONS.add("-Xmixed");
+ VM_OPTIONS.add("-XX:+UnlockDiagnosticVMOptions");
+ VM_OPTIONS.add("-XX:+LogCompilation");
+ VM_OPTIONS.add("-XX:CompilerDirectivesLimit=1001");
+ }
/**
* Performs test
*/
public void test() {
- List commands = prepareCommands();
- Executor executor = new TimeLimitedExecutor(commands);
+ HugeDirectiveUtil.createHugeFile(DESCRIPTORS, DIRECTIVE_FILE,
+ DIRECTIVES_AMOUNT);
+ Executor executor = new TimeLimitedExecutor();
List outputAnalyzers = executor.execute();
outputAnalyzers.get(0).shouldHaveExitValue(0);
}
/**
- * Makes connection to the test VM
+ * Makes connection to the test VM and performs a diagnostic command
*
- * @param pid a pid of the VM under test
- * @param commands a list of jcmd commands to be executed
+ * @param pid a pid of the VM under test
* @return true if the test should continue invocation of this method
*/
- protected abstract boolean makeConnection(int pid, List commands);
+ protected abstract boolean makeConnection(int pid);
/**
* Finish test executions
*/
protected void finish() { }
- private List prepareCommands() {
- String[] files = new String[DIRECTIVE_FILES];
- for (int i = 0; i < DIRECTIVE_FILES; i++) {
- files[i] = "directives" + i + ".json";
- HugeDirectiveUtil.createHugeFile(DESCRIPTORS, files[i],
- DIRECTIVES_AMOUNT);
+ protected String nextCommand() {
+ int i = RANDOM.nextInt(JcmdCommand.values().length);
+ JcmdCommand jcmdCommand = JcmdCommand.values()[i];
+ switch (jcmdCommand) {
+ case ADD:
+ return jcmdCommand.command + " " + DIRECTIVE_FILE;
+ case PRINT:
+ case CLEAR:
+ case REMOVE:
+ return jcmdCommand.command;
+ default:
+ throw new Error("TESTBUG: incorrect command: " + jcmdCommand);
+ }
+ }
+
+ private enum JcmdCommand {
+ ADD("Compiler.directives_add"),
+ PRINT("Compiler.directives_print"),
+ CLEAR("Compiler.directives_clear"),
+ REMOVE("Compiler.directives_remove");
+
+ public final String command;
+
+ JcmdCommand(String command) {
+ this.command = command;
}
- return Stream.of(files)
- .map(file -> "Compiler.directives_add " + file)
- .collect(Collectors.toList());
}
private class TimeLimitedExecutor extends Executor {
- private final List jcmdCommands;
-
- public TimeLimitedExecutor(List jcmdCommands) {
+ public TimeLimitedExecutor() {
/* There are no need to check the state */
- super(true, null, null, jcmdCommands);
- this.jcmdCommands = jcmdCommands;
+ super(true, VM_OPTIONS, null, null);
}
@Override
protected OutputAnalyzer[] executeJCMD(int pid) {
TimeLimitedRunner runner = new TimeLimitedRunner(
- Utils.DEFAULT_TEST_TIMEOUT,
+ TimeUnit.SECONDS.toMillis(TIMEOUT),
Utils.TIMEOUT_FACTOR,
- () -> makeConnection(pid, jcmdCommands));
+ () -> makeConnection(pid));
try {
runner.call();
} catch (Exception e) {
diff --git a/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java b/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java
index b2ad879351a..5bf1464fd55 100644
--- a/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java
+++ b/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java
@@ -27,21 +27,19 @@
* @summary Tests jcmd to be able to add a lot of huge directive files with
* parallel executed jcmds until timeout has reached
* @library /testlibrary /test/lib /compiler/testlibrary ../share /
- * @ignore 8148563
* @build compiler.compilercontrol.jcmd.StressAddMultiThreadedTest
* pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
* compiler.testlibrary.CompilerUtils
* compiler.compilercontrol.share.actions.*
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm/timeout=360 compiler.compilercontrol.jcmd.StressAddMultiThreadedTest
+ * @run driver compiler.compilercontrol.jcmd.StressAddMultiThreadedTest
*/
package compiler.compilercontrol.jcmd;
import jdk.test.lib.dcmd.PidJcmdExecutor;
-import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
@@ -49,16 +47,15 @@ import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class StressAddMultiThreadedTest extends StressAddJcmdBase {
- private static final int THREADS;
+ private static final int THREADS = Integer.getInteger(
+ "compiler.compilercontrol.jcmd.StressAddMultiThreadedTest.threads",
+ 5);
+ private volatile int commands = Integer.getInteger(
+ "compiler.compilercontrol.jcmd.StressAddMultiThreadedTest.commands",
+ 20);
private final BlockingQueue queue;
private final ExecutorService executor;
- static {
- THREADS = Runtime.getRuntime().availableProcessors()
- * Integer.getInteger("compiler.compilercontrol.jcmd" +
- ".StressAddMultiThreadedTest.threadFactor", 10);
- }
-
public StressAddMultiThreadedTest() {
queue = new ArrayBlockingQueue<>(THREADS);
executor = new ThreadPoolExecutor(THREADS, THREADS, 100,
@@ -71,14 +68,10 @@ public class StressAddMultiThreadedTest extends StressAddJcmdBase {
}
@Override
- protected boolean makeConnection(int pid, List commands) {
- commands.forEach(command -> {
- if (!executor.isShutdown()) {
- executor.submit(() -> new PidJcmdExecutor(String.valueOf(pid))
- .execute(command));
- }
- });
- return !executor.isShutdown();
+ protected boolean makeConnection(int pid) {
+ executor.submit(() -> new PidJcmdExecutor(String.valueOf(pid))
+ .execute(nextCommand()));
+ return (--commands != 0);
}
@Override
diff --git a/hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java b/hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java
deleted file mode 100644
index f8509128321..00000000000
--- a/hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * @test
- * @bug 8137167
- * @summary Tests jcmd to be able to add a lot of huge directives
- * @library /testlibrary /test/lib /compiler/testlibrary ../share /
- * @build compiler.compilercontrol.jcmd.StressAddSequentiallyTest
- * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox
- * compiler.testlibrary.CompilerUtils
- * compiler.compilercontrol.share.actions.*
- * @run main ClassFileInstaller sun.hotspot.WhiteBox
- * sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm/timeout=300 compiler.compilercontrol.jcmd.StressAddSequentiallyTest
- */
-
-package compiler.compilercontrol.jcmd;
-
-import jdk.test.lib.dcmd.PidJcmdExecutor;
-
-import java.util.List;
-
-public class StressAddSequentiallyTest extends StressAddJcmdBase {
- public static void main(String[] args) {
- new StressAddSequentiallyTest().test();
- }
-
- @Override
- protected boolean makeConnection(int pid, List commands) {
- commands.forEach(command -> new PidJcmdExecutor(String.valueOf(pid))
- .execute(command));
- return true;
- }
-}
From c40e7bc21fe5a0fb0f6e441b5da92a67add4b0b5 Mon Sep 17 00:00:00 2001
From: Mikael Vidstedt
Date: Thu, 3 Mar 2016 09:33:30 -0800
Subject: [PATCH 052/311] 8149159: Clean up Unsafe
Reviewed-by: jrose, kvn, stsmirno, chegar, aph, psandoz, redestad, twisti
---
hotspot/src/share/vm/classfile/vmSymbols.hpp | 3 +-
hotspot/src/share/vm/oops/method.cpp | 75 --
hotspot/src/share/vm/opto/library_call.cpp | 6 +-
hotspot/src/share/vm/prims/nativeLookup.cpp | 4 +-
hotspot/src/share/vm/prims/unsafe.cpp | 961 +++++++-----------
hotspot/src/share/vm/prims/unsafe.hpp | 39 +
.../src/share/vm/runtime/interfaceSupport.hpp | 8 +-
hotspot/src/share/vm/shark/sharkBuilder.cpp | 2 +-
.../intrinsics/IntrinsicDisabledTest.java | 8 +-
9 files changed, 428 insertions(+), 678 deletions(-)
create mode 100644 hotspot/src/share/vm/prims/unsafe.hpp
diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp
index 4cce6873268..fcc4ad8be25 100644
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp
@@ -1035,14 +1035,13 @@
do_name( updateByteBuffer_A_name, "updateByteBuffer") \
\
/* support for Unsafe */ \
- do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \
do_class(jdk_internal_misc_Unsafe, "jdk/internal/misc/Unsafe") \
\
do_intrinsic(_allocateInstance, jdk_internal_misc_Unsafe, allocateInstance_name, allocateInstance_signature, F_RN) \
do_name( allocateInstance_name, "allocateInstance") \
do_signature(allocateInstance_signature, "(Ljava/lang/Class;)Ljava/lang/Object;") \
do_intrinsic(_copyMemory, jdk_internal_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \
- do_name( copyMemory_name, "copyMemory") \
+ do_name( copyMemory_name, "copyMemory0") \
do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \
do_intrinsic(_loadFence, jdk_internal_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \
do_name( loadFence_name, "loadFence") \
diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp
index 7620ea9f985..8c6029e6fef 100644
--- a/hotspot/src/share/vm/oops/method.cpp
+++ b/hotspot/src/share/vm/oops/method.cpp
@@ -1338,73 +1338,6 @@ vmSymbols::SID Method::klass_id_for_intrinsics(const Klass* holder) {
return vmSymbols::find_sid(klass_name);
}
-static bool is_unsafe_alias(vmSymbols::SID name_id) {
- // All 70 intrinsic candidate methods from sun.misc.Unsafe in 1.8.
- // Some have the same method name but different signature, e.g.
- // getByte(long), getByte(Object,long)
- switch (name_id) {
- case vmSymbols::VM_SYMBOL_ENUM_NAME(allocateInstance_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(copyMemory_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(loadFence_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(storeFence_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(fullFence_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getObject_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getBoolean_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getByte_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getShort_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getChar_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getInt_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getLong_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getFloat_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getDouble_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putObject_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putBoolean_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putByte_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putShort_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putChar_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putInt_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putLong_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putFloat_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putDouble_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getObjectVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getBooleanVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getByteVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getShortVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getCharVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getIntVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getLongVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getFloatVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getDoubleVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putObjectVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putBooleanVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putByteVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putShortVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putCharVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putIntVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putLongVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putFloatVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putDoubleVolatile_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getAddress_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putAddress_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapObject_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapLong_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapInt_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedObject_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedLong_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedInt_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndAddInt_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndAddLong_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetInt_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetLong_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetObject_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(park_name):
- case vmSymbols::VM_SYMBOL_ENUM_NAME(unpark_name):
- return true;
- }
-
- return false;
-}
-
void Method::init_intrinsic_id() {
assert(_intrinsic_id == vmIntrinsics::_none, "do this just once");
const uintptr_t max_id_uint = right_n_bits((int)(sizeof(_intrinsic_id) * BitsPerByte));
@@ -1457,14 +1390,6 @@ void Method::init_intrinsic_id() {
if (is_static() != MethodHandles::is_signature_polymorphic_static(id))
id = vmIntrinsics::_none;
break;
-
- case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_misc_Unsafe):
- // Map sun.misc.Unsafe to jdk.internal.misc.Unsafe
- if (!is_unsafe_alias(name_id)) break;
- // pretend it is the corresponding method in the internal Unsafe class:
- klass_id = vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_internal_misc_Unsafe);
- id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags);
- break;
}
if (id != vmIntrinsics::_none) {
diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp
index 240321cb231..4ecca52fb3d 100644
--- a/hotspot/src/share/vm/opto/library_call.cpp
+++ b/hotspot/src/share/vm/opto/library_call.cpp
@@ -48,6 +48,7 @@
#include "opto/runtime.hpp"
#include "opto/subnode.hpp"
#include "prims/nativeLookup.hpp"
+#include "prims/unsafe.hpp"
#include "runtime/sharedRuntime.hpp"
#include "trace/traceMacros.hpp"
@@ -2306,9 +2307,6 @@ void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset,
}
-// Interpret Unsafe.fieldOffset cookies correctly:
-extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset);
-
const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type, bool is_native_ptr) {
// Attempt to infer a sharper value type from the offset and base type.
ciKlass* sharpened_klass = NULL;
@@ -4466,7 +4464,7 @@ bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) {
}
//----------------------inline_unsafe_copyMemory-------------------------
-// public native void Unsafe.copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes);
+// public native void Unsafe.copyMemory0(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes);
bool LibraryCallKit::inline_unsafe_copyMemory() {
if (callee()->is_static()) return false; // caller must have the capability!
null_check_receiver(); // null-check receiver
diff --git a/hotspot/src/share/vm/prims/nativeLookup.cpp b/hotspot/src/share/vm/prims/nativeLookup.cpp
index c89e4f10c32..51525c26f2d 100644
--- a/hotspot/src/share/vm/prims/nativeLookup.cpp
+++ b/hotspot/src/share/vm/prims/nativeLookup.cpp
@@ -35,6 +35,7 @@
#include "oops/symbol.hpp"
#include "prims/jvm_misc.hpp"
#include "prims/nativeLookup.hpp"
+#include "prims/unsafe.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
@@ -107,8 +108,6 @@ char* NativeLookup::long_jni_name(const methodHandle& method) {
}
extern "C" {
- void JNICALL JVM_RegisterJDKInternalMiscUnsafeMethods(JNIEnv *env, jclass unsafecls);
- void JNICALL JVM_RegisterSunMiscUnsafeMethods(JNIEnv *env, jclass unsafecls);
void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls);
void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass);
void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass);
@@ -123,7 +122,6 @@ extern "C" {
static JNINativeMethod lookup_special_native_methods[] = {
{ CC"Java_jdk_internal_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterJDKInternalMiscUnsafeMethods) },
- { CC"Java_sun_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterSunMiscUnsafeMethods) },
{ CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) },
{ CC"Java_jdk_internal_perf_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) },
{ CC"Java_sun_hotspot_WhiteBox_registerNatives", NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) },
diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp
index cdd4334e229..dc60ebfd208 100644
--- a/hotspot/src/share/vm/prims/unsafe.cpp
+++ b/hotspot/src/share/vm/prims/unsafe.cpp
@@ -30,6 +30,7 @@
#include "oops/oop.inline.hpp"
#include "prims/jni.h"
#include "prims/jvm.h"
+#include "prims/unsafe.hpp"
#include "runtime/atomic.inline.hpp"
#include "runtime/globals.hpp"
#include "runtime/interfaceSupport.hpp"
@@ -45,8 +46,8 @@
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
#endif // INCLUDE_ALL_GCS
-/*
- * Implementation of class Unsafe
+/**
+ * Implementation of the jdk.internal.misc.Unsafe class
*/
@@ -56,25 +57,15 @@
#define UNSAFE_ENTRY(result_type, header) \
- JVM_ENTRY(result_type, header)
+ JVM_ENTRY(static result_type, header)
-// Can't use UNSAFE_LEAF because it has the signature of a straight
-// call into the runtime (just like JVM_LEAF, funny that) but it's
-// called like a Java Native and thus the wrapper built for it passes
-// arguments like a JNI call. It expects those arguments to be popped
-// from the stack on Intel like all good JNI args are, and adjusts the
-// stack according. Since the JVM_LEAF call expects no extra
-// arguments the stack isn't popped in the C code, is pushed by the
-// wrapper and we get sick.
-//#define UNSAFE_LEAF(result_type, header) \
-// JVM_LEAF(result_type, header)
+#define UNSAFE_LEAF(result_type, header) \
+ JVM_LEAF(static result_type, header)
#define UNSAFE_END JVM_END
-#define UnsafeWrapper(arg) /*nothing, for the present*/
-
-inline void* addr_from_java(jlong addr) {
+static inline void* addr_from_java(jlong addr) {
// This assert fails in a variety of ways on 32-bit systems.
// It is impossible to predict whether native code that converts
// pointers to longs will sign-extend or zero-extend the addresses.
@@ -82,7 +73,7 @@ inline void* addr_from_java(jlong addr) {
return (void*)(uintptr_t)addr;
}
-inline jlong addr_to_java(void* p) {
+static inline jlong addr_to_java(void* p) {
assert(p == (void*)(uintptr_t)p, "must not be odd high bits");
return (uintptr_t)p;
}
@@ -98,24 +89,17 @@ inline jlong addr_to_java(void* p) {
// through conversion functions when going between the VM and the Unsafe API.
// The conversion functions just happen to be no-ops at present.
-inline jlong field_offset_to_byte_offset(jlong field_offset) {
+static inline jlong field_offset_to_byte_offset(jlong field_offset) {
return field_offset;
}
-inline jlong field_offset_from_byte_offset(jlong byte_offset) {
+static inline jlong field_offset_from_byte_offset(jlong byte_offset) {
return byte_offset;
}
-inline jint invocation_key_from_method_slot(jint slot) {
- return slot;
-}
-
-inline jint invocation_key_to_method_slot(jint key) {
- return key;
-}
-
-inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
+static inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
jlong byte_offset = field_offset_to_byte_offset(field_offset);
+
#ifdef ASSERT
if (p != NULL) {
assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset");
@@ -128,10 +112,12 @@ inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
assert(byte_offset < p_size, "Unsafe access: offset " INT64_FORMAT " > object's size " INT64_FORMAT, byte_offset, p_size);
}
#endif
- if (sizeof(char*) == sizeof(jint)) // (this constant folds!)
+
+ if (sizeof(char*) == sizeof(jint)) { // (this constant folds!)
return (address)p + (jint) byte_offset;
- else
+ } else {
return (address)p + byte_offset;
+ }
}
// Externally callable versions:
@@ -142,12 +128,6 @@ jlong Unsafe_field_offset_to_byte_offset(jlong field_offset) {
jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
return byte_offset;
}
-jint Unsafe_invocation_key_from_method_slot(jint slot) {
- return invocation_key_from_method_slot(slot);
-}
-jint Unsafe_invocation_key_to_method_slot(jint key) {
- return invocation_key_to_method_slot(key);
-}
///// Data in the Java heap.
@@ -177,17 +157,19 @@ jint Unsafe_invocation_key_to_method_slot(jint key) {
// These functions allow a null base pointer with an arbitrary address.
// But if the base pointer is non-null, the offset should make some sense.
// That is, it should be in the range [0, MAX_OBJECT_SIZE].
-UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
- UnsafeWrapper("Unsafe_GetObject");
+UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
oop p = JNIHandles::resolve(obj);
oop v;
+
if (UseCompressedOops) {
narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset);
v = oopDesc::decode_heap_oop(n);
} else {
v = *(oop*)index_oop_from_field_offset_long(p, offset);
}
+
jobject ret = JNIHandles::make_local(env, v);
+
#if INCLUDE_ALL_GCS
// We could be accessing the referent field in a reference
// object. If G1 is enabled then we need to register non-null
@@ -212,67 +194,71 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj,
}
}
#endif // INCLUDE_ALL_GCS
- return ret;
-UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
- UnsafeWrapper("Unsafe_SetObject");
+ return ret;
+} UNSAFE_END
+
+UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
oop x = JNIHandles::resolve(x_h);
oop p = JNIHandles::resolve(obj);
+
if (UseCompressedOops) {
oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
} else {
oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
}
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
- UnsafeWrapper("Unsafe_GetObjectVolatile");
+UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
oop p = JNIHandles::resolve(obj);
void* addr = index_oop_from_field_offset_long(p, offset);
+
volatile oop v;
+
if (UseCompressedOops) {
volatile narrowOop n = *(volatile narrowOop*) addr;
(void)const_cast(v = oopDesc::decode_heap_oop(n));
} else {
(void)const_cast(v = *(volatile oop*) addr);
}
+
OrderAccess::acquire();
return JNIHandles::make_local(env, v);
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
- UnsafeWrapper("Unsafe_SetObjectVolatile");
+UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
oop x = JNIHandles::resolve(x_h);
oop p = JNIHandles::resolve(obj);
void* addr = index_oop_from_field_offset_long(p, offset);
OrderAccess::release();
+
if (UseCompressedOops) {
oop_store((narrowOop*)addr, x);
} else {
oop_store((oop*)addr, x);
}
+
OrderAccess::fence();
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr))
- UnsafeWrapper("Unsafe_GetUncompressedObject");
+UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
oop v = *(oop*) (address) addr;
+
return JNIHandles::make_local(env, v);
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(jclass, Unsafe_GetJavaMirror(JNIEnv *env, jobject unsafe, jlong metaspace_klass))
- UnsafeWrapper("Unsafe_GetJavaMirror");
+UNSAFE_ENTRY(jclass, Unsafe_GetJavaMirror(JNIEnv *env, jobject unsafe, jlong metaspace_klass)) {
Klass* klass = (Klass*) (address) metaspace_klass;
- return (jclass) JNIHandles::make_local(klass->java_mirror());
-UNSAFE_END
-UNSAFE_ENTRY(jlong, Unsafe_GetKlassPointer(JNIEnv *env, jobject unsafe, jobject obj))
- UnsafeWrapper("Unsafe_GetKlassPointer");
+ return (jclass) JNIHandles::make_local(klass->java_mirror());
+} UNSAFE_END
+
+UNSAFE_ENTRY(jlong, Unsafe_GetKlassPointer(JNIEnv *env, jobject unsafe, jobject obj)) {
oop o = JNIHandles::resolve(obj);
jlong klass = (jlong) (address) o->klass();
+
return klass;
-UNSAFE_END
+} UNSAFE_END
#ifndef SUPPORTS_NATIVE_CX8
@@ -303,83 +289,54 @@ UNSAFE_END
// the address of the field _after_ we have acquired the lock, else the object may have
// been moved by the GC
-UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
- UnsafeWrapper("Unsafe_GetLongVolatile");
- {
- if (VM_Version::supports_cx8()) {
- GET_FIELD_VOLATILE(obj, offset, jlong, v);
- return v;
- }
- else {
- Handle p (THREAD, JNIHandles::resolve(obj));
- jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
- MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
- jlong value = Atomic::load(addr);
- return value;
- }
+UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
+ if (VM_Version::supports_cx8()) {
+ GET_FIELD_VOLATILE(obj, offset, jlong, v);
+ return v;
+ } else {
+ Handle p (THREAD, JNIHandles::resolve(obj));
+ jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
+ MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+ jlong value = Atomic::load(addr);
+ return value;
}
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_SetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x))
- UnsafeWrapper("Unsafe_SetLongVolatile");
- {
- if (VM_Version::supports_cx8()) {
- SET_FIELD_VOLATILE(obj, offset, jlong, x);
- }
- else {
- Handle p (THREAD, JNIHandles::resolve(obj));
- jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
- MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
- Atomic::store(x, addr);
- }
+UNSAFE_ENTRY(void, Unsafe_SetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) {
+ if (VM_Version::supports_cx8()) {
+ SET_FIELD_VOLATILE(obj, offset, jlong, x);
+ } else {
+ Handle p (THREAD, JNIHandles::resolve(obj));
+ jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
+ MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+ Atomic::store(x, addr);
}
-UNSAFE_END
+} UNSAFE_END
#endif // not SUPPORTS_NATIVE_CX8
-UNSAFE_ENTRY(jboolean, Unsafe_isBigEndian0(JNIEnv *env, jobject unsafe))
- UnsafeWrapper("Unsafe_IsBigEndian0");
- {
+UNSAFE_LEAF(jboolean, Unsafe_isBigEndian0(JNIEnv *env, jobject unsafe)) {
#ifdef VM_LITTLE_ENDIAN
- return false;
+ return false;
#else
- return true;
+ return true;
#endif
- }
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe))
- UnsafeWrapper("Unsafe_UnalignedAccess0");
- {
- return UseUnalignedAccesses;
- }
-UNSAFE_END
+UNSAFE_LEAF(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) {
+ return UseUnalignedAccesses;
+} UNSAFE_END
-#define DEFINE_GETSETOOP(jboolean, Boolean) \
+#define DEFINE_GETSETOOP(java_type, Type) \
\
-UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset)) \
- UnsafeWrapper("Unsafe_Get"#Boolean); \
- if (obj == NULL) THROW_0(vmSymbols::java_lang_NullPointerException()); \
- GET_FIELD(obj, offset, jboolean, v); \
+UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
+ GET_FIELD(obj, offset, java_type, v); \
return v; \
-UNSAFE_END \
+} UNSAFE_END \
\
-UNSAFE_ENTRY(void, Unsafe_Set##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset, jboolean x)) \
- UnsafeWrapper("Unsafe_Set"#Boolean); \
- if (obj == NULL) THROW(vmSymbols::java_lang_NullPointerException()); \
- SET_FIELD(obj, offset, jboolean, x); \
-UNSAFE_END \
- \
-UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) \
- UnsafeWrapper("Unsafe_Get"#Boolean); \
- GET_FIELD(obj, offset, jboolean, v); \
- return v; \
-UNSAFE_END \
- \
-UNSAFE_ENTRY(void, Unsafe_Set##Boolean(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jboolean x)) \
- UnsafeWrapper("Unsafe_Set"#Boolean); \
- SET_FIELD(obj, offset, jboolean, x); \
-UNSAFE_END \
+UNSAFE_ENTRY(void, Unsafe_Set##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
+ SET_FIELD(obj, offset, java_type, x); \
+} UNSAFE_END \
\
// END DEFINE_GETSETOOP.
@@ -394,18 +351,16 @@ DEFINE_GETSETOOP(jdouble, Double);
#undef DEFINE_GETSETOOP
-#define DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) \
+#define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \
\
-UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) \
- UnsafeWrapper("Unsafe_Get"#Boolean); \
- GET_FIELD_VOLATILE(obj, offset, jboolean, v); \
+UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \
+ GET_FIELD_VOLATILE(obj, offset, java_type, v); \
return v; \
-UNSAFE_END \
+} UNSAFE_END \
\
-UNSAFE_ENTRY(void, Unsafe_Set##Boolean##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jboolean x)) \
- UnsafeWrapper("Unsafe_Set"#Boolean); \
- SET_FIELD_VOLATILE(obj, offset, jboolean, x); \
-UNSAFE_END \
+UNSAFE_ENTRY(void, Unsafe_Set##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \
+ SET_FIELD_VOLATILE(obj, offset, java_type, x); \
+} UNSAFE_END \
\
// END DEFINE_GETSETOOP_VOLATILE.
@@ -425,59 +380,53 @@ DEFINE_GETSETOOP_VOLATILE(jlong, Long);
// The non-intrinsified versions of setOrdered just use setVolatile
-UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x))
- UnsafeWrapper("Unsafe_SetOrderedInt");
+UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) {
SET_FIELD_VOLATILE(obj, offset, jint, x);
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
- UnsafeWrapper("Unsafe_SetOrderedObject");
+UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
oop x = JNIHandles::resolve(x_h);
oop p = JNIHandles::resolve(obj);
void* addr = index_oop_from_field_offset_long(p, offset);
OrderAccess::release();
+
if (UseCompressedOops) {
oop_store((narrowOop*)addr, x);
} else {
oop_store((oop*)addr, x);
}
- OrderAccess::fence();
-UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x))
- UnsafeWrapper("Unsafe_SetOrderedLong");
+ OrderAccess::fence();
+} UNSAFE_END
+
+UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) {
#ifdef SUPPORTS_NATIVE_CX8
SET_FIELD_VOLATILE(obj, offset, jlong, x);
#else
+
// Keep old code for platforms which may not have atomic long (8 bytes) instructions
- {
- if (VM_Version::supports_cx8()) {
- SET_FIELD_VOLATILE(obj, offset, jlong, x);
- }
- else {
- Handle p (THREAD, JNIHandles::resolve(obj));
- jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
- MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
- Atomic::store(x, addr);
- }
+ if (VM_Version::supports_cx8()) {
+ SET_FIELD_VOLATILE(obj, offset, jlong, x);
+ } else {
+ Handle p(THREAD, JNIHandles::resolve(obj));
+ jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
+ MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+ Atomic::store(x, addr);
}
#endif
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe))
- UnsafeWrapper("Unsafe_LoadFence");
+UNSAFE_LEAF(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe)) {
OrderAccess::acquire();
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_StoreFence(JNIEnv *env, jobject unsafe))
- UnsafeWrapper("Unsafe_StoreFence");
+UNSAFE_LEAF(void, Unsafe_StoreFence(JNIEnv *env, jobject unsafe)) {
OrderAccess::release();
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_FullFence(JNIEnv *env, jobject unsafe))
- UnsafeWrapper("Unsafe_FullFence");
+UNSAFE_LEAF(void, Unsafe_FullFence(JNIEnv *env, jobject unsafe)) {
OrderAccess::fence();
-UNSAFE_END
+} UNSAFE_END
////// Data in the C heap.
@@ -486,24 +435,22 @@ UNSAFE_END
//
#define DEFINE_GETSETNATIVE(java_type, Type, native_type) \
\
-UNSAFE_ENTRY(java_type, Unsafe_GetNative##Type(JNIEnv *env, jobject unsafe, jlong addr)) \
- UnsafeWrapper("Unsafe_GetNative"#Type); \
+UNSAFE_ENTRY(java_type, Unsafe_GetNative##Type(JNIEnv *env, jobject unsafe, jlong addr)) { \
void* p = addr_from_java(addr); \
JavaThread* t = JavaThread::current(); \
t->set_doing_unsafe_access(true); \
java_type x = *(volatile native_type*)p; \
t->set_doing_unsafe_access(false); \
return x; \
-UNSAFE_END \
+} UNSAFE_END \
\
-UNSAFE_ENTRY(void, Unsafe_SetNative##Type(JNIEnv *env, jobject unsafe, jlong addr, java_type x)) \
- UnsafeWrapper("Unsafe_SetNative"#Type); \
+UNSAFE_ENTRY(void, Unsafe_SetNative##Type(JNIEnv *env, jobject unsafe, jlong addr, java_type x)) { \
JavaThread* t = JavaThread::current(); \
t->set_doing_unsafe_access(true); \
void* p = addr_from_java(addr); \
*(volatile native_type*)p = x; \
t->set_doing_unsafe_access(false); \
-UNSAFE_END \
+} UNSAFE_END \
\
// END DEFINE_GETSETNATIVE.
@@ -517,8 +464,7 @@ DEFINE_GETSETNATIVE(jdouble, Double, double);
#undef DEFINE_GETSETNATIVE
-UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr))
- UnsafeWrapper("Unsafe_GetNativeLong");
+UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr)) {
JavaThread* t = JavaThread::current();
// We do it this way to avoid problems with access to heap using 64
// bit loads, as jlong in heap could be not 64-bit aligned, and on
@@ -526,7 +472,8 @@ UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr
t->set_doing_unsafe_access(true);
void* p = addr_from_java(addr);
jlong x;
- if (((intptr_t)p & 7) == 0) {
+
+ if (is_ptr_aligned(p, sizeof(jlong)) == 0) {
// jlong is aligned, do a volatile access
x = *(volatile jlong*)p;
} else {
@@ -535,17 +482,19 @@ UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr
acc.words[1] = ((volatile jint*)p)[1];
x = acc.long_value;
}
- t->set_doing_unsafe_access(false);
- return x;
-UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr, jlong x))
- UnsafeWrapper("Unsafe_SetNativeLong");
+ t->set_doing_unsafe_access(false);
+
+ return x;
+} UNSAFE_END
+
+UNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) {
JavaThread* t = JavaThread::current();
// see comment for Unsafe_GetNativeLong
t->set_doing_unsafe_access(true);
void* p = addr_from_java(addr);
- if (((intptr_t)p & 7) == 0) {
+
+ if (is_ptr_aligned(p, sizeof(jlong))) {
// jlong is aligned, do a volatile access
*(volatile jlong*)p = x;
} else {
@@ -554,119 +503,81 @@ UNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr,
((volatile jint*)p)[0] = acc.words[0];
((volatile jint*)p)[1] = acc.words[1];
}
+
t->set_doing_unsafe_access(false);
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(jlong, Unsafe_GetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr))
- UnsafeWrapper("Unsafe_GetNativeAddress");
+UNSAFE_LEAF(jlong, Unsafe_GetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr)) {
void* p = addr_from_java(addr);
- return addr_to_java(*(void**)p);
-UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_SetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr, jlong x))
- UnsafeWrapper("Unsafe_SetNativeAddress");
+ return addr_to_java(*(void**)p);
+} UNSAFE_END
+
+UNSAFE_LEAF(void, Unsafe_SetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) {
void* p = addr_from_java(addr);
*(void**)p = addr_from_java(x);
-UNSAFE_END
+} UNSAFE_END
////// Allocation requests
-UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls))
- UnsafeWrapper("Unsafe_AllocateInstance");
- {
- ThreadToNativeFromVM ttnfv(thread);
- return env->AllocObject(cls);
- }
-UNSAFE_END
+UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls)) {
+ ThreadToNativeFromVM ttnfv(thread);
+ return env->AllocObject(cls);
+} UNSAFE_END
-UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory(JNIEnv *env, jobject unsafe, jlong size))
- UnsafeWrapper("Unsafe_AllocateMemory");
+UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory0(JNIEnv *env, jobject unsafe, jlong size)) {
size_t sz = (size_t)size;
- if (sz != (julong)size || size < 0) {
- THROW_0(vmSymbols::java_lang_IllegalArgumentException());
- }
- if (sz == 0) {
- return 0;
- }
+
sz = round_to(sz, HeapWordSize);
void* x = os::malloc(sz, mtInternal);
- if (x == NULL) {
- THROW_0(vmSymbols::java_lang_OutOfMemoryError());
- }
- //Copy::fill_to_words((HeapWord*)x, sz / HeapWordSize);
- return addr_to_java(x);
-UNSAFE_END
-UNSAFE_ENTRY(jlong, Unsafe_ReallocateMemory(JNIEnv *env, jobject unsafe, jlong addr, jlong size))
- UnsafeWrapper("Unsafe_ReallocateMemory");
+ return addr_to_java(x);
+} UNSAFE_END
+
+UNSAFE_ENTRY(jlong, Unsafe_ReallocateMemory0(JNIEnv *env, jobject unsafe, jlong addr, jlong size)) {
void* p = addr_from_java(addr);
size_t sz = (size_t)size;
- if (sz != (julong)size || size < 0) {
- THROW_0(vmSymbols::java_lang_IllegalArgumentException());
- }
- if (sz == 0) {
- os::free(p);
- return 0;
- }
sz = round_to(sz, HeapWordSize);
- void* x = (p == NULL) ? os::malloc(sz, mtInternal) : os::realloc(p, sz, mtInternal);
- if (x == NULL) {
- THROW_0(vmSymbols::java_lang_OutOfMemoryError());
- }
+
+ void* x = os::realloc(p, sz, mtInternal);
+
return addr_to_java(x);
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_FreeMemory(JNIEnv *env, jobject unsafe, jlong addr))
- UnsafeWrapper("Unsafe_FreeMemory");
+UNSAFE_ENTRY(void, Unsafe_FreeMemory0(JNIEnv *env, jobject unsafe, jlong addr)) {
void* p = addr_from_java(addr);
- if (p == NULL) {
- return;
- }
- os::free(p);
-UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_SetMemory(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong size, jbyte value))
- UnsafeWrapper("Unsafe_SetMemory");
+ os::free(p);
+} UNSAFE_END
+
+UNSAFE_ENTRY(void, Unsafe_SetMemory0(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong size, jbyte value)) {
size_t sz = (size_t)size;
- if (sz != (julong)size || size < 0) {
- THROW(vmSymbols::java_lang_IllegalArgumentException());
- }
+
oop base = JNIHandles::resolve(obj);
void* p = index_oop_from_field_offset_long(base, offset);
- Copy::fill_to_memory_atomic(p, sz, value);
-UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_CopyMemory(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size))
- UnsafeWrapper("Unsafe_CopyMemory");
- if (size == 0) {
- return;
- }
+ Copy::fill_to_memory_atomic(p, sz, value);
+} UNSAFE_END
+
+UNSAFE_ENTRY(void, Unsafe_CopyMemory0(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size)) {
size_t sz = (size_t)size;
- if (sz != (julong)size || size < 0) {
- THROW(vmSymbols::java_lang_IllegalArgumentException());
- }
+
oop srcp = JNIHandles::resolve(srcObj);
oop dstp = JNIHandles::resolve(dstObj);
- if (dstp != NULL && !dstp->is_typeArray()) {
- // NYI: This works only for non-oop arrays at present.
- // Generalizing it would be reasonable, but requires card marking.
- // Also, autoboxing a Long from 0L in copyMemory(x,y, 0L,z, n) would be bad.
- THROW(vmSymbols::java_lang_IllegalArgumentException());
- }
+
void* src = index_oop_from_field_offset_long(srcp, srcOffset);
void* dst = index_oop_from_field_offset_long(dstp, dstOffset);
+
Copy::conjoint_memory_atomic(src, dst, sz);
-UNSAFE_END
+} UNSAFE_END
// This function is a leaf since if the source and destination are both in native memory
// the copy may potentially be very large, and we don't want to disable GC if we can avoid it.
// If either source or destination (or both) are on the heap, the function will enter VM using
// JVM_ENTRY_FROM_LEAF
-JVM_LEAF(void, Unsafe_CopySwapMemory0(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size, jlong elemSize)) {
- UnsafeWrapper("Unsafe_CopySwapMemory0");
-
+UNSAFE_LEAF(void, Unsafe_CopySwapMemory0(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size, jlong elemSize)) {
size_t sz = (size_t)size;
size_t esz = (size_t)elemSize;
@@ -689,32 +600,24 @@ JVM_LEAF(void, Unsafe_CopySwapMemory0(JNIEnv *env, jobject unsafe, jobject srcOb
Copy::conjoint_swap(src, dst, sz, esz);
} JVM_END
}
-} JVM_END
+} UNSAFE_END
////// Random queries
-// See comment at file start about UNSAFE_LEAF
-//UNSAFE_LEAF(jint, Unsafe_AddressSize())
-UNSAFE_ENTRY(jint, Unsafe_AddressSize(JNIEnv *env, jobject unsafe))
- UnsafeWrapper("Unsafe_AddressSize");
+UNSAFE_LEAF(jint, Unsafe_AddressSize0(JNIEnv *env, jobject unsafe)) {
return sizeof(void*);
-UNSAFE_END
+} UNSAFE_END
-// See comment at file start about UNSAFE_LEAF
-//UNSAFE_LEAF(jint, Unsafe_PageSize())
-UNSAFE_ENTRY(jint, Unsafe_PageSize(JNIEnv *env, jobject unsafe))
- UnsafeWrapper("Unsafe_PageSize");
+UNSAFE_LEAF(jint, Unsafe_PageSize()) {
return os::vm_page_size();
-UNSAFE_END
+} UNSAFE_END
-jint find_field_offset(jobject field, int must_be_static, TRAPS) {
- if (field == NULL) {
- THROW_0(vmSymbols::java_lang_NullPointerException());
- }
+static jint find_field_offset(jobject field, int must_be_static, TRAPS) {
+ assert(field != NULL, "field must not be NULL");
oop reflected = JNIHandles::resolve_non_null(field);
oop mirror = java_lang_reflect_Field::clazz(reflected);
- Klass* k = java_lang_Class::as_Klass(mirror);
+ Klass* k = java_lang_Class::as_Klass(mirror);
int slot = java_lang_reflect_Field::slot(reflected);
int modifiers = java_lang_reflect_Field::modifiers(reflected);
@@ -729,18 +632,17 @@ jint find_field_offset(jobject field, int must_be_static, TRAPS) {
return field_offset_from_byte_offset(offset);
}
-UNSAFE_ENTRY(jlong, Unsafe_ObjectFieldOffset(JNIEnv *env, jobject unsafe, jobject field))
- UnsafeWrapper("Unsafe_ObjectFieldOffset");
+UNSAFE_ENTRY(jlong, Unsafe_ObjectFieldOffset0(JNIEnv *env, jobject unsafe, jobject field)) {
return find_field_offset(field, 0, THREAD);
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(jlong, Unsafe_StaticFieldOffset(JNIEnv *env, jobject unsafe, jobject field))
- UnsafeWrapper("Unsafe_StaticFieldOffset");
+UNSAFE_ENTRY(jlong, Unsafe_StaticFieldOffset0(JNIEnv *env, jobject unsafe, jobject field)) {
return find_field_offset(field, 1, THREAD);
-UNSAFE_END
+} UNSAFE_END
+
+UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBase0(JNIEnv *env, jobject unsafe, jobject field)) {
+ assert(field != NULL, "field must not be NULL");
-UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromField(JNIEnv *env, jobject unsafe, jobject field))
- UnsafeWrapper("Unsafe_StaticFieldBase");
// Note: In this VM implementation, a field address is always a short
// offset from the base of a a klass metaobject. Thus, the full dynamic
// range of the return type is never used. However, some implementations
@@ -749,8 +651,6 @@ UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromField(JNIEnv *env, jobject unsaf
// large. In that last case, this function would return NULL, since
// the address would operate alone, without any base pointer.
- if (field == NULL) THROW_0(vmSymbols::java_lang_NullPointerException());
-
oop reflected = JNIHandles::resolve_non_null(field);
oop mirror = java_lang_reflect_Field::clazz(reflected);
int modifiers = java_lang_reflect_Field::modifiers(reflected);
@@ -760,13 +660,11 @@ UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromField(JNIEnv *env, jobject unsaf
}
return JNIHandles::make_local(env, mirror);
-UNSAFE_END
+} UNSAFE_END
+
+UNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized0(JNIEnv *env, jobject unsafe, jobject clazz)) {
+ assert(clazz != NULL, "clazz must not be NULL");
-UNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized(JNIEnv *env, jobject unsafe, jobject clazz)) {
- UnsafeWrapper("Unsafe_EnsureClassInitialized");
- if (clazz == NULL) {
- THROW(vmSymbols::java_lang_NullPointerException());
- }
oop mirror = JNIHandles::resolve_non_null(clazz);
Klass* klass = java_lang_Class::as_Klass(mirror);
@@ -777,26 +675,26 @@ UNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized(JNIEnv *env, jobject unsafe, jo
}
UNSAFE_END
-UNSAFE_ENTRY(jboolean, Unsafe_ShouldBeInitialized(JNIEnv *env, jobject unsafe, jobject clazz)) {
- UnsafeWrapper("Unsafe_ShouldBeInitialized");
- if (clazz == NULL) {
- THROW_(vmSymbols::java_lang_NullPointerException(), false);
- }
+UNSAFE_ENTRY(jboolean, Unsafe_ShouldBeInitialized0(JNIEnv *env, jobject unsafe, jobject clazz)) {
+ assert(clazz != NULL, "clazz must not be NULL");
+
oop mirror = JNIHandles::resolve_non_null(clazz);
Klass* klass = java_lang_Class::as_Klass(mirror);
+
if (klass != NULL && klass->should_be_initialized()) {
return true;
}
+
return false;
}
UNSAFE_END
-static void getBaseAndScale(int& base, int& scale, jclass acls, TRAPS) {
- if (acls == NULL) {
- THROW(vmSymbols::java_lang_NullPointerException());
- }
- oop mirror = JNIHandles::resolve_non_null(acls);
- Klass* k = java_lang_Class::as_Klass(mirror);
+static void getBaseAndScale(int& base, int& scale, jclass clazz, TRAPS) {
+ assert(clazz != NULL, "clazz must not be NULL");
+
+ oop mirror = JNIHandles::resolve_non_null(clazz);
+ Klass* k = java_lang_Class::as_Klass(mirror);
+
if (k == NULL || !k->is_array_klass()) {
THROW(vmSymbols::java_lang_InvalidClassException());
} else if (k->is_objArray_klass()) {
@@ -812,18 +710,18 @@ static void getBaseAndScale(int& base, int& scale, jclass acls, TRAPS) {
}
}
-UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset(JNIEnv *env, jobject unsafe, jclass acls))
- UnsafeWrapper("Unsafe_ArrayBaseOffset");
+UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset0(JNIEnv *env, jobject unsafe, jclass clazz)) {
int base = 0, scale = 0;
- getBaseAndScale(base, scale, acls, CHECK_0);
+ getBaseAndScale(base, scale, clazz, CHECK_0);
+
return field_offset_from_byte_offset(base);
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale(JNIEnv *env, jobject unsafe, jclass acls))
- UnsafeWrapper("Unsafe_ArrayIndexScale");
+UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) {
int base = 0, scale = 0;
- getBaseAndScale(base, scale, acls, CHECK_0);
+ getBaseAndScale(base, scale, clazz, CHECK_0);
+
// This VM packs both fields and array elements down to the byte.
// But watch out: If this changes, so that array references for
// a given primitive type (say, T_BOOLEAN) use different memory units
@@ -839,100 +737,88 @@ UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale(JNIEnv *env, jobject unsafe, jclass ac
// The following allows for a pretty general fieldOffset cookie scheme,
// but requires it to be linear in byte offset.
return field_offset_from_byte_offset(scale) - field_offset_from_byte_offset(0);
-UNSAFE_END
+} UNSAFE_END
static inline void throw_new(JNIEnv *env, const char *ename) {
char buf[100];
+
jio_snprintf(buf, 100, "%s%s", "java/lang/", ename);
+
jclass cls = env->FindClass(buf);
if (env->ExceptionCheck()) {
env->ExceptionClear();
tty->print_cr("Unsafe: cannot throw %s because FindClass has failed", buf);
return;
}
- char* msg = NULL;
- env->ThrowNew(cls, msg);
+
+ env->ThrowNew(cls, NULL);
}
static jclass Unsafe_DefineClass_impl(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) {
- {
- // Code lifted from JDK 1.3 ClassLoader.c
+ // Code lifted from JDK 1.3 ClassLoader.c
- jbyte *body;
- char *utfName;
- jclass result = 0;
- char buf[128];
+ jbyte *body;
+ char *utfName = NULL;
+ jclass result = 0;
+ char buf[128];
- if (UsePerfData) {
- ClassLoader::unsafe_defineClassCallCounter()->inc();
- }
+ assert(data != NULL, "Class bytes must not be NULL");
+ assert(length >= 0, "length must not be negative: %d", length);
- if (data == NULL) {
- throw_new(env, "NullPointerException");
- return 0;
- }
+ if (UsePerfData) {
+ ClassLoader::unsafe_defineClassCallCounter()->inc();
+ }
- /* Work around 4153825. malloc crashes on Solaris when passed a
- * negative size.
- */
- if (length < 0) {
- throw_new(env, "ArrayIndexOutOfBoundsException");
- return 0;
- }
+ body = NEW_C_HEAP_ARRAY(jbyte, length, mtInternal);
+ if (body == NULL) {
+ throw_new(env, "OutOfMemoryError");
+ return 0;
+ }
- body = NEW_C_HEAP_ARRAY(jbyte, length, mtInternal);
+ env->GetByteArrayRegion(data, offset, length, body);
+ if (env->ExceptionOccurred()) {
+ goto free_body;
+ }
- if (body == 0) {
+ if (name != NULL) {
+ uint len = env->GetStringUTFLength(name);
+ int unicode_len = env->GetStringLength(name);
+
+ if (len >= sizeof(buf)) {
+ utfName = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
+ if (utfName == NULL) {
throw_new(env, "OutOfMemoryError");
- return 0;
- }
-
- env->GetByteArrayRegion(data, offset, length, body);
-
- if (env->ExceptionOccurred())
goto free_body;
-
- if (name != NULL) {
- uint len = env->GetStringUTFLength(name);
- int unicode_len = env->GetStringLength(name);
- if (len >= sizeof(buf)) {
- utfName = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
- if (utfName == NULL) {
- throw_new(env, "OutOfMemoryError");
- goto free_body;
- }
- } else {
- utfName = buf;
- }
- env->GetStringUTFRegion(name, 0, unicode_len, utfName);
- //VerifyFixClassname(utfName);
- for (uint i = 0; i < len; i++) {
- if (utfName[i] == '.') utfName[i] = '/';
- }
+ }
} else {
- utfName = NULL;
+ utfName = buf;
}
- result = JVM_DefineClass(env, utfName, loader, body, length, pd);
+ env->GetStringUTFRegion(name, 0, unicode_len, utfName);
- if (utfName && utfName != buf)
- FREE_C_HEAP_ARRAY(char, utfName);
+ for (uint i = 0; i < len; i++) {
+ if (utfName[i] == '.') utfName[i] = '/';
+ }
+ }
+
+ result = JVM_DefineClass(env, utfName, loader, body, length, pd);
+
+ if (utfName && utfName != buf) {
+ FREE_C_HEAP_ARRAY(char, utfName);
+ }
free_body:
- FREE_C_HEAP_ARRAY(jbyte, body);
- return result;
- }
+ FREE_C_HEAP_ARRAY(jbyte, body);
+ return result;
}
-UNSAFE_ENTRY(jclass, Unsafe_DefineClass(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd))
- UnsafeWrapper("Unsafe_DefineClass");
- {
- ThreadToNativeFromVM ttnfv(thread);
- return Unsafe_DefineClass_impl(env, name, data, offset, length, loader, pd);
- }
-UNSAFE_END
+UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd)) {
+ ThreadToNativeFromVM ttnfv(thread);
+
+ return Unsafe_DefineClass_impl(env, name, data, offset, length, loader, pd);
+} UNSAFE_END
// define a class but do not make it known to the class loader or system dictionary
@@ -986,45 +872,35 @@ UNSAFE_END
static instanceKlassHandle
Unsafe_DefineAnonymousClass_impl(JNIEnv *env,
jclass host_class, jbyteArray data, jobjectArray cp_patches_jh,
- HeapWord* *temp_alloc,
+ u1** temp_alloc,
TRAPS) {
+ assert(host_class != NULL, "host_class must not be NULL");
+ assert(data != NULL, "data must not be NULL");
if (UsePerfData) {
ClassLoader::unsafe_defineClassCallCounter()->inc();
}
- if (data == NULL) {
- THROW_0(vmSymbols::java_lang_NullPointerException());
- }
-
jint length = typeArrayOop(JNIHandles::resolve_non_null(data))->length();
- jint word_length = (length + sizeof(HeapWord)-1) / sizeof(HeapWord);
- HeapWord* body = NEW_C_HEAP_ARRAY(HeapWord, word_length, mtInternal);
- if (body == NULL) {
+ assert(length >= 0, "class_bytes_length must not be negative: %d", length);
+
+ int class_bytes_length = (int) length;
+
+ u1* class_bytes = NEW_C_HEAP_ARRAY(u1, length, mtInternal);
+ if (class_bytes == NULL) {
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
// caller responsible to free it:
- (*temp_alloc) = body;
+ *temp_alloc = class_bytes;
- {
- jbyte* array_base = typeArrayOop(JNIHandles::resolve_non_null(data))->byte_at_addr(0);
- Copy::conjoint_words((HeapWord*) array_base, body, word_length);
- }
-
- u1* class_bytes = (u1*) body;
- int class_bytes_length = (int) length;
- if (class_bytes_length < 0) class_bytes_length = 0;
- if (class_bytes == NULL
- || host_class == NULL
- || length != class_bytes_length)
- THROW_0(vmSymbols::java_lang_IllegalArgumentException());
+ jbyte* array_base = typeArrayOop(JNIHandles::resolve_non_null(data))->byte_at_addr(0);
+ Copy::conjoint_jbytes(array_base, class_bytes, length);
objArrayHandle cp_patches_h;
if (cp_patches_jh != NULL) {
oop p = JNIHandles::resolve_non_null(cp_patches_jh);
- if (!p->is_objArray())
- THROW_0(vmSymbols::java_lang_IllegalArgumentException());
+ assert(p->is_objArray(), "cp_patches must be an object[]");
cp_patches_h = objArrayHandle(THREAD, (objArrayOop)p);
}
@@ -1036,60 +912,56 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env,
Handle host_domain(THREAD, host_klass->protection_domain());
GrowableArray* cp_patches = NULL;
+
if (cp_patches_h.not_null()) {
int alen = cp_patches_h->length();
+
for (int i = alen-1; i >= 0; i--) {
oop p = cp_patches_h->obj_at(i);
if (p != NULL) {
Handle patch(THREAD, p);
- if (cp_patches == NULL)
+
+ if (cp_patches == NULL) {
cp_patches = new GrowableArray(i+1, i+1, Handle());
+ }
+
cp_patches->at_put(i, patch);
}
}
}
- ClassFileStream st(class_bytes,
- class_bytes_length,
- host_source,
- ClassFileStream::verify);
+ ClassFileStream st(class_bytes, class_bytes_length, host_source, ClassFileStream::verify);
- instanceKlassHandle anon_klass;
- {
- Symbol* no_class_name = NULL;
- Klass* anonk = SystemDictionary::parse_stream(no_class_name,
- host_loader,
- host_domain,
- &st,
- host_klass,
- cp_patches,
- CHECK_NULL);
- if (anonk == NULL) return NULL;
- anon_klass = instanceKlassHandle(THREAD, anonk);
+ Symbol* no_class_name = NULL;
+ Klass* anonk = SystemDictionary::parse_stream(no_class_name,
+ host_loader,
+ host_domain,
+ &st,
+ host_klass,
+ cp_patches,
+ CHECK_NULL);
+ if (anonk == NULL) {
+ return NULL;
}
- return anon_klass;
+ return instanceKlassHandle(THREAD, anonk);
}
-UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass(JNIEnv *env, jobject unsafe, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh))
-{
- instanceKlassHandle anon_klass;
- jobject res_jh = NULL;
-
- UnsafeWrapper("Unsafe_DefineAnonymousClass");
+UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass0(JNIEnv *env, jobject unsafe, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh)) {
ResourceMark rm(THREAD);
- HeapWord* temp_alloc = NULL;
+ instanceKlassHandle anon_klass;
+ jobject res_jh = NULL;
+ u1* temp_alloc = NULL;
- anon_klass = Unsafe_DefineAnonymousClass_impl(env, host_class, data,
- cp_patches_jh,
- &temp_alloc, THREAD);
- if (anon_klass() != NULL)
+ anon_klass = Unsafe_DefineAnonymousClass_impl(env, host_class, data, cp_patches_jh, &temp_alloc, THREAD);
+ if (anon_klass() != NULL) {
res_jh = JNIHandles::make_local(env, anon_klass->java_mirror());
+ }
// try/finally clause:
if (temp_alloc != NULL) {
- FREE_C_HEAP_ARRAY(HeapWord, temp_alloc);
+ FREE_C_HEAP_ARRAY(u1, temp_alloc);
}
// The anonymous class loader data has been artificially been kept alive to
@@ -1102,100 +974,103 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass(JNIEnv *env, jobject unsafe, jc
// let caller initialize it as needed...
return (jclass) res_jh;
-}
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr))
- UnsafeWrapper("Unsafe_ThrowException");
- {
- ThreadToNativeFromVM ttnfv(thread);
- env->Throw(thr);
- }
-UNSAFE_END
+UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr)) {
+ ThreadToNativeFromVM ttnfv(thread);
+ env->Throw(thr);
+} UNSAFE_END
// JSR166 ------------------------------------------------------------------
-UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
- UnsafeWrapper("Unsafe_CompareAndExchangeObject");
+UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) {
oop x = JNIHandles::resolve(x_h);
oop e = JNIHandles::resolve(e_h);
oop p = JNIHandles::resolve(obj);
HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);
- if (res == e)
+ if (res == e) {
update_barrier_set((void*)addr, x);
+ }
return JNIHandles::make_local(env, res);
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
- UnsafeWrapper("Unsafe_CompareAndExchangeInt");
+UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
oop p = JNIHandles::resolve(obj);
jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
- return (jint)(Atomic::cmpxchg(x, addr, e));
-UNSAFE_END
-UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x))
- UnsafeWrapper("Unsafe_CompareAndExchangeLong");
+ return (jint)(Atomic::cmpxchg(x, addr, e));
+} UNSAFE_END
+
+UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) {
Handle p (THREAD, JNIHandles::resolve(obj));
jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
+
#ifdef SUPPORTS_NATIVE_CX8
return (jlong)(Atomic::cmpxchg(x, addr, e));
#else
- if (VM_Version::supports_cx8())
+ if (VM_Version::supports_cx8()) {
return (jlong)(Atomic::cmpxchg(x, addr, e));
- else {
+ } else {
MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+
jlong val = Atomic::load(addr);
- if (val == e)
+ if (val == e) {
Atomic::store(x, addr);
+ }
return val;
}
#endif
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
- UnsafeWrapper("Unsafe_CompareAndSwapObject");
+UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) {
oop x = JNIHandles::resolve(x_h);
oop e = JNIHandles::resolve(e_h);
oop p = JNIHandles::resolve(obj);
HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);
- jboolean success = (res == e);
- if (success)
- update_barrier_set((void*)addr, x);
- return success;
-UNSAFE_END
+ if (res != e) {
+ return false;
+ }
-UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
- UnsafeWrapper("Unsafe_CompareAndSwapInt");
+ update_barrier_set((void*)addr, x);
+
+ return true;
+} UNSAFE_END
+
+UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) {
oop p = JNIHandles::resolve(obj);
jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
- return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
-UNSAFE_END
-UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x))
- UnsafeWrapper("Unsafe_CompareAndSwapLong");
- Handle p (THREAD, JNIHandles::resolve(obj));
- jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
+ return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
+} UNSAFE_END
+
+UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) {
+ Handle p(THREAD, JNIHandles::resolve(obj));
+ jlong* addr = (jlong*)index_oop_from_field_offset_long(p(), offset);
+
#ifdef SUPPORTS_NATIVE_CX8
return (jlong)(Atomic::cmpxchg(x, addr, e)) == e;
#else
- if (VM_Version::supports_cx8())
+ if (VM_Version::supports_cx8()) {
return (jlong)(Atomic::cmpxchg(x, addr, e)) == e;
- else {
- jboolean success = false;
+ } else {
MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag);
+
jlong val = Atomic::load(addr);
- if (val == e) { Atomic::store(x, addr); success = true; }
- return success;
+ if (val != e) {
+ return false;
+ }
+
+ Atomic::store(x, addr);
+ return true;
}
#endif
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time))
- UnsafeWrapper("Unsafe_Park");
+UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) {
EventThreadPark event;
HOTSPOT_THREAD_PARK_BEGIN((uintptr_t) thread->parker(), (int) isAbsolute, time);
@@ -1203,6 +1078,7 @@ UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute,
thread->parker()->park(isAbsolute != 0, time);
HOTSPOT_THREAD_PARK_END((uintptr_t) thread->parker());
+
if (event.should_commit()) {
oop obj = thread->current_park_blocker();
event.set_klass((obj != NULL) ? obj->klass() : NULL);
@@ -1210,11 +1086,11 @@ UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute,
event.set_address((obj != NULL) ? (TYPE_ADDRESS) cast_from_oop(obj) : 0);
event.commit();
}
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread))
- UnsafeWrapper("Unsafe_Unpark");
+UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) {
Parker* p = NULL;
+
if (jthread != NULL) {
oop java_thread = JNIHandles::resolve_non_null(jthread);
if (java_thread != NULL) {
@@ -1228,6 +1104,7 @@ UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread))
// Grab lock if apparently null or using older version of library
MutexLocker mu(Threads_lock);
java_thread = JNIHandles::resolve_non_null(jthread);
+
if (java_thread != NULL) {
JavaThread* thr = java_lang_Thread::thread(java_thread);
if (thr != NULL) {
@@ -1240,14 +1117,14 @@ UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread))
}
}
}
+
if (p != NULL) {
HOTSPOT_THREAD_UNPARK((uintptr_t) p);
p->unpark();
}
-UNSAFE_END
+} UNSAFE_END
-UNSAFE_ENTRY(jint, Unsafe_Loadavg(JNIEnv *env, jobject unsafe, jdoubleArray loadavg, jint nelem))
- UnsafeWrapper("Unsafe_Loadavg");
+UNSAFE_ENTRY(jint, Unsafe_GetLoadAverage0(JNIEnv *env, jobject unsafe, jdoubleArray loadavg, jint nelem)) {
const int max_nelem = 3;
double la[max_nelem];
jint ret;
@@ -1255,15 +1132,11 @@ UNSAFE_ENTRY(jint, Unsafe_Loadavg(JNIEnv *env, jobject unsafe, jdoubleArray load
typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(loadavg));
assert(a->is_typeArray(), "must be type array");
- if (nelem < 0 || nelem > max_nelem || a->length() < nelem) {
- ThreadToNativeFromVM ttnfv(thread);
- throw_new(env, "ArrayIndexOutOfBoundsException");
+ ret = os::loadavg(la, nelem);
+ if (ret == -1) {
return -1;
}
- ret = os::loadavg(la, nelem);
- if (ret == -1) return -1;
-
// if successful, ret is the number of samples actually retrieved.
assert(ret >= 0 && ret <= max_nelem, "Unexpected loadavg return value");
switch(ret) {
@@ -1271,8 +1144,9 @@ UNSAFE_ENTRY(jint, Unsafe_Loadavg(JNIEnv *env, jobject unsafe, jdoubleArray load
case 2: a->double_at_put(1, (jdouble)la[1]); // fall through
case 1: a->double_at_put(0, (jdouble)la[0]); break;
}
+
return ret;
-UNSAFE_END
+} UNSAFE_END
/// JVM_RegisterUnsafeMethods
@@ -1292,87 +1166,17 @@ UNSAFE_END
#define CC (char*) /*cast a literal from (const char*)*/
#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
-#define DECLARE_GETPUTOOP(Boolean, Z) \
- {CC "get" #Boolean, CC "(" OBJ "J)" #Z, FN_PTR(Unsafe_Get##Boolean)}, \
- {CC "put" #Boolean, CC "(" OBJ "J" #Z ")V", FN_PTR(Unsafe_Set##Boolean)}, \
- {CC "get" #Boolean "Volatile", CC "(" OBJ "J)" #Z, FN_PTR(Unsafe_Get##Boolean##Volatile)}, \
- {CC "put" #Boolean "Volatile", CC "(" OBJ "J" #Z ")V", FN_PTR(Unsafe_Set##Boolean##Volatile)}
+#define DECLARE_GETPUTOOP(Type, Desc) \
+ {CC "get" #Type, CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type)}, \
+ {CC "put" #Type, CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Set##Type)}, \
+ {CC "get" #Type "Volatile", CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type##Volatile)}, \
+ {CC "put" #Type "Volatile", CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Set##Type##Volatile)}
#define DECLARE_GETPUTNATIVE(Byte, B) \
{CC "get" #Byte, CC "(" ADR ")" #B, FN_PTR(Unsafe_GetNative##Byte)}, \
{CC "put" #Byte, CC "(" ADR#B ")V", FN_PTR(Unsafe_SetNative##Byte)}
-
-static JNINativeMethod sun_misc_Unsafe_methods[] = {
- {CC "getObject", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObject)},
- {CC "putObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObject)},
- {CC "getObjectVolatile",CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObjectVolatile)},
- {CC "putObjectVolatile",CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObjectVolatile)},
-
- {CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)},
- {CC "getJavaMirror", CC "(" ADR ")" CLS, FN_PTR(Unsafe_GetJavaMirror)},
- {CC "getKlassPointer", CC "(" OBJ ")" ADR, FN_PTR(Unsafe_GetKlassPointer)},
-
- DECLARE_GETPUTOOP(Boolean, Z),
- DECLARE_GETPUTOOP(Byte, B),
- DECLARE_GETPUTOOP(Short, S),
- DECLARE_GETPUTOOP(Char, C),
- DECLARE_GETPUTOOP(Int, I),
- DECLARE_GETPUTOOP(Long, J),
- DECLARE_GETPUTOOP(Float, F),
- DECLARE_GETPUTOOP(Double, D),
-
- DECLARE_GETPUTNATIVE(Byte, B),
- DECLARE_GETPUTNATIVE(Short, S),
- DECLARE_GETPUTNATIVE(Char, C),
- DECLARE_GETPUTNATIVE(Int, I),
- DECLARE_GETPUTNATIVE(Long, J),
- DECLARE_GETPUTNATIVE(Float, F),
- DECLARE_GETPUTNATIVE(Double, D),
-
- {CC "getAddress", CC "(" ADR ")" ADR, FN_PTR(Unsafe_GetNativeAddress)},
- {CC "putAddress", CC "(" ADR "" ADR ")V", FN_PTR(Unsafe_SetNativeAddress)},
-
- {CC "allocateMemory", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory)},
- {CC "reallocateMemory", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory)},
- {CC "freeMemory", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory)},
-
- {CC "objectFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_ObjectFieldOffset)},
- {CC "staticFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_StaticFieldOffset)},
- {CC "staticFieldBase", CC "(" FLD ")" OBJ, FN_PTR(Unsafe_StaticFieldBaseFromField)},
- {CC "ensureClassInitialized",CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized)},
- {CC "arrayBaseOffset", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset)},
- {CC "arrayIndexScale", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale)},
- {CC "addressSize", CC "()I", FN_PTR(Unsafe_AddressSize)},
- {CC "pageSize", CC "()I", FN_PTR(Unsafe_PageSize)},
-
- {CC "defineClass", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass)},
- {CC "allocateInstance", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_AllocateInstance)},
- {CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)},
- {CC "compareAndSwapObject", CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
- {CC "compareAndSwapInt", CC "(" OBJ "J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
- {CC "compareAndSwapLong", CC "(" OBJ "J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)},
- {CC "putOrderedObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetOrderedObject)},
- {CC "putOrderedInt", CC "(" OBJ "JI)V", FN_PTR(Unsafe_SetOrderedInt)},
- {CC "putOrderedLong", CC "(" OBJ "JJ)V", FN_PTR(Unsafe_SetOrderedLong)},
- {CC "park", CC "(ZJ)V", FN_PTR(Unsafe_Park)},
- {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)},
-
- {CC "getLoadAverage", CC "([DI)I", FN_PTR(Unsafe_Loadavg)},
-
- {CC "copyMemory", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory)},
- {CC "setMemory", CC "(" OBJ "JJB)V", FN_PTR(Unsafe_SetMemory)},
-
- {CC "defineAnonymousClass", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass)},
-
- {CC "shouldBeInitialized",CC "(" CLS ")Z", FN_PTR(Unsafe_ShouldBeInitialized)},
-
- {CC "loadFence", CC "()V", FN_PTR(Unsafe_LoadFence)},
- {CC "storeFence", CC "()V", FN_PTR(Unsafe_StoreFence)},
- {CC "fullFence", CC "()V", FN_PTR(Unsafe_FullFence)},
-};
-
static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
{CC "getObject", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObject)},
{CC "putObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObject)},
@@ -1403,20 +1207,20 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
{CC "getAddress", CC "(" ADR ")" ADR, FN_PTR(Unsafe_GetNativeAddress)},
{CC "putAddress", CC "(" ADR "" ADR ")V", FN_PTR(Unsafe_SetNativeAddress)},
- {CC "allocateMemory", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory)},
- {CC "reallocateMemory", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory)},
- {CC "freeMemory", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory)},
+ {CC "allocateMemory0", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory0)},
+ {CC "reallocateMemory0", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory0)},
+ {CC "freeMemory0", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory0)},
- {CC "objectFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_ObjectFieldOffset)},
- {CC "staticFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_StaticFieldOffset)},
- {CC "staticFieldBase", CC "(" FLD ")" OBJ, FN_PTR(Unsafe_StaticFieldBaseFromField)},
- {CC "ensureClassInitialized",CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized)},
- {CC "arrayBaseOffset", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset)},
- {CC "arrayIndexScale", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale)},
- {CC "addressSize", CC "()I", FN_PTR(Unsafe_AddressSize)},
+ {CC "objectFieldOffset0", CC "(" FLD ")J", FN_PTR(Unsafe_ObjectFieldOffset0)},
+ {CC "staticFieldOffset0", CC "(" FLD ")J", FN_PTR(Unsafe_StaticFieldOffset0)},
+ {CC "staticFieldBase0", CC "(" FLD ")" OBJ, FN_PTR(Unsafe_StaticFieldBase0)},
+ {CC "ensureClassInitialized0", CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized0)},
+ {CC "arrayBaseOffset0", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset0)},
+ {CC "arrayIndexScale0", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale0)},
+ {CC "addressSize0", CC "()I", FN_PTR(Unsafe_AddressSize0)},
{CC "pageSize", CC "()I", FN_PTR(Unsafe_PageSize)},
- {CC "defineClass", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass)},
+ {CC "defineClass0", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass0)},
{CC "allocateInstance", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_AllocateInstance)},
{CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)},
{CC "compareAndSwapObject", CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
@@ -1432,15 +1236,15 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
{CC "park", CC "(ZJ)V", FN_PTR(Unsafe_Park)},
{CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)},
- {CC "getLoadAverage", CC "([DI)I", FN_PTR(Unsafe_Loadavg)},
+ {CC "getLoadAverage0", CC "([DI)I", FN_PTR(Unsafe_GetLoadAverage0)},
- {CC "copyMemory", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory)},
+ {CC "copyMemory0", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)},
{CC "copySwapMemory0", CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)},
- {CC "setMemory", CC "(" OBJ "JJB)V", FN_PTR(Unsafe_SetMemory)},
+ {CC "setMemory0", CC "(" OBJ "JJB)V", FN_PTR(Unsafe_SetMemory0)},
- {CC "defineAnonymousClass", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass)},
+ {CC "defineAnonymousClass0", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass0)},
- {CC "shouldBeInitialized",CC "(" CLS ")Z", FN_PTR(Unsafe_ShouldBeInitialized)},
+ {CC "shouldBeInitialized0", CC "(" CLS ")Z", FN_PTR(Unsafe_ShouldBeInitialized0)},
{CC "loadFence", CC "()V", FN_PTR(Unsafe_LoadFence)},
{CC "storeFence", CC "()V", FN_PTR(Unsafe_StoreFence)},
@@ -1466,27 +1270,14 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
#undef DECLARE_GETPUTNATIVE
-// These two functions are exported, used by NativeLookup.
+// This function is exported, used by NativeLookup.
// The Unsafe_xxx functions above are called only from the interpreter.
// The optimizer looks at names and signatures to recognize
// individual functions.
-JVM_ENTRY(void, JVM_RegisterSunMiscUnsafeMethods(JNIEnv *env, jclass unsafeclass))
- UnsafeWrapper("JVM_RegisterSunMiscUnsafeMethods");
- {
- ThreadToNativeFromVM ttnfv(thread);
+JVM_ENTRY(void, JVM_RegisterJDKInternalMiscUnsafeMethods(JNIEnv *env, jclass unsafeclass)) {
+ ThreadToNativeFromVM ttnfv(thread);
- int ok = env->RegisterNatives(unsafeclass, sun_misc_Unsafe_methods, sizeof(sun_misc_Unsafe_methods)/sizeof(JNINativeMethod));
- guarantee(ok == 0, "register sun.misc.Unsafe natives");
- }
-JVM_END
-
-JVM_ENTRY(void, JVM_RegisterJDKInternalMiscUnsafeMethods(JNIEnv *env, jclass unsafeclass))
- UnsafeWrapper("JVM_RegisterJDKInternalMiscUnsafeMethods");
- {
- ThreadToNativeFromVM ttnfv(thread);
-
- int ok = env->RegisterNatives(unsafeclass, jdk_internal_misc_Unsafe_methods, sizeof(jdk_internal_misc_Unsafe_methods)/sizeof(JNINativeMethod));
- guarantee(ok == 0, "register jdk.internal.misc.Unsafe natives");
- }
-JVM_END
+ int ok = env->RegisterNatives(unsafeclass, jdk_internal_misc_Unsafe_methods, sizeof(jdk_internal_misc_Unsafe_methods)/sizeof(JNINativeMethod));
+ guarantee(ok == 0, "register jdk.internal.misc.Unsafe natives");
+} JVM_END
diff --git a/hotspot/src/share/vm/prims/unsafe.hpp b/hotspot/src/share/vm/prims/unsafe.hpp
new file mode 100644
index 00000000000..e8ed3a2ad02
--- /dev/null
+++ b/hotspot/src/share/vm/prims/unsafe.hpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ */
+
+
+#ifndef SHARE_VM_PRIMS_UNSAFE_HPP
+#define SHARE_VM_PRIMS_UNSAFE_HPP
+
+#include "jni.h"
+
+extern "C" {
+ void JNICALL JVM_RegisterJDKInternalMiscUnsafeMethods(JNIEnv *env, jclass unsafecls);
+}
+
+jlong Unsafe_field_offset_to_byte_offset(jlong field_offset);
+
+jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset);
+
+#endif // SHARE_VM_PRIMS_UNSAFE_HPP
diff --git a/hotspot/src/share/vm/runtime/interfaceSupport.hpp b/hotspot/src/share/vm/runtime/interfaceSupport.hpp
index 84a6d6afafd..8dbc6be317c 100644
--- a/hotspot/src/share/vm/runtime/interfaceSupport.hpp
+++ b/hotspot/src/share/vm/runtime/interfaceSupport.hpp
@@ -521,9 +521,9 @@ class RuntimeHistogramElement : public HistogramElement {
JNI_ENTRY_NO_PRESERVE(result_type, header) \
WeakPreserveExceptionMark __wem(thread);
-#define JNI_ENTRY_NO_PRESERVE(result_type, header) \
+#define JNI_ENTRY_NO_PRESERVE(result_type, header) \
extern "C" { \
- result_type JNICALL header { \
+ result_type JNICALL header { \
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \
ThreadInVMfromNative __tiv(thread); \
@@ -535,7 +535,7 @@ extern "C" { \
// a GC, is called outside the NoHandleMark (set via VM_QUICK_ENTRY_BASE).
#define JNI_QUICK_ENTRY(result_type, header) \
extern "C" { \
- result_type JNICALL header { \
+ result_type JNICALL header { \
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \
ThreadInVMfromNative __tiv(thread); \
@@ -545,7 +545,7 @@ extern "C" { \
#define JNI_LEAF(result_type, header) \
extern "C" { \
- result_type JNICALL header { \
+ result_type JNICALL header { \
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \
VM_LEAF_BASE(result_type, header)
diff --git a/hotspot/src/share/vm/shark/sharkBuilder.cpp b/hotspot/src/share/vm/shark/sharkBuilder.cpp
index 0fcc8107fc9..ab4dcdcefbf 100644
--- a/hotspot/src/share/vm/shark/sharkBuilder.cpp
+++ b/hotspot/src/share/vm/shark/sharkBuilder.cpp
@@ -29,6 +29,7 @@
#include "gc/shared/cardTableModRefBS.hpp"
#include "memory/resourceArea.hpp"
#include "oops/method.hpp"
+#include "prims/unsafe.hpp"
#include "runtime/os.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/thread.hpp"
@@ -326,7 +327,6 @@ Value* SharkBuilder::fabs() {
}
Value* SharkBuilder::unsafe_field_offset_to_byte_offset() {
- extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset);
return make_function((address) Unsafe_field_offset_to_byte_offset, "l", "l");
}
diff --git a/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java b/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java
index d96de812faa..1fdaf805f9a 100644
--- a/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java
+++ b/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java
@@ -33,8 +33,8 @@
* -XX:+WhiteBoxAPI
* -XX:DisableIntrinsic=_putCharVolatile,_putInt
* -XX:DisableIntrinsic=_putIntVolatile
- * -XX:CompileCommand=option,sun.misc.Unsafe::putChar,ccstrlist,DisableIntrinsic,_getCharVolatile,_getInt
- * -XX:CompileCommand=option,sun.misc.Unsafe::putCharVolatile,ccstrlist,DisableIntrinsic,_getIntVolatile
+ * -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putChar,ccstrlist,DisableIntrinsic,_getCharVolatile,_getInt
+ * -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putCharVolatile,ccstrlist,DisableIntrinsic,_getIntVolatile
* IntrinsicDisabledTest
*/
@@ -60,7 +60,7 @@ public class IntrinsicDisabledTest {
return Boolean.valueOf(Objects.toString(wb.getVMFlag("TieredCompilation")));
}
- /* This test uses several methods from sun.misc.Unsafe. The method
+ /* This test uses several methods from jdk.internal.misc.Unsafe. The method
* getMethod() returns a different Executable for each different
* combination of its input parameters. There are eight possible
* combinations, getMethod can return an Executable representing
@@ -74,7 +74,7 @@ public class IntrinsicDisabledTest {
String methodTypeName = isChar ? "Char" : "Int";
try {
- Class aClass = Class.forName("sun.misc.Unsafe");
+ Class aClass = Class.forName("jdk.internal.misc.Unsafe");
if (isPut) {
aMethod = aClass.getDeclaredMethod("put" + methodTypeName + (isVolatile ? "Volatile" : ""),
Object.class,
From 890f94d7e6be731ac2ebae2f1ad3cc20ec836115 Mon Sep 17 00:00:00 2001
From: Aleksey Shipilev
Date: Thu, 3 Mar 2016 22:17:38 +0300
Subject: [PATCH 053/311] 8150669: C1 intrinsic for Class.isPrimitive
Reviewed-by: twisti, vlivanov, redestad
---
hotspot/src/share/vm/c1/c1_Canonicalizer.cpp | 13 +-
hotspot/src/share/vm/c1/c1_Compiler.cpp | 1 +
hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 20 +++
hotspot/src/share/vm/c1/c1_LIRGenerator.hpp | 1 +
.../class/TestClassIsPrimitive.java | 166 ++++++++++++++++++
5 files changed, 200 insertions(+), 1 deletion(-)
create mode 100644 hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java
diff --git a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp
index 033beb0d25e..d70a769e93b 100644
--- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp
+++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp
@@ -471,7 +471,7 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) {
InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant();
if (c != NULL && !c->value()->is_null_object()) {
// ciInstance::java_mirror_type() returns non-NULL only for Java mirrors
- ciType* t = c->value()->as_instance()->java_mirror_type();
+ ciType* t = c->value()->java_mirror_type();
if (t->is_klass()) {
// substitute cls.isInstance(obj) of a constant Class into
// an InstantOf instruction
@@ -487,6 +487,17 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) {
}
break;
}
+ case vmIntrinsics::_isPrimitive : {
+ assert(x->number_of_arguments() == 1, "wrong type");
+
+ // Class.isPrimitive is known on constant classes:
+ InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant();
+ if (c != NULL && !c->value()->is_null_object()) {
+ ciType* t = c->value()->java_mirror_type();
+ set_constant(t->is_primitive_type());
+ }
+ break;
+ }
}
}
diff --git a/hotspot/src/share/vm/c1/c1_Compiler.cpp b/hotspot/src/share/vm/c1/c1_Compiler.cpp
index 5dbe6c209f3..75974669b35 100644
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp
@@ -148,6 +148,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) {
case vmIntrinsics::_longBitsToDouble:
case vmIntrinsics::_getClass:
case vmIntrinsics::_isInstance:
+ case vmIntrinsics::_isPrimitive:
case vmIntrinsics::_currentThread:
case vmIntrinsics::_dabs:
case vmIntrinsics::_dsqrt:
diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp
index 30ae8f86e9f..bfe367453c9 100644
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp
@@ -1293,6 +1293,25 @@ void LIRGenerator::do_getClass(Intrinsic* x) {
__ move_wide(new LIR_Address(temp, in_bytes(Klass::java_mirror_offset()), T_OBJECT), result);
}
+// java.lang.Class::isPrimitive()
+void LIRGenerator::do_isPrimitive(Intrinsic* x) {
+ assert(x->number_of_arguments() == 1, "wrong type");
+
+ LIRItem rcvr(x->argument_at(0), this);
+ rcvr.load_item();
+ LIR_Opr temp = new_register(T_METADATA);
+ LIR_Opr result = rlock_result(x);
+
+ CodeEmitInfo* info = NULL;
+ if (x->needs_null_check()) {
+ info = state_for(x);
+ }
+
+ __ move(new LIR_Address(rcvr.result(), java_lang_Class::klass_offset_in_bytes(), T_ADDRESS), temp, info);
+ __ cmp(lir_cond_notEqual, temp, LIR_OprFact::intConst(0));
+ __ cmove(lir_cond_notEqual, LIR_OprFact::intConst(0), LIR_OprFact::intConst(1), result, T_BOOLEAN);
+}
+
// Example: Thread.currentThread()
void LIRGenerator::do_currentThread(Intrinsic* x) {
@@ -3132,6 +3151,7 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) {
case vmIntrinsics::_Object_init: do_RegisterFinalizer(x); break;
case vmIntrinsics::_isInstance: do_isInstance(x); break;
+ case vmIntrinsics::_isPrimitive: do_isPrimitive(x); break;
case vmIntrinsics::_getClass: do_getClass(x); break;
case vmIntrinsics::_currentThread: do_currentThread(x); break;
diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp
index 9438d77288c..b673f566723 100644
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp
@@ -246,6 +246,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
void do_RegisterFinalizer(Intrinsic* x);
void do_isInstance(Intrinsic* x);
+ void do_isPrimitive(Intrinsic* x);
void do_getClass(Intrinsic* x);
void do_currentThread(Intrinsic* x);
void do_MathIntrinsic(Intrinsic* x);
diff --git a/hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java b/hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java
new file mode 100644
index 00000000000..76a2812e733
--- /dev/null
+++ b/hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8150669
+ * @summary C1 intrinsic for Class.isPrimitive
+ * @modules java.base/jdk.internal.misc
+ * @run main/othervm -ea -Diters=200 -Xint TestClassIsPrimitive
+ * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=1 TestClassIsPrimitive
+ * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=4 TestClassIsPrimitive
+ */
+import java.lang.reflect.Field;
+import java.lang.reflect.Array;
+import java.util.concurrent.Callable;
+
+public class TestClassIsPrimitive {
+ static final int ITERS = Integer.getInteger("iters", 1);
+
+ public static void main(String... args) throws Exception {
+ testOK(true, InlineConstants::testBoolean);
+ testOK(true, InlineConstants::testByte);
+ testOK(true, InlineConstants::testShort);
+ testOK(true, InlineConstants::testChar);
+ testOK(true, InlineConstants::testInt);
+ testOK(true, InlineConstants::testFloat);
+ testOK(true, InlineConstants::testLong);
+ testOK(true, InlineConstants::testDouble);
+ testOK(false, InlineConstants::testObject);
+ testOK(false, InlineConstants::testArray);
+
+ testOK(true, StaticConstants::testBoolean);
+ testOK(true, StaticConstants::testByte);
+ testOK(true, StaticConstants::testShort);
+ testOK(true, StaticConstants::testChar);
+ testOK(true, StaticConstants::testInt);
+ testOK(true, StaticConstants::testFloat);
+ testOK(true, StaticConstants::testLong);
+ testOK(true, StaticConstants::testDouble);
+ testOK(false, StaticConstants::testObject);
+ testOK(false, StaticConstants::testArray);
+ testNPE( StaticConstants::testNull);
+
+ testOK(true, NoConstants::testBoolean);
+ testOK(true, NoConstants::testByte);
+ testOK(true, NoConstants::testShort);
+ testOK(true, NoConstants::testChar);
+ testOK(true, NoConstants::testInt);
+ testOK(true, NoConstants::testFloat);
+ testOK(true, NoConstants::testLong);
+ testOK(true, NoConstants::testDouble);
+ testOK(false, NoConstants::testObject);
+ testOK(false, NoConstants::testArray);
+ testNPE( NoConstants::testNull);
+ }
+
+ public static void testOK(boolean expected, Callable test) throws Exception {
+ for (int c = 0; c < ITERS; c++) {
+ Object res = test.call();
+ if (!res.equals(expected)) {
+ throw new IllegalStateException("Wrong result: expected = " + expected + ", but got " + res);
+ }
+ }
+ }
+
+ static volatile Object sink;
+
+ public static void testNPE(Callable test) throws Exception {
+ for (int c = 0; c < ITERS; c++) {
+ try {
+ sink = test.call();
+ throw new IllegalStateException("Expected NPE");
+ } catch (NullPointerException iae) {
+ // expected
+ }
+ }
+ }
+
+ static volatile Class> classBoolean = boolean.class;
+ static volatile Class> classByte = byte.class;
+ static volatile Class> classShort = short.class;
+ static volatile Class> classChar = char.class;
+ static volatile Class> classInt = int.class;
+ static volatile Class> classFloat = float.class;
+ static volatile Class> classLong = long.class;
+ static volatile Class> classDouble = double.class;
+ static volatile Class> classObject = Object.class;
+ static volatile Class> classArray = Object[].class;
+ static volatile Class> classNull = null;
+
+ static final Class> staticClassBoolean = boolean.class;
+ static final Class> staticClassByte = byte.class;
+ static final Class> staticClassShort = short.class;
+ static final Class> staticClassChar = char.class;
+ static final Class> staticClassInt = int.class;
+ static final Class> staticClassFloat = float.class;
+ static final Class> staticClassLong = long.class;
+ static final Class> staticClassDouble = double.class;
+ static final Class> staticClassObject = Object.class;
+ static final Class> staticClassArray = Object[].class;
+ static final Class> staticClassNull = null;
+
+ static class InlineConstants {
+ static boolean testBoolean() { return boolean.class.isPrimitive(); }
+ static boolean testByte() { return byte.class.isPrimitive(); }
+ static boolean testShort() { return short.class.isPrimitive(); }
+ static boolean testChar() { return char.class.isPrimitive(); }
+ static boolean testInt() { return int.class.isPrimitive(); }
+ static boolean testFloat() { return float.class.isPrimitive(); }
+ static boolean testLong() { return long.class.isPrimitive(); }
+ static boolean testDouble() { return double.class.isPrimitive(); }
+ static boolean testObject() { return Object.class.isPrimitive(); }
+ static boolean testArray() { return Object[].class.isPrimitive(); }
+ }
+
+ static class StaticConstants {
+ static boolean testBoolean() { return staticClassBoolean.isPrimitive(); }
+ static boolean testByte() { return staticClassByte.isPrimitive(); }
+ static boolean testShort() { return staticClassShort.isPrimitive(); }
+ static boolean testChar() { return staticClassChar.isPrimitive(); }
+ static boolean testInt() { return staticClassInt.isPrimitive(); }
+ static boolean testFloat() { return staticClassFloat.isPrimitive(); }
+ static boolean testLong() { return staticClassLong.isPrimitive(); }
+ static boolean testDouble() { return staticClassDouble.isPrimitive(); }
+ static boolean testObject() { return staticClassObject.isPrimitive(); }
+ static boolean testArray() { return staticClassArray.isPrimitive(); }
+ static boolean testNull() { return staticClassNull.isPrimitive(); }
+ }
+
+ static class NoConstants {
+ static boolean testBoolean() { return classBoolean.isPrimitive(); }
+ static boolean testByte() { return classByte.isPrimitive(); }
+ static boolean testShort() { return classShort.isPrimitive(); }
+ static boolean testChar() { return classChar.isPrimitive(); }
+ static boolean testInt() { return classInt.isPrimitive(); }
+ static boolean testFloat() { return classFloat.isPrimitive(); }
+ static boolean testLong() { return classLong.isPrimitive(); }
+ static boolean testDouble() { return classDouble.isPrimitive(); }
+ static boolean testObject() { return classObject.isPrimitive(); }
+ static boolean testArray() { return classArray.isPrimitive(); }
+ static boolean testNull() { return classNull.isPrimitive(); }
+ }
+
+}
+
From 548530cf084b5756200def41f52e03df55cb51e7 Mon Sep 17 00:00:00 2001
From: Aleksey Shipilev
Date: Thu, 3 Mar 2016 23:57:29 +0300
Subject: [PATCH 054/311] 8150465: Unsafe methods to produce uninitialized
arrays
Reviewed-by: jrose, kvn, psandoz, aph, twisti, flar
---
hotspot/src/share/vm/classfile/vmSymbols.hpp | 2 +
hotspot/src/share/vm/opto/c2compiler.cpp | 1 +
hotspot/src/share/vm/opto/library_call.cpp | 27 ++-
.../unsafe/AllocateUninitializedArray.java | 213 ++++++++++++++++++
4 files changed, 237 insertions(+), 6 deletions(-)
create mode 100644 hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java
diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp
index fcc4ad8be25..6dd88c2d2e7 100644
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp
@@ -1040,6 +1040,8 @@
do_intrinsic(_allocateInstance, jdk_internal_misc_Unsafe, allocateInstance_name, allocateInstance_signature, F_RN) \
do_name( allocateInstance_name, "allocateInstance") \
do_signature(allocateInstance_signature, "(Ljava/lang/Class;)Ljava/lang/Object;") \
+ do_intrinsic(_allocateUninitializedArray, jdk_internal_misc_Unsafe, allocateUninitializedArray_name, newArray_signature, F_R) \
+ do_name( allocateUninitializedArray_name, "allocateUninitializedArray0") \
do_intrinsic(_copyMemory, jdk_internal_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \
do_name( copyMemory_name, "copyMemory0") \
do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \
diff --git a/hotspot/src/share/vm/opto/c2compiler.cpp b/hotspot/src/share/vm/opto/c2compiler.cpp
index aeea26748fe..5d61042af32 100644
--- a/hotspot/src/share/vm/opto/c2compiler.cpp
+++ b/hotspot/src/share/vm/opto/c2compiler.cpp
@@ -500,6 +500,7 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
case vmIntrinsics::_currentTimeMillis:
case vmIntrinsics::_nanoTime:
case vmIntrinsics::_allocateInstance:
+ case vmIntrinsics::_allocateUninitializedArray:
case vmIntrinsics::_newArray:
case vmIntrinsics::_getLength:
case vmIntrinsics::_copyOf:
diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp
index 4ecca52fb3d..40d82895cf4 100644
--- a/hotspot/src/share/vm/opto/library_call.cpp
+++ b/hotspot/src/share/vm/opto/library_call.cpp
@@ -247,6 +247,7 @@ class LibraryCallKit : public GraphKit {
bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, AccessKind kind, bool is_unaligned);
static bool klass_needs_init_guard(Node* kls);
bool inline_unsafe_allocate();
+ bool inline_unsafe_newArray(bool uninitialized);
bool inline_unsafe_copyMemory();
bool inline_native_currentThread();
#ifdef TRACE_HAVE_INTRINSICS
@@ -257,8 +258,6 @@ class LibraryCallKit : public GraphKit {
bool inline_native_isInterrupted();
bool inline_native_Class_query(vmIntrinsics::ID id);
bool inline_native_subtype_check();
-
- bool inline_native_newArray();
bool inline_native_getLength();
bool inline_array_copyOf(bool is_copyOfRange);
bool inline_array_equals(StrIntrinsicNode::ArgEnc ae);
@@ -715,7 +714,6 @@ bool LibraryCallKit::try_to_inline(int predicate) {
case vmIntrinsics::_nanoTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeNanos), "nanoTime");
case vmIntrinsics::_allocateInstance: return inline_unsafe_allocate();
case vmIntrinsics::_copyMemory: return inline_unsafe_copyMemory();
- case vmIntrinsics::_newArray: return inline_native_newArray();
case vmIntrinsics::_getLength: return inline_native_getLength();
case vmIntrinsics::_copyOf: return inline_array_copyOf(false);
case vmIntrinsics::_copyOfRange: return inline_array_copyOf(true);
@@ -724,6 +722,9 @@ bool LibraryCallKit::try_to_inline(int predicate) {
case vmIntrinsics::_Objects_checkIndex: return inline_objects_checkIndex();
case vmIntrinsics::_clone: return inline_native_clone(intrinsic()->is_virtual());
+ case vmIntrinsics::_allocateUninitializedArray: return inline_unsafe_newArray(true);
+ case vmIntrinsics::_newArray: return inline_unsafe_newArray(false);
+
case vmIntrinsics::_isAssignableFrom: return inline_native_subtype_check();
case vmIntrinsics::_isInstance:
@@ -3829,9 +3830,17 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region,
//-----------------------inline_native_newArray--------------------------
// private static native Object java.lang.reflect.newArray(Class> componentType, int length);
-bool LibraryCallKit::inline_native_newArray() {
- Node* mirror = argument(0);
- Node* count_val = argument(1);
+// private native Object Unsafe.allocateUninitializedArray0(Class> cls, int size);
+bool LibraryCallKit::inline_unsafe_newArray(bool uninitialized) {
+ Node* mirror;
+ Node* count_val;
+ if (uninitialized) {
+ mirror = argument(1);
+ count_val = argument(2);
+ } else {
+ mirror = argument(0);
+ count_val = argument(1);
+ }
mirror = null_check(mirror);
// If mirror or obj is dead, only null-path is taken.
@@ -3876,6 +3885,12 @@ bool LibraryCallKit::inline_native_newArray() {
result_val->init_req(_normal_path, obj);
result_io ->init_req(_normal_path, i_o());
result_mem->init_req(_normal_path, reset_memory());
+
+ if (uninitialized) {
+ // Mark the allocation so that zeroing is skipped
+ AllocateArrayNode* alloc = AllocateArrayNode::Ideal_array_allocation(obj, &_gvn);
+ alloc->maybe_set_complete(&_gvn);
+ }
}
// Return the combined state.
diff --git a/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java b/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java
new file mode 100644
index 00000000000..404ccc6c60d
--- /dev/null
+++ b/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ */
+
+/*
+ * @test
+ * @bug 8150465
+ * @summary Unsafe methods to produce uninitialized arrays
+ * @modules java.base/jdk.internal.misc
+ * @run main/othervm -ea -Diters=200 -Xint AllocateUninitializedArray
+ * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=1 AllocateUninitializedArray
+ * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=4 AllocateUninitializedArray
+ */
+import java.lang.reflect.Field;
+import java.lang.reflect.Array;
+import java.util.concurrent.Callable;
+
+public class AllocateUninitializedArray {
+ static final int ITERS = Integer.getInteger("iters", 1);
+ static final jdk.internal.misc.Unsafe UNSAFE;
+
+ static {
+ try {
+ Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ UNSAFE = (jdk.internal.misc.Unsafe) f.get(null);
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to get Unsafe instance.", e);
+ }
+ }
+
+ public static void main(String... args) throws Exception {
+ testIAE(AllConstants::testObject);
+ testIAE(LengthIsConstant::testObject);
+ testIAE(ClassIsConstant::testObject);
+ testIAE(NothingIsConstant::testObject);
+
+ testIAE(AllConstants::testArray);
+ testIAE(LengthIsConstant::testArray);
+ testIAE(ClassIsConstant::testArray);
+ testIAE(NothingIsConstant::testArray);
+
+ testIAE(AllConstants::testNull);
+ testIAE(LengthIsConstant::testNull);
+ testIAE(ClassIsConstant::testNull);
+ testIAE(NothingIsConstant::testNull);
+
+ testOK(boolean[].class, 10, AllConstants::testBoolean);
+ testOK(byte[].class, 10, AllConstants::testByte);
+ testOK(short[].class, 10, AllConstants::testShort);
+ testOK(char[].class, 10, AllConstants::testChar);
+ testOK(int[].class, 10, AllConstants::testInt);
+ testOK(float[].class, 10, AllConstants::testFloat);
+ testOK(long[].class, 10, AllConstants::testLong);
+ testOK(double[].class, 10, AllConstants::testDouble);
+
+ testOK(boolean[].class, 10, LengthIsConstant::testBoolean);
+ testOK(byte[].class, 10, LengthIsConstant::testByte);
+ testOK(short[].class, 10, LengthIsConstant::testShort);
+ testOK(char[].class, 10, LengthIsConstant::testChar);
+ testOK(int[].class, 10, LengthIsConstant::testInt);
+ testOK(float[].class, 10, LengthIsConstant::testFloat);
+ testOK(long[].class, 10, LengthIsConstant::testLong);
+ testOK(double[].class, 10, LengthIsConstant::testDouble);
+
+ testOK(boolean[].class, 10, ClassIsConstant::testBoolean);
+ testOK(byte[].class, 10, ClassIsConstant::testByte);
+ testOK(short[].class, 10, ClassIsConstant::testShort);
+ testOK(char[].class, 10, ClassIsConstant::testChar);
+ testOK(int[].class, 10, ClassIsConstant::testInt);
+ testOK(float[].class, 10, ClassIsConstant::testFloat);
+ testOK(long[].class, 10, ClassIsConstant::testLong);
+ testOK(double[].class, 10, ClassIsConstant::testDouble);
+
+ testOK(boolean[].class, 10, NothingIsConstant::testBoolean);
+ testOK(byte[].class, 10, NothingIsConstant::testByte);
+ testOK(short[].class, 10, NothingIsConstant::testShort);
+ testOK(char[].class, 10, NothingIsConstant::testChar);
+ testOK(int[].class, 10, NothingIsConstant::testInt);
+ testOK(float[].class, 10, NothingIsConstant::testFloat);
+ testOK(long[].class, 10, NothingIsConstant::testLong);
+ testOK(double[].class, 10, NothingIsConstant::testDouble);
+ }
+
+ public static void testOK(Class> expectClass, int expectLen, Callable test) throws Exception {
+ for (int c = 0; c < ITERS; c++) {
+ Object res = test.call();
+ Class> actualClass = res.getClass();
+ if (!actualClass.equals(expectClass)) {
+ throw new IllegalStateException("Wrong class: expected = " + expectClass + ", but got " + actualClass);
+ }
+ int actualLen = Array.getLength(res);
+ if (actualLen != expectLen) {
+ throw new IllegalStateException("Wrong length: expected = " + expectLen + ", but got " + actualLen);
+ }
+ }
+ }
+
+ static volatile Object sink;
+
+ public static void testIAE(Callable test) throws Exception {
+ for (int c = 0; c < ITERS; c++) {
+ try {
+ sink = test.call();
+ throw new IllegalStateException("Expected IAE");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+ }
+
+ static volatile int sampleLenNeg = -1;
+ static volatile int sampleLenZero = 0;
+ static volatile int sampleLen = 10;
+
+
+ static volatile Class> classBoolean = boolean.class;
+ static volatile Class> classByte = byte.class;
+ static volatile Class> classShort = short.class;
+ static volatile Class> classChar = char.class;
+ static volatile Class> classInt = int.class;
+ static volatile Class> classFloat = float.class;
+ static volatile Class> classLong = long.class;
+ static volatile Class> classDouble = double.class;
+ static volatile Class> classObject = Object.class;
+ static volatile Class> classArray = Object[].class;
+ static volatile Class> classNull = null;
+
+ static class AllConstants {
+ static Object testBoolean() { return UNSAFE.allocateUninitializedArray(boolean.class, 10); }
+ static Object testByte() { return UNSAFE.allocateUninitializedArray(byte.class, 10); }
+ static Object testShort() { return UNSAFE.allocateUninitializedArray(short.class, 10); }
+ static Object testChar() { return UNSAFE.allocateUninitializedArray(char.class, 10); }
+ static Object testInt() { return UNSAFE.allocateUninitializedArray(int.class, 10); }
+ static Object testFloat() { return UNSAFE.allocateUninitializedArray(float.class, 10); }
+ static Object testLong() { return UNSAFE.allocateUninitializedArray(long.class, 10); }
+ static Object testDouble() { return UNSAFE.allocateUninitializedArray(double.class, 10); }
+ static Object testObject() { return UNSAFE.allocateUninitializedArray(Object.class, 10); }
+ static Object testArray() { return UNSAFE.allocateUninitializedArray(Object[].class, 10); }
+ static Object testNull() { return UNSAFE.allocateUninitializedArray(null, 10); }
+ static Object testZero() { return UNSAFE.allocateUninitializedArray(int.class, 0); }
+ static Object testNeg() { return UNSAFE.allocateUninitializedArray(int.class, -1); }
+ }
+
+ static class ClassIsConstant {
+ static Object testBoolean() { return UNSAFE.allocateUninitializedArray(boolean.class, sampleLen); }
+ static Object testByte() { return UNSAFE.allocateUninitializedArray(byte.class, sampleLen); }
+ static Object testShort() { return UNSAFE.allocateUninitializedArray(short.class, sampleLen); }
+ static Object testChar() { return UNSAFE.allocateUninitializedArray(char.class, sampleLen); }
+ static Object testInt() { return UNSAFE.allocateUninitializedArray(int.class, sampleLen); }
+ static Object testFloat() { return UNSAFE.allocateUninitializedArray(float.class, sampleLen); }
+ static Object testLong() { return UNSAFE.allocateUninitializedArray(long.class, sampleLen); }
+ static Object testDouble() { return UNSAFE.allocateUninitializedArray(double.class, sampleLen); }
+ static Object testObject() { return UNSAFE.allocateUninitializedArray(Object.class, sampleLen); }
+ static Object testArray() { return UNSAFE.allocateUninitializedArray(Object[].class, sampleLen); }
+ static Object testNull() { return UNSAFE.allocateUninitializedArray(null, sampleLen); }
+ static Object testZero() { return UNSAFE.allocateUninitializedArray(int.class, sampleLenZero); }
+ static Object testNeg() { return UNSAFE.allocateUninitializedArray(int.class, sampleLenNeg); }
+ }
+
+ static class LengthIsConstant {
+ static Object testBoolean() { return UNSAFE.allocateUninitializedArray(classBoolean, 10); }
+ static Object testByte() { return UNSAFE.allocateUninitializedArray(classByte, 10); }
+ static Object testShort() { return UNSAFE.allocateUninitializedArray(classShort, 10); }
+ static Object testChar() { return UNSAFE.allocateUninitializedArray(classChar, 10); }
+ static Object testInt() { return UNSAFE.allocateUninitializedArray(classInt, 10); }
+ static Object testFloat() { return UNSAFE.allocateUninitializedArray(classFloat, 10); }
+ static Object testLong() { return UNSAFE.allocateUninitializedArray(classLong, 10); }
+ static Object testDouble() { return UNSAFE.allocateUninitializedArray(classDouble, 10); }
+ static Object testObject() { return UNSAFE.allocateUninitializedArray(classObject, 10); }
+ static Object testArray() { return UNSAFE.allocateUninitializedArray(classArray, 10); }
+ static Object testNull() { return UNSAFE.allocateUninitializedArray(classNull, 10); }
+ static Object testZero() { return UNSAFE.allocateUninitializedArray(classInt, 0); }
+ static Object testNeg() { return UNSAFE.allocateUninitializedArray(classInt, -1); }
+ }
+
+ static class NothingIsConstant {
+ static Object testBoolean() { return UNSAFE.allocateUninitializedArray(classBoolean, sampleLen); }
+ static Object testByte() { return UNSAFE.allocateUninitializedArray(classByte, sampleLen); }
+ static Object testShort() { return UNSAFE.allocateUninitializedArray(classShort, sampleLen); }
+ static Object testChar() { return UNSAFE.allocateUninitializedArray(classChar, sampleLen); }
+ static Object testInt() { return UNSAFE.allocateUninitializedArray(classInt, sampleLen); }
+ static Object testFloat() { return UNSAFE.allocateUninitializedArray(classFloat, sampleLen); }
+ static Object testLong() { return UNSAFE.allocateUninitializedArray(classLong, sampleLen); }
+ static Object testDouble() { return UNSAFE.allocateUninitializedArray(classDouble, sampleLen); }
+ static Object testObject() { return UNSAFE.allocateUninitializedArray(classObject, sampleLen); }
+ static Object testArray() { return UNSAFE.allocateUninitializedArray(classArray, sampleLen); }
+ static Object testNull() { return UNSAFE.allocateUninitializedArray(classNull, sampleLen); }
+ static Object testZero() { return UNSAFE.allocateUninitializedArray(classInt, sampleLenZero); }
+ static Object testNeg() { return UNSAFE.allocateUninitializedArray(classInt, sampleLenNeg); }
+ }
+}
+
From 103aff334f61fdb654453a0f6a6d58a5ded6ac7c Mon Sep 17 00:00:00 2001
From: Aleksey Shipilev
Date: Fri, 4 Mar 2016 01:30:11 +0300
Subject: [PATCH 055/311] 8146801: Allocating short arrays of non-constant size
is slow
Reviewed-by: kvn, twisti, vlivanov
---
hotspot/src/cpu/aarch64/vm/aarch64.ad | 3 --
.../src/cpu/aarch64/vm/globals_aarch64.hpp | 2 +
hotspot/src/cpu/ppc/vm/globals_ppc.hpp | 2 +
hotspot/src/cpu/ppc/vm/ppc.ad | 2 -
hotspot/src/cpu/sparc/vm/globals_sparc.hpp | 2 +
hotspot/src/cpu/sparc/vm/sparc.ad | 3 --
hotspot/src/cpu/x86/vm/globals_x86.hpp | 2 +
hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp | 35 ++++++++++--
hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp | 5 +-
hotspot/src/cpu/x86/vm/x86_32.ad | 52 +++++++++++++-----
hotspot/src/cpu/x86/vm/x86_64.ad | 53 +++++++++++++------
hotspot/src/share/vm/opto/matcher.hpp | 4 --
hotspot/src/share/vm/opto/memnode.cpp | 14 +++--
hotspot/src/share/vm/opto/memnode.hpp | 7 ++-
.../commandLineFlagConstraintsCompiler.cpp | 8 +++
.../commandLineFlagConstraintsCompiler.hpp | 2 +
hotspot/src/share/vm/runtime/globals.hpp | 7 +++
17 files changed, 150 insertions(+), 53 deletions(-)
diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad
index acc65080e2f..832c9e765ba 100644
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad
@@ -3425,9 +3425,6 @@ const bool Matcher::misaligned_vectors_ok() {
// false => size gets scaled to BytesPerLong, ok.
const bool Matcher::init_array_count_is_in_bytes = false;
-// Threshold size for cleararray.
-const int Matcher::init_array_short_size = 18 * BytesPerLong;
-
// Use conditional move (CMOVL)
const int Matcher::long_cmove_cost() {
// long cmoves are no more expensive than int cmoves
diff --git a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
index 86d2c14ce54..9380d429878 100644
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
@@ -76,6 +76,8 @@ define_pd_global(bool, CompactStrings, false);
// avoid biased locking while we are bootstrapping the aarch64 build
define_pd_global(bool, UseBiasedLocking, false);
+define_pd_global(intx, InitArrayShortSize, 18*BytesPerLong);
+
#if defined(COMPILER1) || defined(COMPILER2)
define_pd_global(intx, InlineSmallCode, 1000);
#endif
diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp
index 4afb89e1ffb..77f7a491b02 100644
--- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp
+++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp
@@ -76,6 +76,8 @@ define_pd_global(uintx, TypeProfileLevel, 111);
define_pd_global(bool, CompactStrings, true);
+define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong);
+
// Platform dependent flag handling: flags only defined on this platform.
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
\
diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad
index df119f8bdf1..20521eb8e18 100644
--- a/hotspot/src/cpu/ppc/vm/ppc.ad
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad
@@ -2137,8 +2137,6 @@ MachTypeNode *Matcher::make_decode_node() {
return decode;
}
*/
-// Threshold size for cleararray.
-const int Matcher::init_array_short_size = 8 * BytesPerLong;
// false => size gets scaled to BytesPerLong, ok.
const bool Matcher::init_array_count_is_in_bytes = false;
diff --git a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp
index 3b813df0254..66889ae73b3 100644
--- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp
@@ -90,6 +90,8 @@ define_pd_global(uintx, TypeProfileLevel, 111);
define_pd_global(bool, CompactStrings, true);
+define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong);
+
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
\
product(intx, UseVIS, 99, \
diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad
index 5cf884a5501..f24c1f9b384 100644
--- a/hotspot/src/cpu/sparc/vm/sparc.ad
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad
@@ -1980,9 +1980,6 @@ const bool Matcher::isSimpleConstant64(jlong value) {
// No scaling for the parameter the ClearArray node.
const bool Matcher::init_array_count_is_in_bytes = true;
-// Threshold size for cleararray.
-const int Matcher::init_array_short_size = 8 * BytesPerLong;
-
// No additional cost for CMOVL.
const int Matcher::long_cmove_cost() { return 0; }
diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp
index 7a34048248e..a8d36092b58 100644
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp
@@ -97,6 +97,8 @@ define_pd_global(bool, CompactStrings, true);
define_pd_global(bool, PreserveFramePointer, false);
+define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong);
+
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
\
develop(bool, IEEEPrecision, true, \
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
index e1c73024118..4bca248d815 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
@@ -7198,21 +7198,50 @@ void MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_
}
-void MacroAssembler::clear_mem(Register base, Register cnt, Register tmp) {
+void MacroAssembler::clear_mem(Register base, Register cnt, Register tmp, bool is_large) {
// cnt - number of qwords (8-byte words).
// base - start address, qword aligned.
+ // is_large - if optimizers know cnt is larger than InitArrayShortSize
assert(base==rdi, "base register must be edi for rep stos");
assert(tmp==rax, "tmp register must be eax for rep stos");
assert(cnt==rcx, "cnt register must be ecx for rep stos");
+ assert(InitArrayShortSize % BytesPerLong == 0,
+ "InitArrayShortSize should be the multiple of BytesPerLong");
+
+ Label DONE;
xorptr(tmp, tmp);
+
+ if (!is_large) {
+ Label LOOP, LONG;
+ cmpptr(cnt, InitArrayShortSize/BytesPerLong);
+ jccb(Assembler::greater, LONG);
+
+ NOT_LP64(shlptr(cnt, 1);) // convert to number of 32-bit words for 32-bit VM
+
+ decrement(cnt);
+ jccb(Assembler::negative, DONE); // Zero length
+
+ // Use individual pointer-sized stores for small counts:
+ BIND(LOOP);
+ movptr(Address(base, cnt, Address::times_ptr), tmp);
+ decrement(cnt);
+ jccb(Assembler::greaterEqual, LOOP);
+ jmpb(DONE);
+
+ BIND(LONG);
+ }
+
+ // Use longer rep-prefixed ops for non-small counts:
if (UseFastStosb) {
- shlptr(cnt,3); // convert to number of bytes
+ shlptr(cnt, 3); // convert to number of bytes
rep_stosb();
} else {
- NOT_LP64(shlptr(cnt,1);) // convert to number of dwords for 32-bit VM
+ NOT_LP64(shlptr(cnt, 1);) // convert to number of 32-bit words for 32-bit VM
rep_stos();
}
+
+ BIND(DONE);
}
#ifdef COMPILER2
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
index 95931ad2b24..84d9df6cfb4 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
@@ -1284,8 +1284,9 @@ public:
// C2 compiled method's prolog code.
void verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b);
- // clear memory of size 'cnt' qwords, starting at 'base'.
- void clear_mem(Register base, Register cnt, Register rtmp);
+ // clear memory of size 'cnt' qwords, starting at 'base';
+ // if 'is_large' is set, do not try to produce short loop
+ void clear_mem(Register base, Register cnt, Register rtmp, bool is_large);
#ifdef COMPILER2
void string_indexof_char(Register str1, Register cnt1, Register ch, Register result,
diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad
index b09ca8e36ab..c9583ba13e0 100644
--- a/hotspot/src/cpu/x86/vm/x86_32.ad
+++ b/hotspot/src/cpu/x86/vm/x86_32.ad
@@ -1420,9 +1420,6 @@ const bool Matcher::isSimpleConstant64(jlong value) {
// The ecx parameter to rep stos for the ClearArray node is in dwords.
const bool Matcher::init_array_count_is_in_bytes = false;
-// Threshold size for cleararray.
-const int Matcher::init_array_short_size = 8 * BytesPerLong;
-
// Needs 2 CMOV's for longs.
const int Matcher::long_cmove_cost() { return 1; }
@@ -11369,27 +11366,54 @@ instruct MoveL2D_reg_reg_sse(regD dst, eRegL src, regD tmp) %{
// =======================================================================
// fast clearing of an array
instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{
- predicate(!UseFastStosb);
+ predicate(!((ClearArrayNode*)n)->is_large());
match(Set dummy (ClearArray cnt base));
effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr);
- format %{ "XOR EAX,EAX\t# ClearArray:\n\t"
- "SHL ECX,1\t# Convert doublewords to words\n\t"
- "REP STOS\t# store EAX into [EDI++] while ECX--" %}
+
+ format %{ $$template
+ $$emit$$"XOR EAX,EAX\t# ClearArray:\n\t"
+ $$emit$$"CMP InitArrayShortSize,rcx\n\t"
+ $$emit$$"JG LARGE\n\t"
+ $$emit$$"SHL ECX, 1\n\t"
+ $$emit$$"DEC ECX\n\t"
+ $$emit$$"JS DONE\t# Zero length\n\t"
+ $$emit$$"MOV EAX,(EDI,ECX,4)\t# LOOP\n\t"
+ $$emit$$"DEC ECX\n\t"
+ $$emit$$"JGE LOOP\n\t"
+ $$emit$$"JMP DONE\n\t"
+ $$emit$$"# LARGE:\n\t"
+ if (UseFastStosb) {
+ $$emit$$"SHL ECX,3\t# Convert doublewords to bytes\n\t"
+ $$emit$$"REP STOSB\t# store EAX into [EDI++] while ECX--\n\t"
+ } else {
+ $$emit$$"SHL ECX,1\t# Convert doublewords to words\n\t"
+ $$emit$$"REP STOS\t# store EAX into [EDI++] while ECX--\n\t"
+ }
+ $$emit$$"# DONE"
+ %}
ins_encode %{
- __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register);
+ __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register, false);
%}
ins_pipe( pipe_slow );
%}
-instruct rep_fast_stosb(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{
- predicate(UseFastStosb);
+instruct rep_stos_large(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{
+ predicate(((ClearArrayNode*)n)->is_large());
match(Set dummy (ClearArray cnt base));
effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr);
- format %{ "XOR EAX,EAX\t# ClearArray:\n\t"
- "SHL ECX,3\t# Convert doublewords to bytes\n\t"
- "REP STOSB\t# store EAX into [EDI++] while ECX--" %}
+ format %{ $$template
+ $$emit$$"XOR EAX,EAX\t# ClearArray:\n\t"
+ if (UseFastStosb) {
+ $$emit$$"SHL ECX,3\t# Convert doublewords to bytes\n\t"
+ $$emit$$"REP STOSB\t# store EAX into [EDI++] while ECX--\n\t"
+ } else {
+ $$emit$$"SHL ECX,1\t# Convert doublewords to words\n\t"
+ $$emit$$"REP STOS\t# store EAX into [EDI++] while ECX--\n\t"
+ }
+ $$emit$$"# DONE"
+ %}
ins_encode %{
- __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register);
+ __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register, true);
%}
ins_pipe( pipe_slow );
%}
diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad
index 6f32ace2f18..9579436fb20 100644
--- a/hotspot/src/cpu/x86/vm/x86_64.ad
+++ b/hotspot/src/cpu/x86/vm/x86_64.ad
@@ -1637,9 +1637,6 @@ const bool Matcher::isSimpleConstant64(jlong value) {
// The ecx parameter to rep stosq for the ClearArray node is in words.
const bool Matcher::init_array_count_is_in_bytes = false;
-// Threshold size for cleararray.
-const int Matcher::init_array_short_size = 8 * BytesPerLong;
-
// No additional cost for CMOVL.
const int Matcher::long_cmove_cost() { return 0; }
@@ -10460,31 +10457,55 @@ instruct MoveL2D_reg_reg(regD dst, rRegL src) %{
instruct rep_stos(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy,
rFlagsReg cr)
%{
- predicate(!UseFastStosb);
+ predicate(!((ClearArrayNode*)n)->is_large());
match(Set dummy (ClearArray cnt base));
effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr);
- format %{ "xorq rax, rax\t# ClearArray:\n\t"
- "rep stosq\t# Store rax to *rdi++ while rcx--" %}
+ format %{ $$template
+ $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
+ $$emit$$"cmp InitArrayShortSize,rcx\n\t"
+ $$emit$$"jg LARGE\n\t"
+ $$emit$$"dec rcx\n\t"
+ $$emit$$"js DONE\t# Zero length\n\t"
+ $$emit$$"mov rax,(rdi,rcx,8)\t# LOOP\n\t"
+ $$emit$$"dec rcx\n\t"
+ $$emit$$"jge LOOP\n\t"
+ $$emit$$"jmp DONE\n\t"
+ $$emit$$"# LARGE:\n\t"
+ if (UseFastStosb) {
+ $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t"
+ $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--\n\t"
+ } else {
+ $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--\n\t"
+ }
+ $$emit$$"# DONE"
+ %}
ins_encode %{
- __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register);
+ __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register, false);
%}
ins_pipe(pipe_slow);
%}
-instruct rep_fast_stosb(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy,
- rFlagsReg cr)
+instruct rep_stos_large(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy,
+ rFlagsReg cr)
%{
- predicate(UseFastStosb);
+ predicate(((ClearArrayNode*)n)->is_large());
match(Set dummy (ClearArray cnt base));
effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr);
- format %{ "xorq rax, rax\t# ClearArray:\n\t"
- "shlq rcx,3\t# Convert doublewords to bytes\n\t"
- "rep stosb\t# Store rax to *rdi++ while rcx--" %}
- ins_encode %{
- __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register);
+
+ format %{ $$template
+ $$emit$$"xorq rax, rax\t# ClearArray:\n\t"
+ if (UseFastStosb) {
+ $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t"
+ $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--"
+ } else {
+ $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--"
+ }
%}
- ins_pipe( pipe_slow );
+ ins_encode %{
+ __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register, true);
+ %}
+ ins_pipe(pipe_slow);
%}
instruct string_compareL(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
diff --git a/hotspot/src/share/vm/opto/matcher.hpp b/hotspot/src/share/vm/opto/matcher.hpp
index 64cc48c65ec..dad3854e3f2 100644
--- a/hotspot/src/share/vm/opto/matcher.hpp
+++ b/hotspot/src/share/vm/opto/matcher.hpp
@@ -399,10 +399,6 @@ public:
// Optional scaling for the parameter to the ClearArray/CopyArray node.
static const bool init_array_count_is_in_bytes;
- // Threshold small size (in bytes) for a ClearArray/CopyArray node.
- // Anything this size or smaller may get converted to discrete scalar stores.
- static const int init_array_short_size;
-
// Some hardware needs 2 CMOV's for longs.
static const int long_cmove_cost();
diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp
index 51733c8fa65..a09caf81bb7 100644
--- a/hotspot/src/share/vm/opto/memnode.cpp
+++ b/hotspot/src/share/vm/opto/memnode.cpp
@@ -2741,6 +2741,9 @@ Node* ClearArrayNode::Identity(PhaseGVN* phase) {
//------------------------------Idealize---------------------------------------
// Clearing a short array is faster with stores
Node *ClearArrayNode::Ideal(PhaseGVN *phase, bool can_reshape){
+ // Already know this is a large node, do not try to ideal it
+ if (_is_large) return NULL;
+
const int unit = BytesPerLong;
const TypeX* t = phase->type(in(2))->isa_intptr_t();
if (!t) return NULL;
@@ -2753,8 +2756,11 @@ Node *ClearArrayNode::Ideal(PhaseGVN *phase, bool can_reshape){
// (see jck test stmt114.stmt11402.val).
if (size <= 0 || size % unit != 0) return NULL;
intptr_t count = size / unit;
- // Length too long; use fast hardware clear
- if (size > Matcher::init_array_short_size) return NULL;
+ // Length too long; communicate this to matchers and assemblers.
+ // Assemblers are responsible to produce fast hardware clears for it.
+ if (size > InitArrayShortSize) {
+ return new ClearArrayNode(in(0), in(1), in(2), in(3), true);
+ }
Node *mem = in(1);
if( phase->type(mem)==Type::TOP ) return NULL;
Node *adr = in(3);
@@ -2852,7 +2858,7 @@ Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest,
// Bulk clear double-words
Node* zsize = phase->transform(new SubXNode(zend, zbase) );
Node* adr = phase->transform(new AddPNode(dest, dest, start_offset) );
- mem = new ClearArrayNode(ctl, mem, zsize, adr);
+ mem = new ClearArrayNode(ctl, mem, zsize, adr, false);
return phase->transform(mem);
}
@@ -3901,7 +3907,7 @@ Node* InitializeNode::complete_stores(Node* rawctl, Node* rawmem, Node* rawptr,
zeroes_done, zeroes_needed,
phase);
zeroes_done = zeroes_needed;
- if (zsize > Matcher::init_array_short_size && ++big_init_gaps > 2)
+ if (zsize > InitArrayShortSize && ++big_init_gaps > 2)
do_zeroing = false; // leave the hole, next time
}
}
diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp
index 8d9cd71bc0a..c1477bb2e4c 100644
--- a/hotspot/src/share/vm/opto/memnode.hpp
+++ b/hotspot/src/share/vm/opto/memnode.hpp
@@ -1013,9 +1013,11 @@ public:
//------------------------------ClearArray-------------------------------------
class ClearArrayNode: public Node {
+private:
+ bool _is_large;
public:
- ClearArrayNode( Node *ctrl, Node *arymem, Node *word_cnt, Node *base )
- : Node(ctrl,arymem,word_cnt,base) {
+ ClearArrayNode( Node *ctrl, Node *arymem, Node *word_cnt, Node *base, bool is_large)
+ : Node(ctrl,arymem,word_cnt,base), _is_large(is_large) {
init_class_id(Class_ClearArray);
}
virtual int Opcode() const;
@@ -1026,6 +1028,7 @@ public:
virtual Node* Identity(PhaseGVN* phase);
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual uint match_edge(uint idx) const;
+ bool is_large() const { return _is_large; }
// Clear the given area of an object or array.
// The start offset must always be aligned mod BytesPerInt.
diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp
index 1484cba01c8..bfadc319516 100644
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp
@@ -354,6 +354,14 @@ Flag::Error TypeProfileLevelConstraintFunc(uintx value, bool verbose) {
return Flag::SUCCESS;
}
+Flag::Error InitArrayShortSizeConstraintFunc(intx value, bool verbose) {
+ if (value % BytesPerLong != 0) {
+ return Flag::VIOLATES_CONSTRAINT;
+ } else {
+ return Flag::SUCCESS;
+ }
+}
+
#ifdef COMPILER2
Flag::Error InteriorEntryAlignmentConstraintFunc(intx value, bool verbose) {
if (InteriorEntryAlignment > CodeEntryAlignment) {
diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp
index f9d07848960..0038d52eac8 100644
--- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp
+++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp
@@ -62,6 +62,8 @@ Flag::Error ArraycopySrcPrefetchDistanceConstraintFunc(uintx value, bool verbose
Flag::Error TypeProfileLevelConstraintFunc(uintx value, bool verbose);
+Flag::Error InitArrayShortSizeConstraintFunc(intx value, bool verbose);
+
#ifdef COMPILER2
Flag::Error InteriorEntryAlignmentConstraintFunc(intx value, bool verbose);
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
index ce36ff1db49..113a9f71ab6 100644
--- a/hotspot/src/share/vm/runtime/globals.hpp
+++ b/hotspot/src/share/vm/runtime/globals.hpp
@@ -4162,6 +4162,13 @@ public:
"in the loaded class C. " \
"Check (3) is available only in debug builds.") \
\
+ develop_pd(intx, InitArrayShortSize, \
+ "Threshold small size (in bytes) for clearing arrays. " \
+ "Anything this size or smaller may get converted to discrete " \
+ "scalar stores.") \
+ range(0, max_intx) \
+ constraint(InitArrayShortSizeConstraintFunc, AfterErgo) \
+ \
diagnostic(bool, CompilerDirectivesIgnoreCompileCommands, false, \
"Disable backwards compatibility for compile commands.") \
\
From 40fe96de0de8f604ba19055650aa2657f000d1fa Mon Sep 17 00:00:00 2001
From: Vivek Deshpande
Date: Thu, 3 Mar 2016 22:02:13 -0800
Subject: [PATCH 056/311] 8150767: Enables SHA Extensions on x86
Add x86 intrinsics for SHA-1 and SHA-256.
Co-authored-by: Shravya Rukmannagari
Reviewed-by: kvn, twisti
---
hotspot/src/cpu/x86/vm/assembler_x86.cpp | 88 ++++
hotspot/src/cpu/x86/vm/assembler_x86.hpp | 13 +
hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp | 52 +-
.../src/cpu/x86/vm/macroAssembler_x86_sha.cpp | 495 ++++++++++++++++++
.../src/cpu/x86/vm/stubGenerator_x86_32.cpp | 143 +++++
.../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 140 +++++
hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp | 30 ++
hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp | 15 +
hotspot/src/cpu/x86/vm/vmStructs_x86.hpp | 7 +-
hotspot/src/cpu/x86/vm/vm_version_x86.cpp | 27 +-
hotspot/src/cpu/x86/vm/vm_version_x86.hpp | 13 +-
.../src/jdk/vm/ci/amd64/AMD64.java | 3 +-
.../AMD64HotSpotJVMCIBackendFactory.java | 3 +
.../jdk/vm/ci/hotspot/HotSpotVMConfig.java | 1 +
.../src/share/vm/jvmci/vmStructs_jvmci.cpp | 7 +-
hotspot/src/share/vm/runtime/globals.hpp | 2 +-
16 files changed, 1011 insertions(+), 28 deletions(-)
create mode 100644 hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp
index 00ce5c3560c..65f2da7ecd0 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp
@@ -777,6 +777,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
case 0x6E: // movd
case 0x7E: // movd
case 0xAE: // ldmxcsr, stmxcsr, fxrstor, fxsave, clflush
+ case 0xFE: // paddd
debug_only(has_disp32 = true);
break;
@@ -926,6 +927,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) {
ip++; // skip P2, move to opcode
// To find the end of instruction (which == end_pc_operand).
switch (0xFF & *ip) {
+ case 0x22: // pinsrd r, r/a, #8
case 0x61: // pcmpestri r, r/a, #8
case 0x70: // pshufd r, r/a, #8
case 0x73: // psrldq r, #8
@@ -3953,6 +3955,83 @@ void Assembler::setb(Condition cc, Register dst) {
emit_int8((unsigned char)(0xC0 | encode));
}
+void Assembler::palignr(XMMRegister dst, XMMRegister src, int imm8) {
+ assert(VM_Version::supports_ssse3(), "");
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ false, /* uses_vl */ false);
+ int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
+ emit_int8((unsigned char)0x0F);
+ emit_int8((unsigned char)(0xC0 | encode));
+ emit_int8(imm8);
+}
+
+void Assembler::pblendw(XMMRegister dst, XMMRegister src, int imm8) {
+ assert(VM_Version::supports_sse4_1(), "");
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
+ emit_int8((unsigned char)0x0E);
+ emit_int8((unsigned char)(0xC0 | encode));
+ emit_int8(imm8);
+}
+
+void Assembler::sha1rnds4(XMMRegister dst, XMMRegister src, int imm8) {
+ assert(VM_Version::supports_sha(), "");
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_3A, &attributes);
+ emit_int8((unsigned char)0xCC);
+ emit_int8((unsigned char)(0xC0 | encode));
+ emit_int8((unsigned char)imm8);
+}
+
+void Assembler::sha1nexte(XMMRegister dst, XMMRegister src) {
+ assert(VM_Version::supports_sha(), "");
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes);
+ emit_int8((unsigned char)0xC8);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+void Assembler::sha1msg1(XMMRegister dst, XMMRegister src) {
+ assert(VM_Version::supports_sha(), "");
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes);
+ emit_int8((unsigned char)0xC9);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+void Assembler::sha1msg2(XMMRegister dst, XMMRegister src) {
+ assert(VM_Version::supports_sha(), "");
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes);
+ emit_int8((unsigned char)0xCA);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+// xmm0 is implicit additional source to this instruction.
+void Assembler::sha256rnds2(XMMRegister dst, XMMRegister src) {
+ assert(VM_Version::supports_sha(), "");
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes);
+ emit_int8((unsigned char)0xCB);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+void Assembler::sha256msg1(XMMRegister dst, XMMRegister src) {
+ assert(VM_Version::supports_sha(), "");
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes);
+ emit_int8((unsigned char)0xCC);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+void Assembler::sha256msg2(XMMRegister dst, XMMRegister src) {
+ assert(VM_Version::supports_sha(), "");
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false);
+ int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes);
+ emit_int8((unsigned char)0xCD);
+ emit_int8((unsigned char)(0xC0 | encode));
+}
+
+
void Assembler::shll(Register dst, int imm8) {
assert(isShiftCount(imm8), "illegal shift count");
int encode = prefix_and_encode(dst->encoding());
@@ -4931,6 +5010,15 @@ void Assembler::paddd(XMMRegister dst, XMMRegister src) {
emit_int8((unsigned char)(0xC0 | encode));
}
+void Assembler::paddd(XMMRegister dst, Address src) {
+ NOT_LP64(assert(VM_Version::supports_sse2(), ""));
+ InstructionMark im(this);
+ InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
+ simd_prefix(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F, &attributes);
+ emit_int8((unsigned char)0xFE);
+ emit_operand(dst, src);
+}
+
void Assembler::paddq(XMMRegister dst, XMMRegister src) {
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true);
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp
index 7712ce02cab..3026afda174 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp
@@ -1672,6 +1672,18 @@ private:
void setb(Condition cc, Register dst);
+ void palignr(XMMRegister dst, XMMRegister src, int imm8);
+ void pblendw(XMMRegister dst, XMMRegister src, int imm8);
+
+ void sha1rnds4(XMMRegister dst, XMMRegister src, int imm8);
+ void sha1nexte(XMMRegister dst, XMMRegister src);
+ void sha1msg1(XMMRegister dst, XMMRegister src);
+ void sha1msg2(XMMRegister dst, XMMRegister src);
+ // xmm0 is implicit additional source to the following instruction.
+ void sha256rnds2(XMMRegister dst, XMMRegister src);
+ void sha256msg1(XMMRegister dst, XMMRegister src);
+ void sha256msg2(XMMRegister dst, XMMRegister src);
+
void shldl(Register dst, Register src);
void shldl(Register dst, Register src, int8_t imm8);
@@ -1868,6 +1880,7 @@ private:
void paddb(XMMRegister dst, XMMRegister src);
void paddw(XMMRegister dst, XMMRegister src);
void paddd(XMMRegister dst, XMMRegister src);
+ void paddd(XMMRegister dst, Address src);
void paddq(XMMRegister dst, XMMRegister src);
void vpaddb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
void vpaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
index 84d9df6cfb4..d33473606aa 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
@@ -48,7 +48,6 @@ class MacroAssembler: public Assembler {
// This is the base routine called by the different versions of call_VM_leaf. The interpreter
// may customize this version by overriding it for its purposes (e.g., to save/restore
// additional registers when doing a VM call).
-#define COMMA ,
virtual void call_VM_leaf_base(
address entry_point, // the entry point
@@ -903,35 +902,66 @@ class MacroAssembler: public Assembler {
void ldmxcsr(Address src) { Assembler::ldmxcsr(src); }
void ldmxcsr(AddressLiteral src);
+ void fast_sha1(XMMRegister abcd, XMMRegister e0, XMMRegister e1, XMMRegister msg0,
+ XMMRegister msg1, XMMRegister msg2, XMMRegister msg3, XMMRegister shuf_mask,
+ Register buf, Register state, Register ofs, Register limit, Register rsp,
+ bool multi_block);
+
+#ifdef _LP64
+ void fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0,
+ XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4,
+ Register buf, Register state, Register ofs, Register limit, Register rsp,
+ bool multi_block, XMMRegister shuf_mask);
+#else
+ void fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0,
+ XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4,
+ Register buf, Register state, Register ofs, Register limit, Register rsp,
+ bool multi_block);
+#endif
+
void fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
Register rax, Register rcx, Register rdx, Register tmp);
+#ifdef _LP64
void fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
- Register rax, Register rcx, Register rdx, Register tmp1 LP64_ONLY(COMMA Register tmp2));
+ Register rax, Register rcx, Register rdx, Register tmp1, Register tmp2);
void fast_pow(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4,
XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register rax, Register rcx,
- Register rdx NOT_LP64(COMMA Register tmp) LP64_ONLY(COMMA Register tmp1)
- LP64_ONLY(COMMA Register tmp2) LP64_ONLY(COMMA Register tmp3) LP64_ONLY(COMMA Register tmp4));
+ Register rdx, Register tmp1, Register tmp2, Register tmp3, Register tmp4);
void fast_sin(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
- Register rax, Register rbx LP64_ONLY(COMMA Register rcx), Register rdx
- LP64_ONLY(COMMA Register tmp1) LP64_ONLY(COMMA Register tmp2)
- LP64_ONLY(COMMA Register tmp3) LP64_ONLY(COMMA Register tmp4));
+ Register rax, Register rbx, Register rcx, Register rdx, Register tmp1, Register tmp2,
+ Register tmp3, Register tmp4);
void fast_cos(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
- Register rax, Register rcx, Register rdx NOT_LP64(COMMA Register tmp)
- LP64_ONLY(COMMA Register r8) LP64_ONLY(COMMA Register r9)
- LP64_ONLY(COMMA Register r10) LP64_ONLY(COMMA Register r11));
+ Register rax, Register rcx, Register rdx, Register tmp1,
+ Register tmp2, Register tmp3, Register tmp4);
+#else
+ void fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
+ XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
+ Register rax, Register rcx, Register rdx, Register tmp1);
+
+ void fast_pow(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4,
+ XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register rax, Register rcx,
+ Register rdx, Register tmp);
+
+ void fast_sin(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
+ XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
+ Register rax, Register rbx, Register rdx);
+
+ void fast_cos(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
+ XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
+ Register rax, Register rcx, Register rdx, Register tmp);
-#ifndef _LP64
void libm_sincos_huge(XMMRegister xmm0, XMMRegister xmm1, Register eax, Register ecx,
Register edx, Register ebx, Register esi, Register edi,
Register ebp, Register esp);
+
void libm_reduce_pi04l(Register eax, Register ecx, Register edx, Register ebx,
Register esi, Register edi, Register ebp, Register esp);
#endif
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp
new file mode 100644
index 00000000000..bbc96156fe5
--- /dev/null
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp
@@ -0,0 +1,495 @@
+/*
+* Copyright (c) 2016, Intel Corporation.
+*
+* 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.
+*
+*/
+
+#include "precompiled.hpp"
+#include "asm/assembler.hpp"
+#include "asm/assembler.inline.hpp"
+#include "runtime/stubRoutines.hpp"
+#include "macroAssembler_x86.hpp"
+
+// ofs and limit are used for multi-block byte array.
+// int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit)
+void MacroAssembler::fast_sha1(XMMRegister abcd, XMMRegister e0, XMMRegister e1, XMMRegister msg0,
+ XMMRegister msg1, XMMRegister msg2, XMMRegister msg3, XMMRegister shuf_mask,
+ Register buf, Register state, Register ofs, Register limit, Register rsp, bool multi_block) {
+
+ Label start, done_hash, loop0;
+
+ address upper_word_mask = StubRoutines::x86::upper_word_mask_addr();
+ address shuffle_byte_flip_mask = StubRoutines::x86::shuffle_byte_flip_mask_addr();
+
+ bind(start);
+ movdqu(abcd, Address(state, 0));
+ pinsrd(e0, Address(state, 16), 3);
+ movdqu(shuf_mask, ExternalAddress(upper_word_mask)); // 0xFFFFFFFF000000000000000000000000
+ pand(e0, shuf_mask);
+ pshufd(abcd, abcd, 0x1B);
+ movdqu(shuf_mask, ExternalAddress(shuffle_byte_flip_mask)); //0x000102030405060708090a0b0c0d0e0f
+
+ bind(loop0);
+ // Save hash values for addition after rounds
+ movdqu(Address(rsp, 0), e0);
+ movdqu(Address(rsp, 16), abcd);
+
+
+ // Rounds 0 - 3
+ movdqu(msg0, Address(buf, 0));
+ pshufb(msg0, shuf_mask);
+ paddd(e0, msg0);
+ movdqa(e1, abcd);
+ sha1rnds4(abcd, e0, 0);
+
+ // Rounds 4 - 7
+ movdqu(msg1, Address(buf, 16));
+ pshufb(msg1, shuf_mask);
+ sha1nexte(e1, msg1);
+ movdqa(e0, abcd);
+ sha1rnds4(abcd, e1, 0);
+ sha1msg1(msg0, msg1);
+
+ // Rounds 8 - 11
+ movdqu(msg2, Address(buf, 32));
+ pshufb(msg2, shuf_mask);
+ sha1nexte(e0, msg2);
+ movdqa(e1, abcd);
+ sha1rnds4(abcd, e0, 0);
+ sha1msg1(msg1, msg2);
+ pxor(msg0, msg2);
+
+ // Rounds 12 - 15
+ movdqu(msg3, Address(buf, 48));
+ pshufb(msg3, shuf_mask);
+ sha1nexte(e1, msg3);
+ movdqa(e0, abcd);
+ sha1msg2(msg0, msg3);
+ sha1rnds4(abcd, e1, 0);
+ sha1msg1(msg2, msg3);
+ pxor(msg1, msg3);
+
+ // Rounds 16 - 19
+ sha1nexte(e0, msg0);
+ movdqa(e1, abcd);
+ sha1msg2(msg1, msg0);
+ sha1rnds4(abcd, e0, 0);
+ sha1msg1(msg3, msg0);
+ pxor(msg2, msg0);
+
+ // Rounds 20 - 23
+ sha1nexte(e1, msg1);
+ movdqa(e0, abcd);
+ sha1msg2(msg2, msg1);
+ sha1rnds4(abcd, e1, 1);
+ sha1msg1(msg0, msg1);
+ pxor(msg3, msg1);
+
+ // Rounds 24 - 27
+ sha1nexte(e0, msg2);
+ movdqa(e1, abcd);
+ sha1msg2(msg3, msg2);
+ sha1rnds4(abcd, e0, 1);
+ sha1msg1(msg1, msg2);
+ pxor(msg0, msg2);
+
+ // Rounds 28 - 31
+ sha1nexte(e1, msg3);
+ movdqa(e0, abcd);
+ sha1msg2(msg0, msg3);
+ sha1rnds4(abcd, e1, 1);
+ sha1msg1(msg2, msg3);
+ pxor(msg1, msg3);
+
+ // Rounds 32 - 35
+ sha1nexte(e0, msg0);
+ movdqa(e1, abcd);
+ sha1msg2(msg1, msg0);
+ sha1rnds4(abcd, e0, 1);
+ sha1msg1(msg3, msg0);
+ pxor(msg2, msg0);
+
+ // Rounds 36 - 39
+ sha1nexte(e1, msg1);
+ movdqa(e0, abcd);
+ sha1msg2(msg2, msg1);
+ sha1rnds4(abcd, e1, 1);
+ sha1msg1(msg0, msg1);
+ pxor(msg3, msg1);
+
+ // Rounds 40 - 43
+ sha1nexte(e0, msg2);
+ movdqa(e1, abcd);
+ sha1msg2(msg3, msg2);
+ sha1rnds4(abcd, e0, 2);
+ sha1msg1(msg1, msg2);
+ pxor(msg0, msg2);
+
+ // Rounds 44 - 47
+ sha1nexte(e1, msg3);
+ movdqa(e0, abcd);
+ sha1msg2(msg0, msg3);
+ sha1rnds4(abcd, e1, 2);
+ sha1msg1(msg2, msg3);
+ pxor(msg1, msg3);
+
+ // Rounds 48 - 51
+ sha1nexte(e0, msg0);
+ movdqa(e1, abcd);
+ sha1msg2(msg1, msg0);
+ sha1rnds4(abcd, e0, 2);
+ sha1msg1(msg3, msg0);
+ pxor(msg2, msg0);
+
+ // Rounds 52 - 55
+ sha1nexte(e1, msg1);
+ movdqa(e0, abcd);
+ sha1msg2(msg2, msg1);
+ sha1rnds4(abcd, e1, 2);
+ sha1msg1(msg0, msg1);
+ pxor(msg3, msg1);
+
+ // Rounds 56 - 59
+ sha1nexte(e0, msg2);
+ movdqa(e1, abcd);
+ sha1msg2(msg3, msg2);
+ sha1rnds4(abcd, e0, 2);
+ sha1msg1(msg1, msg2);
+ pxor(msg0, msg2);
+
+ // Rounds 60 - 63
+ sha1nexte(e1, msg3);
+ movdqa(e0, abcd);
+ sha1msg2(msg0, msg3);
+ sha1rnds4(abcd, e1, 3);
+ sha1msg1(msg2, msg3);
+ pxor(msg1, msg3);
+
+ // Rounds 64 - 67
+ sha1nexte(e0, msg0);
+ movdqa(e1, abcd);
+ sha1msg2(msg1, msg0);
+ sha1rnds4(abcd, e0, 3);
+ sha1msg1(msg3, msg0);
+ pxor(msg2, msg0);
+
+ // Rounds 68 - 71
+ sha1nexte(e1, msg1);
+ movdqa(e0, abcd);
+ sha1msg2(msg2, msg1);
+ sha1rnds4(abcd, e1, 3);
+ pxor(msg3, msg1);
+
+ // Rounds 72 - 75
+ sha1nexte(e0, msg2);
+ movdqa(e1, abcd);
+ sha1msg2(msg3, msg2);
+ sha1rnds4(abcd, e0, 3);
+
+ // Rounds 76 - 79
+ sha1nexte(e1, msg3);
+ movdqa(e0, abcd);
+ sha1rnds4(abcd, e1, 3);
+
+ // add current hash values with previously saved
+ movdqu(msg0, Address(rsp, 0));
+ sha1nexte(e0, msg0);
+ movdqu(msg0, Address(rsp, 16));
+ paddd(abcd, msg0);
+
+ if (multi_block) {
+ // increment data pointer and loop if more to process
+ addptr(buf, 64);
+ addptr(ofs, 64);
+ cmpptr(ofs, limit);
+ jcc(Assembler::belowEqual, loop0);
+ movptr(rax, ofs); //return ofs
+ }
+ // write hash values back in the correct order
+ pshufd(abcd, abcd, 0x1b);
+ movdqu(Address(state, 0), abcd);
+ pextrd(Address(state, 16), e0, 3);
+
+ bind(done_hash);
+
+}
+
+// xmm0 (msg) is used as an implicit argument to sh256rnds2
+// and state0 and state1 can never use xmm0 register.
+// ofs and limit are used for multi-block byte array.
+// int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit)
+#ifdef _LP64
+void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0,
+ XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4,
+ Register buf, Register state, Register ofs, Register limit, Register rsp,
+ bool multi_block, XMMRegister shuf_mask) {
+#else
+void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0,
+ XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4,
+ Register buf, Register state, Register ofs, Register limit, Register rsp,
+ bool multi_block) {
+#endif
+ Label start, done_hash, loop0;
+
+ address K256 = StubRoutines::x86::k256_addr();
+ address pshuffle_byte_flip_mask = StubRoutines::x86::pshuffle_byte_flip_mask_addr();
+
+ bind(start);
+ movdqu(state0, Address(state, 0));
+ movdqu(state1, Address(state, 16));
+
+ pshufd(state0, state0, 0xB1);
+ pshufd(state1, state1, 0x1B);
+ movdqa(msgtmp4, state0);
+ palignr(state0, state1, 8);
+ pblendw(state1, msgtmp4, 0xF0);
+
+#ifdef _LP64
+ movdqu(shuf_mask, ExternalAddress(pshuffle_byte_flip_mask));
+#endif
+ lea(rax, ExternalAddress(K256));
+
+ bind(loop0);
+ movdqu(Address(rsp, 0), state0);
+ movdqu(Address(rsp, 16), state1);
+
+ // Rounds 0-3
+ movdqu(msg, Address(buf, 0));
+#ifdef _LP64
+ pshufb(msg, shuf_mask);
+#else
+ pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask));
+#endif
+ movdqa(msgtmp0, msg);
+ paddd(msg, Address(rax, 0));
+ sha256rnds2(state1, state0);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+
+ // Rounds 4-7
+ movdqu(msg, Address(buf, 16));
+#ifdef _LP64
+ pshufb(msg, shuf_mask);
+#else
+ pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask));
+#endif
+ movdqa(msgtmp1, msg);
+ paddd(msg, Address(rax, 16));
+ sha256rnds2(state1, state0);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ sha256msg1(msgtmp0, msgtmp1);
+
+ // Rounds 8-11
+ movdqu(msg, Address(buf, 32));
+#ifdef _LP64
+ pshufb(msg, shuf_mask);
+#else
+ pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask));
+#endif
+ movdqa(msgtmp2, msg);
+ paddd(msg, Address(rax, 32));
+ sha256rnds2(state1, state0);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ sha256msg1(msgtmp1, msgtmp2);
+
+ // Rounds 12-15
+ movdqu(msg, Address(buf, 48));
+#ifdef _LP64
+ pshufb(msg, shuf_mask);
+#else
+ pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask));
+#endif
+ movdqa(msgtmp3, msg);
+ paddd(msg, Address(rax, 48));
+ sha256rnds2(state1, state0);
+ movdqa(msgtmp4, msgtmp3);
+ palignr(msgtmp4, msgtmp2, 4);
+ paddd(msgtmp0, msgtmp4);
+ sha256msg2(msgtmp0, msgtmp3);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ sha256msg1(msgtmp2, msgtmp3);
+
+ // Rounds 16-19
+ movdqa(msg, msgtmp0);
+ paddd(msg, Address(rax, 64));
+ sha256rnds2(state1, state0);
+ movdqa(msgtmp4, msgtmp0);
+ palignr(msgtmp4, msgtmp3, 4);
+ paddd(msgtmp1, msgtmp4);
+ sha256msg2(msgtmp1, msgtmp0);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ sha256msg1(msgtmp3, msgtmp0);
+
+ // Rounds 20-23
+ movdqa(msg, msgtmp1);
+ paddd(msg, Address(rax, 80));
+ sha256rnds2(state1, state0);
+ movdqa(msgtmp4, msgtmp1);
+ palignr(msgtmp4, msgtmp0, 4);
+ paddd(msgtmp2, msgtmp4);
+ sha256msg2(msgtmp2, msgtmp1);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ sha256msg1(msgtmp0, msgtmp1);
+
+ // Rounds 24-27
+ movdqa(msg, msgtmp2);
+ paddd(msg, Address(rax, 96));
+ sha256rnds2(state1, state0);
+ movdqa(msgtmp4, msgtmp2);
+ palignr(msgtmp4, msgtmp1, 4);
+ paddd(msgtmp3, msgtmp4);
+ sha256msg2(msgtmp3, msgtmp2);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ sha256msg1(msgtmp1, msgtmp2);
+
+ // Rounds 28-31
+ movdqa(msg, msgtmp3);
+ paddd(msg, Address(rax, 112));
+ sha256rnds2(state1, state0);
+ movdqa(msgtmp4, msgtmp3);
+ palignr(msgtmp4, msgtmp2, 4);
+ paddd(msgtmp0, msgtmp4);
+ sha256msg2(msgtmp0, msgtmp3);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ sha256msg1(msgtmp2, msgtmp3);
+
+ // Rounds 32-35
+ movdqa(msg, msgtmp0);
+ paddd(msg, Address(rax, 128));
+ sha256rnds2(state1, state0);
+ movdqa(msgtmp4, msgtmp0);
+ palignr(msgtmp4, msgtmp3, 4);
+ paddd(msgtmp1, msgtmp4);
+ sha256msg2(msgtmp1, msgtmp0);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ sha256msg1(msgtmp3, msgtmp0);
+
+ // Rounds 36-39
+ movdqa(msg, msgtmp1);
+ paddd(msg, Address(rax, 144));
+ sha256rnds2(state1, state0);
+ movdqa(msgtmp4, msgtmp1);
+ palignr(msgtmp4, msgtmp0, 4);
+ paddd(msgtmp2, msgtmp4);
+ sha256msg2(msgtmp2, msgtmp1);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ sha256msg1(msgtmp0, msgtmp1);
+
+ // Rounds 40-43
+ movdqa(msg, msgtmp2);
+ paddd(msg, Address(rax, 160));
+ sha256rnds2(state1, state0);
+ movdqa(msgtmp4, msgtmp2);
+ palignr(msgtmp4, msgtmp1, 4);
+ paddd(msgtmp3, msgtmp4);
+ sha256msg2(msgtmp3, msgtmp2);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ sha256msg1(msgtmp1, msgtmp2);
+
+ // Rounds 44-47
+ movdqa(msg, msgtmp3);
+ paddd(msg, Address(rax, 176));
+ sha256rnds2(state1, state0);
+ movdqa(msgtmp4, msgtmp3);
+ palignr(msgtmp4, msgtmp2, 4);
+ paddd(msgtmp0, msgtmp4);
+ sha256msg2(msgtmp0, msgtmp3);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ sha256msg1(msgtmp2, msgtmp3);
+
+ // Rounds 48-51
+ movdqa(msg, msgtmp0);
+ paddd(msg, Address(rax, 192));
+ sha256rnds2(state1, state0);
+ movdqa(msgtmp4, msgtmp0);
+ palignr(msgtmp4, msgtmp3, 4);
+ paddd(msgtmp1, msgtmp4);
+ sha256msg2(msgtmp1, msgtmp0);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ sha256msg1(msgtmp3, msgtmp0);
+
+ // Rounds 52-55
+ movdqa(msg, msgtmp1);
+ paddd(msg, Address(rax, 208));
+ sha256rnds2(state1, state0);
+ movdqa(msgtmp4, msgtmp1);
+ palignr(msgtmp4, msgtmp0, 4);
+ paddd(msgtmp2, msgtmp4);
+ sha256msg2(msgtmp2, msgtmp1);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+
+ // Rounds 56-59
+ movdqa(msg, msgtmp2);
+ paddd(msg, Address(rax, 224));
+ sha256rnds2(state1, state0);
+ movdqa(msgtmp4, msgtmp2);
+ palignr(msgtmp4, msgtmp1, 4);
+ paddd(msgtmp3, msgtmp4);
+ sha256msg2(msgtmp3, msgtmp2);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+
+ // Rounds 60-63
+ movdqa(msg, msgtmp3);
+ paddd(msg, Address(rax, 240));
+ sha256rnds2(state1, state0);
+ pshufd(msg, msg, 0x0E);
+ sha256rnds2(state0, state1);
+ movdqu(msg, Address(rsp, 0));
+ paddd(state0, msg);
+ movdqu(msg, Address(rsp, 16));
+ paddd(state1, msg);
+
+ if (multi_block) {
+ // increment data pointer and loop if more to process
+ addptr(buf, 64);
+ addptr(ofs, 64);
+ cmpptr(ofs, limit);
+ jcc(Assembler::belowEqual, loop0);
+ movptr(rax, ofs); //return ofs
+ }
+
+ pshufd(state0, state0, 0x1B);
+ pshufd(state1, state1, 0xB1);
+ movdqa(msgtmp4, state0);
+ pblendw(state0, state1, 0xF0);
+ palignr(state1, msgtmp4, 8);
+
+ movdqu(Address(state, 0), state0);
+ movdqu(Address(state, 16), state1);
+
+ bind(done_hash);
+
+}
diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp
index 894e4cb3319..f5652df8b31 100644
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp
@@ -3068,6 +3068,136 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
+ address generate_upper_word_mask() {
+ __ align(64);
+ StubCodeMark mark(this, "StubRoutines", "upper_word_mask");
+ address start = __ pc();
+ __ emit_data(0x00000000, relocInfo::none, 0);
+ __ emit_data(0x00000000, relocInfo::none, 0);
+ __ emit_data(0x00000000, relocInfo::none, 0);
+ __ emit_data(0xFFFFFFFF, relocInfo::none, 0);
+ return start;
+ }
+
+ address generate_shuffle_byte_flip_mask() {
+ __ align(64);
+ StubCodeMark mark(this, "StubRoutines", "shuffle_byte_flip_mask");
+ address start = __ pc();
+ __ emit_data(0x0c0d0e0f, relocInfo::none, 0);
+ __ emit_data(0x08090a0b, relocInfo::none, 0);
+ __ emit_data(0x04050607, relocInfo::none, 0);
+ __ emit_data(0x00010203, relocInfo::none, 0);
+ return start;
+ }
+
+ // ofs and limit are use for multi-block byte array.
+ // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit)
+ address generate_sha1_implCompress(bool multi_block, const char *name) {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", name);
+ address start = __ pc();
+
+ Register buf = rax;
+ Register state = rdx;
+ Register ofs = rcx;
+ Register limit = rdi;
+
+ const Address buf_param(rbp, 8 + 0);
+ const Address state_param(rbp, 8 + 4);
+ const Address ofs_param(rbp, 8 + 8);
+ const Address limit_param(rbp, 8 + 12);
+
+ const XMMRegister abcd = xmm0;
+ const XMMRegister e0 = xmm1;
+ const XMMRegister e1 = xmm2;
+ const XMMRegister msg0 = xmm3;
+
+ const XMMRegister msg1 = xmm4;
+ const XMMRegister msg2 = xmm5;
+ const XMMRegister msg3 = xmm6;
+ const XMMRegister shuf_mask = xmm7;
+
+ __ enter();
+ __ subptr(rsp, 8 * wordSize);
+ if (multi_block) {
+ __ push(limit);
+ }
+ __ movptr(buf, buf_param);
+ __ movptr(state, state_param);
+ if (multi_block) {
+ __ movptr(ofs, ofs_param);
+ __ movptr(limit, limit_param);
+ }
+
+ __ fast_sha1(abcd, e0, e1, msg0, msg1, msg2, msg3, shuf_mask,
+ buf, state, ofs, limit, rsp, multi_block);
+
+ if (multi_block) {
+ __ pop(limit);
+ }
+ __ addptr(rsp, 8 * wordSize);
+ __ leave();
+ __ ret(0);
+ return start;
+ }
+
+ address generate_pshuffle_byte_flip_mask() {
+ __ align(64);
+ StubCodeMark mark(this, "StubRoutines", "pshuffle_byte_flip_mask");
+ address start = __ pc();
+ __ emit_data(0x00010203, relocInfo::none, 0);
+ __ emit_data(0x04050607, relocInfo::none, 0);
+ __ emit_data(0x08090a0b, relocInfo::none, 0);
+ __ emit_data(0x0c0d0e0f, relocInfo::none, 0);
+ return start;
+ }
+
+ // ofs and limit are use for multi-block byte array.
+ // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit)
+ address generate_sha256_implCompress(bool multi_block, const char *name) {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", name);
+ address start = __ pc();
+
+ Register buf = rbx;
+ Register state = rsi;
+ Register ofs = rdx;
+ Register limit = rcx;
+
+ const Address buf_param(rbp, 8 + 0);
+ const Address state_param(rbp, 8 + 4);
+ const Address ofs_param(rbp, 8 + 8);
+ const Address limit_param(rbp, 8 + 12);
+
+ const XMMRegister msg = xmm0;
+ const XMMRegister state0 = xmm1;
+ const XMMRegister state1 = xmm2;
+ const XMMRegister msgtmp0 = xmm3;
+
+ const XMMRegister msgtmp1 = xmm4;
+ const XMMRegister msgtmp2 = xmm5;
+ const XMMRegister msgtmp3 = xmm6;
+ const XMMRegister msgtmp4 = xmm7;
+
+ __ enter();
+ __ subptr(rsp, 8 * wordSize);
+ handleSOERegisters(true /*saving*/);
+ __ movptr(buf, buf_param);
+ __ movptr(state, state_param);
+ if (multi_block) {
+ __ movptr(ofs, ofs_param);
+ __ movptr(limit, limit_param);
+ }
+
+ __ fast_sha256(msg, state0, state1, msgtmp0, msgtmp1, msgtmp2, msgtmp3, msgtmp4,
+ buf, state, ofs, limit, rsp, multi_block);
+
+ handleSOERegisters(false);
+ __ addptr(rsp, 8 * wordSize);
+ __ leave();
+ __ ret(0);
+ return start;
+ }
// byte swap x86 long
address generate_ghash_long_swap_mask() {
@@ -3772,6 +3902,19 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_counterMode_AESCrypt = generate_counterMode_AESCrypt_Parallel();
}
+ if (UseSHA1Intrinsics) {
+ StubRoutines::x86::_upper_word_mask_addr = generate_upper_word_mask();
+ StubRoutines::x86::_shuffle_byte_flip_mask_addr = generate_shuffle_byte_flip_mask();
+ StubRoutines::_sha1_implCompress = generate_sha1_implCompress(false, "sha1_implCompress");
+ StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB");
+ }
+ if (UseSHA256Intrinsics) {
+ StubRoutines::x86::_k256_adr = (address)StubRoutines::x86::_k256;
+ StubRoutines::x86::_pshuffle_byte_flip_mask_addr = generate_pshuffle_byte_flip_mask();
+ StubRoutines::_sha256_implCompress = generate_sha256_implCompress(false, "sha256_implCompress");
+ StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB");
+ }
+
// Generate GHASH intrinsics code
if (UseGHASHIntrinsics) {
StubRoutines::x86::_ghash_long_swap_mask_addr = generate_ghash_long_swap_mask();
diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
index db518d804db..2f4adc88506 100644
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
@@ -3695,6 +3695,133 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
+ address generate_upper_word_mask() {
+ __ align(64);
+ StubCodeMark mark(this, "StubRoutines", "upper_word_mask");
+ address start = __ pc();
+ __ emit_data64(0x0000000000000000, relocInfo::none);
+ __ emit_data64(0xFFFFFFFF00000000, relocInfo::none);
+ return start;
+ }
+
+ address generate_shuffle_byte_flip_mask() {
+ __ align(64);
+ StubCodeMark mark(this, "StubRoutines", "shuffle_byte_flip_mask");
+ address start = __ pc();
+ __ emit_data64(0x08090a0b0c0d0e0f, relocInfo::none);
+ __ emit_data64(0x0001020304050607, relocInfo::none);
+ return start;
+ }
+
+ // ofs and limit are use for multi-block byte array.
+ // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit)
+ address generate_sha1_implCompress(bool multi_block, const char *name) {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", name);
+ address start = __ pc();
+
+ Register buf = c_rarg0;
+ Register state = c_rarg1;
+ Register ofs = c_rarg2;
+ Register limit = c_rarg3;
+
+ const XMMRegister abcd = xmm0;
+ const XMMRegister e0 = xmm1;
+ const XMMRegister e1 = xmm2;
+ const XMMRegister msg0 = xmm3;
+
+ const XMMRegister msg1 = xmm4;
+ const XMMRegister msg2 = xmm5;
+ const XMMRegister msg3 = xmm6;
+ const XMMRegister shuf_mask = xmm7;
+
+ __ enter();
+
+#ifdef _WIN64
+ // save the xmm registers which must be preserved 6-7
+ __ subptr(rsp, 4 * wordSize);
+ __ movdqu(Address(rsp, 0), xmm6);
+ __ movdqu(Address(rsp, 2 * wordSize), xmm7);
+#endif
+
+ __ subptr(rsp, 4 * wordSize);
+
+ __ fast_sha1(abcd, e0, e1, msg0, msg1, msg2, msg3, shuf_mask,
+ buf, state, ofs, limit, rsp, multi_block);
+
+ __ addptr(rsp, 4 * wordSize);
+#ifdef _WIN64
+ // restore xmm regs belonging to calling function
+ __ movdqu(xmm6, Address(rsp, 0));
+ __ movdqu(xmm7, Address(rsp, 2 * wordSize));
+ __ addptr(rsp, 4 * wordSize);
+#endif
+
+ __ leave();
+ __ ret(0);
+ return start;
+ }
+
+ address generate_pshuffle_byte_flip_mask() {
+ __ align(64);
+ StubCodeMark mark(this, "StubRoutines", "pshuffle_byte_flip_mask");
+ address start = __ pc();
+ __ emit_data64(0x0405060700010203, relocInfo::none);
+ __ emit_data64(0x0c0d0e0f08090a0b, relocInfo::none);
+ return start;
+ }
+
+// ofs and limit are use for multi-block byte array.
+// int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit)
+ address generate_sha256_implCompress(bool multi_block, const char *name) {
+ __ align(CodeEntryAlignment);
+ StubCodeMark mark(this, "StubRoutines", name);
+ address start = __ pc();
+
+ Register buf = c_rarg0;
+ Register state = c_rarg1;
+ Register ofs = c_rarg2;
+ Register limit = c_rarg3;
+
+ const XMMRegister msg = xmm0;
+ const XMMRegister state0 = xmm1;
+ const XMMRegister state1 = xmm2;
+ const XMMRegister msgtmp0 = xmm3;
+
+ const XMMRegister msgtmp1 = xmm4;
+ const XMMRegister msgtmp2 = xmm5;
+ const XMMRegister msgtmp3 = xmm6;
+ const XMMRegister msgtmp4 = xmm7;
+
+ const XMMRegister shuf_mask = xmm8;
+
+ __ enter();
+#ifdef _WIN64
+ // save the xmm registers which must be preserved 6-7
+ __ subptr(rsp, 6 * wordSize);
+ __ movdqu(Address(rsp, 0), xmm6);
+ __ movdqu(Address(rsp, 2 * wordSize), xmm7);
+ __ movdqu(Address(rsp, 4 * wordSize), xmm8);
+#endif
+
+ __ subptr(rsp, 4 * wordSize);
+
+ __ fast_sha256(msg, state0, state1, msgtmp0, msgtmp1, msgtmp2, msgtmp3, msgtmp4,
+ buf, state, ofs, limit, rsp, multi_block, shuf_mask);
+
+ __ addptr(rsp, 4 * wordSize);
+#ifdef _WIN64
+ // restore xmm regs belonging to calling function
+ __ movdqu(xmm6, Address(rsp, 0));
+ __ movdqu(xmm7, Address(rsp, 2 * wordSize));
+ __ movdqu(xmm8, Address(rsp, 4 * wordSize));
+ __ addptr(rsp, 6 * wordSize);
+#endif
+ __ leave();
+ __ ret(0);
+ return start;
+ }
+
// This is a version of CTR/AES crypt which does 6 blocks in a loop at a time
// to hide instruction latency
//
@@ -4974,6 +5101,19 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_counterMode_AESCrypt = generate_counterMode_AESCrypt_Parallel();
}
+ if (UseSHA1Intrinsics) {
+ StubRoutines::x86::_upper_word_mask_addr = generate_upper_word_mask();
+ StubRoutines::x86::_shuffle_byte_flip_mask_addr = generate_shuffle_byte_flip_mask();
+ StubRoutines::_sha1_implCompress = generate_sha1_implCompress(false, "sha1_implCompress");
+ StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB");
+ }
+ if (UseSHA256Intrinsics) {
+ StubRoutines::x86::_k256_adr = (address)StubRoutines::x86::_k256;
+ StubRoutines::x86::_pshuffle_byte_flip_mask_addr = generate_pshuffle_byte_flip_mask();
+ StubRoutines::_sha256_implCompress = generate_sha256_implCompress(false, "sha256_implCompress");
+ StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB");
+ }
+
// Generate GHASH intrinsics code
if (UseGHASHIntrinsics) {
StubRoutines::x86::_ghash_long_swap_mask_addr = generate_ghash_long_swap_mask();
diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp
index 3bc199b1db5..141fbf048eb 100644
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp
@@ -29,6 +29,12 @@
#include "runtime/thread.inline.hpp"
#include "crc32c.h"
+#ifdef _MSC_VER
+#define ALIGNED_(x) __declspec(align(x))
+#else
+#define ALIGNED_(x) __attribute__ ((aligned(x)))
+#endif
+
// Implementation of the platform-specific part of StubRoutines - for
// a description of how to extend it, see the stubRoutines.hpp file.
@@ -37,6 +43,10 @@ address StubRoutines::x86::_key_shuffle_mask_addr = NULL;
address StubRoutines::x86::_counter_shuffle_mask_addr = NULL;
address StubRoutines::x86::_ghash_long_swap_mask_addr = NULL;
address StubRoutines::x86::_ghash_byte_swap_mask_addr = NULL;
+address StubRoutines::x86::_upper_word_mask_addr = NULL;
+address StubRoutines::x86::_shuffle_byte_flip_mask_addr = NULL;
+address StubRoutines::x86::_k256_adr = NULL;
+address StubRoutines::x86::_pshuffle_byte_flip_mask_addr = NULL;
uint64_t StubRoutines::x86::_crc_by128_masks[] =
{
@@ -236,3 +246,23 @@ void StubRoutines::x86::generate_CRC32C_table(bool is_pclmulqdq_table_supported)
_crc32c_table = (juint*)pclmulqdq_table;
}
}
+
+ALIGNED_(64) juint StubRoutines::x86::_k256[] =
+{
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+ 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+ 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+ 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+ 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+ 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+ 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+ 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+ 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+ 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+ 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+ 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+ 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+ 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+ 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp
index 5b2bf4bdf91..4c9ce0153fd 100644
--- a/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp
@@ -46,6 +46,17 @@
static address _ghash_long_swap_mask_addr;
static address _ghash_byte_swap_mask_addr;
+ // upper word mask for sha1
+ static address _upper_word_mask_addr;
+ // byte flip mask for sha1
+ static address _shuffle_byte_flip_mask_addr;
+
+ //k256 table for sha256
+ static juint _k256[];
+ static address _k256_adr;
+ // byte flip mask for sha256
+ static address _pshuffle_byte_flip_mask_addr;
+
public:
static address verify_mxcsr_entry() { return _verify_mxcsr_entry; }
static address key_shuffle_mask_addr() { return _key_shuffle_mask_addr; }
@@ -53,5 +64,9 @@
static address crc_by128_masks_addr() { return (address)_crc_by128_masks; }
static address ghash_long_swap_mask_addr() { return _ghash_long_swap_mask_addr; }
static address ghash_byte_swap_mask_addr() { return _ghash_byte_swap_mask_addr; }
+ static address upper_word_mask_addr() { return _upper_word_mask_addr; }
+ static address shuffle_byte_flip_mask_addr() { return _shuffle_byte_flip_mask_addr; }
+ static address k256_addr() { return _k256_adr; }
+ static address pshuffle_byte_flip_mask_addr() { return _pshuffle_byte_flip_mask_addr; }
static void generate_CRC32C_table(bool is_pclmulqdq_supported);
#endif // CPU_X86_VM_STUBROUTINES_X86_32_HPP
diff --git a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp
index 40e6e431882..713ee14472d 100644
--- a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp
@@ -68,10 +68,11 @@
declare_constant(VM_Version::CPU_AVX512DQ) \
declare_constant(VM_Version::CPU_AVX512PF) \
declare_constant(VM_Version::CPU_AVX512ER) \
- declare_constant(VM_Version::CPU_AVX512CD) \
- declare_constant(VM_Version::CPU_AVX512BW)
+ declare_constant(VM_Version::CPU_AVX512CD)
#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
- declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL)
+ declare_preprocessor_constant("VM_Version::CPU_AVX512BW", CPU_AVX512BW) \
+ declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) \
+ declare_preprocessor_constant("VM_Version::CPU_SHA", CPU_SHA)
#endif // CPU_X86_VM_VMSTRUCTS_X86_HPP
diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
index 0bfd8e8f3e0..7472ad4def1 100644
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
@@ -577,7 +577,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%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%s",
cores_per_cpu(), threads_per_core(),
cpu_family(), _model, _stepping,
(supports_cmov() ? ", cmov" : ""),
@@ -608,7 +608,8 @@ void VM_Version::get_processor_features() {
(supports_bmi1() ? ", bmi1" : ""),
(supports_bmi2() ? ", bmi2" : ""),
(supports_adx() ? ", adx" : ""),
- (supports_evex() ? ", evex" : ""));
+ (supports_evex() ? ", evex" : ""),
+ (supports_sha() ? ", sha" : ""));
_features_string = os::strdup(buf);
// UseSSE is set to the smaller of what hardware supports and what
@@ -730,17 +731,29 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
}
- if (UseSHA) {
+ if (supports_sha()) {
+ if (FLAG_IS_DEFAULT(UseSHA)) {
+ UseSHA = true;
+ }
+ } else if (UseSHA) {
warning("SHA instructions are not available on this CPU");
FLAG_SET_DEFAULT(UseSHA, false);
}
- if (UseSHA1Intrinsics) {
+ if (UseSHA) {
+ if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) {
+ FLAG_SET_DEFAULT(UseSHA1Intrinsics, true);
+ }
+ } else if (UseSHA1Intrinsics) {
warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
}
- if (UseSHA256Intrinsics) {
+ if (UseSHA) {
+ if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
+ FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
+ }
+ } else if (UseSHA256Intrinsics) {
warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU.");
FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
}
@@ -750,6 +763,10 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
}
+ if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) {
+ FLAG_SET_DEFAULT(UseSHA, false);
+ }
+
if (UseAdler32Intrinsics) {
warning("Adler32Intrinsics not available on this CPU.");
FLAG_SET_DEFAULT(UseAdler32Intrinsics, false);
diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp
index 77550a96a4c..8dca27b546b 100644
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp
@@ -221,7 +221,7 @@ class VM_Version : public Abstract_VM_Version {
avx512pf : 1,
avx512er : 1,
avx512cd : 1,
- : 1,
+ sha : 1,
avx512bw : 1,
avx512vl : 1;
} bits;
@@ -282,11 +282,13 @@ protected:
CPU_AVX512DQ = (1 << 27),
CPU_AVX512PF = (1 << 28),
CPU_AVX512ER = (1 << 29),
- CPU_AVX512CD = (1 << 30),
- CPU_AVX512BW = (1 << 31)
+ CPU_AVX512CD = (1 << 30)
+ // Keeping sign bit 31 unassigned.
};
-#define CPU_AVX512VL UCONST64(0x100000000) // EVEX instructions with smaller vector length : enums are limited to 32bit
+#define CPU_AVX512BW ((uint64_t)UCONST64(0x100000000)) // enums are limited to 31 bit
+#define CPU_AVX512VL ((uint64_t)UCONST64(0x200000000)) // EVEX instructions with smaller vector length
+#define CPU_SHA ((uint64_t)UCONST64(0x400000000)) // SHA instructions
enum Extended_Family {
// AMD
@@ -516,6 +518,8 @@ protected:
result |= CPU_ADX;
if(_cpuid_info.sef_cpuid7_ebx.bits.bmi2 != 0)
result |= CPU_BMI2;
+ if (_cpuid_info.sef_cpuid7_ebx.bits.sha != 0)
+ result |= CPU_SHA;
if(_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0)
result |= CPU_LZCNT;
// for Intel, ecx.bits.misalignsse bit (bit 8) indicates support for prefetchw
@@ -721,6 +725,7 @@ public:
static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); }
static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); }
static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); }
+ static bool supports_sha() { return (_features & CPU_SHA) != 0; }
// Intel features
static bool is_intel_family_core() { return is_intel() &&
extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java
index 972aea94231..3fb9046711b 100644
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java
@@ -203,7 +203,8 @@ public class AMD64 extends Architecture {
AVX512ER,
AVX512CD,
AVX512BW,
- AVX512VL
+ AVX512VL,
+ SHA
}
private final EnumSet features;
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java
index 69a31604560..b2fec728519 100644
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java
@@ -122,6 +122,9 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto
if ((config.vmVersionFeatures & config.amd64AVX512VL) != 0) {
features.add(AMD64.CPUFeature.AVX512VL);
}
+ if ((config.vmVersionFeatures & config.amd64SHA) != 0) {
+ features.add(AMD64.CPUFeature.SHA);
+ }
return features;
}
diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java
index 88da9e5b32a..744ec27c044 100644
--- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java
+++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java
@@ -945,6 +945,7 @@ public class HotSpotVMConfig {
@HotSpotVMConstant(name = "VM_Version::CPU_AVX512CD", archs = {"amd64"}) @Stable public long amd64AVX512CD;
@HotSpotVMConstant(name = "VM_Version::CPU_AVX512BW", archs = {"amd64"}) @Stable public long amd64AVX512BW;
@HotSpotVMConstant(name = "VM_Version::CPU_AVX512VL", archs = {"amd64"}) @Stable public long amd64AVX512VL;
+ @HotSpotVMConstant(name = "VM_Version::CPU_SHA", archs = {"amd64"}) @Stable public long amd64SHA;
// SPARC specific values
@HotSpotVMConstant(name = "VM_Version::vis3_instructions_m", archs = {"sparc"}) @Stable public int sparcVis3Instructions;
diff --git a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
index 99a7fbd3ac9..9c754133a40 100644
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp
@@ -639,11 +639,12 @@
declare_constant(VM_Version::CPU_AVX512DQ) \
declare_constant(VM_Version::CPU_AVX512PF) \
declare_constant(VM_Version::CPU_AVX512ER) \
- declare_constant(VM_Version::CPU_AVX512CD) \
- declare_constant(VM_Version::CPU_AVX512BW)
+ declare_constant(VM_Version::CPU_AVX512CD)
#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
- declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL)
+ declare_preprocessor_constant("VM_Version::CPU_AVX512BW", CPU_AVX512BW) \
+ declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) \
+ declare_preprocessor_constant("VM_Version::CPU_SHA", CPU_SHA)
#endif // TARGET_ARCH_x86
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
index 113a9f71ab6..d1a72e7027a 100644
--- a/hotspot/src/share/vm/runtime/globals.hpp
+++ b/hotspot/src/share/vm/runtime/globals.hpp
@@ -725,7 +725,7 @@ public:
\
product(bool, UseSHA, false, \
"Control whether SHA instructions can be used " \
- "on SPARC and on ARM") \
+ "on SPARC, on ARM and on x86") \
\
product(bool, UseGHASHIntrinsics, false, \
"Use intrinsics for GHASH versions of crypto") \
From d30d68717818485dad96159ebd2c313e3071839f Mon Sep 17 00:00:00 2001
From: Zoltan Majo
Date: Fri, 4 Mar 2016 08:53:59 +0100
Subject: [PATCH 057/311] 8150839: Adjust the number of compiler threads for
32-bit platforms
Set the number of compiler threads to 3 on 32-bit platforms.
Reviewed-by: iveresov
---
.../share/vm/runtime/advancedThresholdPolicy.cpp | 15 ++++++++++++++-
hotspot/src/share/vm/runtime/arguments.cpp | 2 ++
.../share/vm/runtime/simpleThresholdPolicy.cpp | 6 ++++++
3 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
index 1d046e6abe0..4ecfa0e913c 100644
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
@@ -42,17 +42,30 @@ void AdvancedThresholdPolicy::print_specific(EventType type, methodHandle mh, me
}
void AdvancedThresholdPolicy::initialize() {
+ int count = CICompilerCount;
+#ifdef _LP64
// Turn on ergonomic compiler count selection
if (FLAG_IS_DEFAULT(CICompilerCountPerCPU) && FLAG_IS_DEFAULT(CICompilerCount)) {
FLAG_SET_DEFAULT(CICompilerCountPerCPU, true);
}
- int count = CICompilerCount;
if (CICompilerCountPerCPU) {
// Simple log n seems to grow too slowly for tiered, try something faster: log n * log log n
int log_cpu = log2_intptr(os::active_processor_count());
int loglog_cpu = log2_intptr(MAX2(log_cpu, 1));
count = MAX2(log_cpu * loglog_cpu, 1) * 3 / 2;
}
+#else
+ // On 32-bit systems, the number of compiler threads is limited to 3.
+ // On these systems, the virtual address space available to the JVM
+ // is usually limited to 2-4 GB (the exact value depends on the platform).
+ // As the compilers (especially C2) can consume a large amount of
+ // memory, scaling the number of compiler threads with the number of
+ // available cores can result in the exhaustion of the address space
+ /// available to the VM and thus cause the VM to crash.
+ if (FLAG_IS_DEFAULT(CICompilerCount)) {
+ count = 3;
+ }
+#endif
set_c1_count(MAX2(count / 3, 1));
set_c2_count(MAX2(count - c1_count(), 1));
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 006e3c94739..88fe092af1c 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -2472,9 +2472,11 @@ bool Arguments::check_vm_args_consistency() {
status = false;
}
+#ifdef _LP64
if (!FLAG_IS_DEFAULT(CICompilerCount) && !FLAG_IS_DEFAULT(CICompilerCountPerCPU) && CICompilerCountPerCPU) {
warning("The VM option CICompilerCountPerCPU overrides CICompilerCount.");
}
+#endif
#ifndef SUPPORT_RESERVED_STACK_AREA
if (StackReservedPages != 0) {
diff --git a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp
index 187d3b1e208..3f8b76c9327 100644
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp
@@ -138,9 +138,15 @@ void SimpleThresholdPolicy::initialize() {
FLAG_SET_DEFAULT(CICompilerCount, 3);
}
int count = CICompilerCount;
+#ifdef _LP64
+ // On 64-bit systems, scale the number of compiler threads with
+ // the number of cores available on the system. Scaling is not
+ // performed on 32-bit systems because it can lead to exhaustion
+ // of the virtual memory address space available to the JVM.
if (CICompilerCountPerCPU) {
count = MAX2(log2_intptr(os::active_processor_count()), 1) * 3 / 2;
}
+#endif
set_c1_count(MAX2(count / 3, 1));
set_c2_count(MAX2(count - c1_count(), 1));
FLAG_SET_ERGO(intx, CICompilerCount, c1_count() + c2_count());
From 29b4b2182cb6944beda92b121f5006bb718230df Mon Sep 17 00:00:00 2001
From: Rahul Raghavan
Date: Fri, 4 Mar 2016 01:18:08 -0800
Subject: [PATCH 058/311] 8140721: ProfilerNumberOf*Methods flags should be
diagnostic
Converted four ProfilerNumberOf*Methods flags from develop to diagnostic.
Reviewed-by: twisti
---
hotspot/src/share/vm/runtime/globals.hpp | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
index ce36ff1db49..ffff2be7ff0 100644
--- a/hotspot/src/share/vm/runtime/globals.hpp
+++ b/hotspot/src/share/vm/runtime/globals.hpp
@@ -3092,16 +3092,16 @@ public:
develop(intx, MethodHistogramCutoff, 100, \
"The cutoff value for method invocation histogram (+CountCalls)") \
\
- develop(intx, ProfilerNumberOfInterpretedMethods, 25, \
+ diagnostic(intx, ProfilerNumberOfInterpretedMethods, 25, \
"Number of interpreted methods to show in profile") \
\
- develop(intx, ProfilerNumberOfCompiledMethods, 25, \
+ diagnostic(intx, ProfilerNumberOfCompiledMethods, 25, \
"Number of compiled methods to show in profile") \
\
- develop(intx, ProfilerNumberOfStubMethods, 25, \
+ diagnostic(intx, ProfilerNumberOfStubMethods, 25, \
"Number of stub methods to show in profile") \
\
- develop(intx, ProfilerNumberOfRuntimeStubNodes, 25, \
+ diagnostic(intx, ProfilerNumberOfRuntimeStubNodes, 25, \
"Number of runtime stub nodes to show in profile") \
\
product(intx, ProfileIntervalsTicks, 100, \
From 1c2427a1827c7d21af03082041612d4f454be25b Mon Sep 17 00:00:00 2001
From: Gustavo Romero
Date: Mon, 7 Mar 2016 10:03:06 -0300
Subject: [PATCH 059/311] 8150353: PPC64LE: Support RTM on linux
Reviewed-by: mdoerr, kvn
---
.../src/cpu/ppc/vm/globalDefinitions_ppc.hpp | 2 +-
hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp | 11 ++++-
hotspot/src/os/linux/vm/os_linux.cpp | 45 +++++++++++++++++++
hotspot/src/os/linux/vm/os_linux.hpp | 13 ++++++
hotspot/src/share/vm/opto/compile.hpp | 4 ++
5 files changed, 73 insertions(+), 2 deletions(-)
diff --git a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp
index ba981816f4a..f8fe437547d 100644
--- a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp
+++ b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp
@@ -47,7 +47,7 @@ const bool CCallingConventionRequiresIntsAsLongs = true;
// The expected size in bytes of a cache line, used to pad data structures.
#define DEFAULT_CACHE_LINE_SIZE 128
-#if defined(COMPILER2) && defined(AIX)
+#if defined(COMPILER2) && (defined(AIX) || defined(linux))
// Include Transactional Memory lock eliding optimization
#define INCLUDE_RTM_OPT 1
#endif
diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp
index 63c0e30a913..6743b2967f9 100644
--- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp
@@ -255,7 +255,16 @@ void VM_Version::initialize() {
}
#endif
#ifdef linux
- // TODO: check kernel version (we currently have too old versions only)
+ // At least Linux kernel 4.2, as the problematic behavior of syscalls
+ // being called in the middle of a transaction has been addressed.
+ // Please, refer to commit b4b56f9ecab40f3b4ef53e130c9f6663be491894
+ // in Linux kernel source tree: https://goo.gl/Kc5i7A
+ if (os::Linux::os_version_is_known()) {
+ if (os::Linux::os_version() >= 0x040200)
+ os_too_old = false;
+ } else {
+ vm_exit_during_initialization("RTM can not be enabled: kernel version is unknown.");
+ }
#endif
if (os_too_old) {
vm_exit_during_initialization("RTM is not supported on this OS version.");
diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp
index d46a1146dd7..f3896ed96a0 100644
--- a/hotspot/src/os/linux/vm/os_linux.cpp
+++ b/hotspot/src/os/linux/vm/os_linux.cpp
@@ -144,6 +144,7 @@ pthread_t os::Linux::_main_thread;
int os::Linux::_page_size = -1;
const int os::Linux::_vm_default_page_size = (8 * K);
bool os::Linux::_supports_fast_thread_cpu_time = false;
+uint32_t os::Linux::_os_version = 0;
const char * os::Linux::_glibc_version = NULL;
const char * os::Linux::_libpthread_version = NULL;
pthread_condattr_t os::Linux::_condattr[1];
@@ -4356,6 +4357,48 @@ jlong os::Linux::fast_thread_cpu_time(clockid_t clockid) {
return (tp.tv_sec * NANOSECS_PER_SEC) + tp.tv_nsec;
}
+void os::Linux::initialize_os_info() {
+ assert(_os_version == 0, "OS info already initialized");
+
+ struct utsname _uname;
+
+ uint32_t major;
+ uint32_t minor;
+ uint32_t fix;
+
+ int rc;
+
+ // Kernel version is unknown if
+ // verification below fails.
+ _os_version = 0x01000000;
+
+ rc = uname(&_uname);
+ if (rc != -1) {
+
+ rc = sscanf(_uname.release,"%d.%d.%d", &major, &minor, &fix);
+ if (rc == 3) {
+
+ if (major < 256 && minor < 256 && fix < 256) {
+ // Kernel version format is as expected,
+ // set it overriding unknown state.
+ _os_version = (major << 16) |
+ (minor << 8 ) |
+ (fix << 0 ) ;
+ }
+ }
+ }
+}
+
+uint32_t os::Linux::os_version() {
+ assert(_os_version != 0, "not initialized");
+ return _os_version & 0x00FFFFFF;
+}
+
+bool os::Linux::os_version_is_known() {
+ assert(_os_version != 0, "not initialized");
+ return _os_version & 0x01000000 ? false : true;
+}
+
/////
// glibc on Linux platform uses non-documented flag
// to indicate, that some special sort of signal
@@ -4578,6 +4621,8 @@ void os::init(void) {
Linux::initialize_system_info();
+ Linux::initialize_os_info();
+
// main_thread points to the aboriginal thread
Linux::_main_thread = pthread_self();
diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp
index 1dcaafefd11..68e1968d2a1 100644
--- a/hotspot/src/os/linux/vm/os_linux.hpp
+++ b/hotspot/src/os/linux/vm/os_linux.hpp
@@ -56,6 +56,15 @@ class Linux {
static GrowableArray* _cpu_to_node;
+ // 0x00000000 = uninitialized,
+ // 0x01000000 = kernel version unknown,
+ // otherwise a 32-bit number:
+ // Ox00AABBCC
+ // AA, Major Version
+ // BB, Minor Version
+ // CC, Fix Version
+ static uint32_t _os_version;
+
protected:
static julong _physical_memory;
@@ -198,6 +207,10 @@ class Linux {
static jlong fast_thread_cpu_time(clockid_t clockid);
+ static void initialize_os_info();
+ static bool os_version_is_known();
+ static uint32_t os_version();
+
// pthread_cond clock suppport
private:
static pthread_condattr_t _condattr[1];
diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp
index 40724fbd6b7..343574e68f3 100644
--- a/hotspot/src/share/vm/opto/compile.hpp
+++ b/hotspot/src/share/vm/opto/compile.hpp
@@ -1118,7 +1118,11 @@ class Compile : public Phase {
bool in_scratch_emit_size() const { return _in_scratch_emit_size; }
enum ScratchBufferBlob {
+#if defined(PPC64)
+ MAX_inst_size = 2048,
+#else
MAX_inst_size = 1024,
+#endif
MAX_locs_size = 128, // number of relocInfo elements
MAX_const_size = 128,
MAX_stubs_size = 128
From d4b4dca194fbe01fec2c8576ea93f8129e0e4023 Mon Sep 17 00:00:00 2001
From: Mikael Vidstedt
Date: Mon, 7 Mar 2016 15:03:48 -0800
Subject: [PATCH 060/311] 8151002: Make Assembler methods vextract and vinsert
match actual instructions
Reviewed-by: kvn, vlivanov, mcberg
---
hotspot/src/cpu/x86/vm/assembler_x86.cpp | 130 ++++++++-----
hotspot/src/cpu/x86/vm/assembler_x86.hpp | 50 +++--
hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp | 20 +-
hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp | 131 ++++++++++++-
.../src/cpu/x86/vm/sharedRuntime_x86_32.cpp | 8 +-
.../src/cpu/x86/vm/sharedRuntime_x86_64.cpp | 8 +-
.../src/cpu/x86/vm/stubGenerator_x86_64.cpp | 4 +-
hotspot/src/cpu/x86/vm/vm_version_x86.cpp | 4 +-
hotspot/src/cpu/x86/vm/x86.ad | 184 +++++++++---------
9 files changed, 342 insertions(+), 197 deletions(-)
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp
index 65f2da7ecd0..ffdd9fe2338 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -5699,8 +5699,9 @@ void Assembler::vpxor(XMMRegister dst, XMMRegister nds, Address src, int vector_
}
-void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src) {
+void Assembler::vinsertf128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_avx(), "");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit;
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
@@ -5709,11 +5710,12 @@ void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src)
emit_int8((unsigned char)(0xC0 | encode));
// 0x00 - insert into lower 128 bits
// 0x01 - insert into upper 128 bits
- emit_int8(0x01);
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value) {
+void Assembler::vinsertf64x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_evex(), "");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
@@ -5721,26 +5723,29 @@ void Assembler::vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src,
emit_int8((unsigned char)(0xC0 | encode));
// 0x00 - insert into lower 256 bits
// 0x01 - insert into upper 256 bits
- emit_int8(value & 0x01);
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vinsertf64x4h(XMMRegister dst, Address src, int value) {
+void Assembler::vinsertf64x4(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) {
assert(VM_Version::supports_evex(), "");
assert(dst != xnoreg, "sanity");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
InstructionMark im(this);
InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
+ int nds_enc = nds->is_valid() ? nds->encoding() : 0;
attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_64bit);
// swap src<->dst for encoding
- vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
+ vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
emit_int8(0x1A);
emit_operand(dst, src);
// 0x00 - insert into lower 256 bits
- // 0x01 - insert into upper 128 bits
- emit_int8(value & 0x01);
+ // 0x01 - insert into upper 256 bits
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value) {
+void Assembler::vinsertf32x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_evex(), "");
+ assert(imm8 <= 0x03, "imm8: %u", imm8);
InstructionAttr attributes(AVX_512bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
@@ -5750,57 +5755,64 @@ void Assembler::vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src,
// 0x01 - insert into q1 128 bits (128..255)
// 0x02 - insert into q2 128 bits (256..383)
// 0x03 - insert into q3 128 bits (384..511)
- emit_int8(value & 0x3);
+ emit_int8(imm8 & 0x03);
}
-void Assembler::vinsertf32x4h(XMMRegister dst, Address src, int value) {
+void Assembler::vinsertf32x4(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) {
assert(VM_Version::supports_avx(), "");
assert(dst != xnoreg, "sanity");
+ assert(imm8 <= 0x03, "imm8: %u", imm8);
int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit;
+ int nds_enc = nds->is_valid() ? nds->encoding() : 0;
InstructionMark im(this);
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit);
// swap src<->dst for encoding
- vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
+ vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
emit_int8(0x18);
emit_operand(dst, src);
// 0x00 - insert into q0 128 bits (0..127)
// 0x01 - insert into q1 128 bits (128..255)
// 0x02 - insert into q2 128 bits (256..383)
// 0x03 - insert into q3 128 bits (384..511)
- emit_int8(value & 0x3);
+ emit_int8(imm8 & 0x03);
}
-void Assembler::vinsertf128h(XMMRegister dst, Address src) {
+void Assembler::vinsertf128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) {
assert(VM_Version::supports_avx(), "");
assert(dst != xnoreg, "sanity");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit;
+ int nds_enc = nds->is_valid() ? nds->encoding() : 0;
InstructionMark im(this);
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit);
// swap src<->dst for encoding
- vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
+ vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
emit_int8(0x18);
emit_operand(dst, src);
+ // 0x00 - insert into lower 128 bits
// 0x01 - insert into upper 128 bits
- emit_int8(0x01);
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vextractf128h(XMMRegister dst, XMMRegister src) {
+void Assembler::vextractf128(XMMRegister dst, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_avx(), "");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit;
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
emit_int8(0x19);
emit_int8((unsigned char)(0xC0 | encode));
- // 0x00 - insert into lower 128 bits
- // 0x01 - insert into upper 128 bits
- emit_int8(0x01);
+ // 0x00 - extract from lower 128 bits
+ // 0x01 - extract from upper 128 bits
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vextractf128h(Address dst, XMMRegister src) {
+void Assembler::vextractf128(Address dst, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_avx(), "");
assert(src != xnoreg, "sanity");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit;
InstructionMark im(this);
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
@@ -5808,12 +5820,14 @@ void Assembler::vextractf128h(Address dst, XMMRegister src) {
vex_prefix(dst, 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
emit_int8(0x19);
emit_operand(src, dst);
+ // 0x00 - extract from lower 128 bits
// 0x01 - extract from upper 128 bits
- emit_int8(0x01);
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) {
+void Assembler::vinserti128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_avx2(), "");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit;
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
@@ -5822,11 +5836,12 @@ void Assembler::vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src)
emit_int8((unsigned char)(0xC0 | encode));
// 0x00 - insert into lower 128 bits
// 0x01 - insert into upper 128 bits
- emit_int8(0x01);
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value) {
+void Assembler::vinserti64x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_evex(), "");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int nds_enc = nds->is_valid() ? nds->encoding() : 0;
int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
@@ -5834,39 +5849,44 @@ void Assembler::vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src,
emit_int8((unsigned char)(0xC0 | encode));
// 0x00 - insert into lower 256 bits
// 0x01 - insert into upper 256 bits
- emit_int8(value & 0x01);
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vinserti128h(XMMRegister dst, Address src) {
+void Assembler::vinserti128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) {
assert(VM_Version::supports_avx2(), "");
assert(dst != xnoreg, "sanity");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit;
+ int nds_enc = nds->is_valid() ? nds->encoding() : 0;
InstructionMark im(this);
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit);
// swap src<->dst for encoding
- vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
+ vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
emit_int8(0x38);
emit_operand(dst, src);
+ // 0x00 - insert into lower 128 bits
// 0x01 - insert into upper 128 bits
- emit_int8(0x01);
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vextracti128h(XMMRegister dst, XMMRegister src) {
+void Assembler::vextracti128(XMMRegister dst, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_avx(), "");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit;
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
emit_int8(0x39);
emit_int8((unsigned char)(0xC0 | encode));
- // 0x00 - insert into lower 128 bits
- // 0x01 - insert into upper 128 bits
- emit_int8(0x01);
+ // 0x00 - extract from lower 128 bits
+ // 0x01 - extract from upper 128 bits
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vextracti128h(Address dst, XMMRegister src) {
+void Assembler::vextracti128(Address dst, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_avx2(), "");
assert(src != xnoreg, "sanity");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit;
InstructionMark im(this);
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
@@ -5874,47 +5894,53 @@ void Assembler::vextracti128h(Address dst, XMMRegister src) {
vex_prefix(dst, 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
emit_int8(0x39);
emit_operand(src, dst);
+ // 0x00 - extract from lower 128 bits
// 0x01 - extract from upper 128 bits
- emit_int8(0x01);
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vextracti64x4h(XMMRegister dst, XMMRegister src, int value) {
+void Assembler::vextracti64x4(XMMRegister dst, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_evex(), "");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
emit_int8(0x3B);
emit_int8((unsigned char)(0xC0 | encode));
// 0x00 - extract from lower 256 bits
// 0x01 - extract from upper 256 bits
- emit_int8(value & 0x01);
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vextracti64x2h(XMMRegister dst, XMMRegister src, int value) {
+void Assembler::vextracti64x2(XMMRegister dst, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_evex(), "");
+ assert(imm8 <= 0x03, "imm8: %u", imm8);
InstructionAttr attributes(AVX_512bit, /* vex_w */ !_legacy_mode_dq, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
emit_int8(0x39);
emit_int8((unsigned char)(0xC0 | encode));
+ // 0x00 - extract from bits 127:0
// 0x01 - extract from bits 255:128
// 0x02 - extract from bits 383:256
// 0x03 - extract from bits 511:384
- emit_int8(value & 0x3);
+ emit_int8(imm8 & 0x03);
}
-void Assembler::vextractf64x4h(XMMRegister dst, XMMRegister src, int value) {
+void Assembler::vextractf64x4(XMMRegister dst, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_evex(), "");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
emit_int8(0x1B);
emit_int8((unsigned char)(0xC0 | encode));
// 0x00 - extract from lower 256 bits
// 0x01 - extract from upper 256 bits
- emit_int8(value & 0x1);
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vextractf64x4h(Address dst, XMMRegister src, int value) {
+void Assembler::vextractf64x4(Address dst, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_evex(), "");
assert(src != xnoreg, "sanity");
+ assert(imm8 <= 0x01, "imm8: %u", imm8);
InstructionMark im(this);
InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T4,/* input_size_in_bits */ EVEX_64bit);
@@ -5923,11 +5949,12 @@ void Assembler::vextractf64x4h(Address dst, XMMRegister src, int value) {
emit_operand(src, dst);
// 0x00 - extract from lower 256 bits
// 0x01 - extract from upper 256 bits
- emit_int8(value & 0x01);
+ emit_int8(imm8 & 0x01);
}
-void Assembler::vextractf32x4h(XMMRegister dst, XMMRegister src, int value) {
+void Assembler::vextractf32x4(XMMRegister dst, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_avx(), "");
+ assert(imm8 <= 0x03, "imm8: %u", imm8);
int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit;
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
@@ -5937,12 +5964,13 @@ void Assembler::vextractf32x4h(XMMRegister dst, XMMRegister src, int value) {
// 0x01 - extract from bits 255:128
// 0x02 - extract from bits 383:256
// 0x03 - extract from bits 511:384
- emit_int8(value & 0x3);
+ emit_int8(imm8 & 0x03);
}
-void Assembler::vextractf32x4h(Address dst, XMMRegister src, int value) {
+void Assembler::vextractf32x4(Address dst, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_evex(), "");
assert(src != xnoreg, "sanity");
+ assert(imm8 <= 0x03, "imm8: %u", imm8);
InstructionMark im(this);
InstructionAttr attributes(AVX_512bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit);
@@ -5953,19 +5981,21 @@ void Assembler::vextractf32x4h(Address dst, XMMRegister src, int value) {
// 0x01 - extract from bits 255:128
// 0x02 - extract from bits 383:256
// 0x03 - extract from bits 511:384
- emit_int8(value & 0x3);
+ emit_int8(imm8 & 0x03);
}
-void Assembler::vextractf64x2h(XMMRegister dst, XMMRegister src, int value) {
+void Assembler::vextractf64x2(XMMRegister dst, XMMRegister src, uint8_t imm8) {
assert(VM_Version::supports_evex(), "");
+ assert(imm8 <= 0x03, "imm8: %u", imm8);
InstructionAttr attributes(AVX_512bit, /* vex_w */ !_legacy_mode_dq, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
emit_int8(0x19);
emit_int8((unsigned char)(0xC0 | encode));
+ // 0x00 - extract from bits 127:0
// 0x01 - extract from bits 255:128
// 0x02 - extract from bits 383:256
// 0x03 - extract from bits 511:384
- emit_int8(value & 0x3);
+ emit_int8(imm8 & 0x03);
}
// duplicate 4-bytes integer data from src into 8 locations in dest
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp
index 3026afda174..561278599b7 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -1971,33 +1971,31 @@ private:
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);
+ // 128bit copy from/to 256bit (YMM) vector registers
+ void vinsertf128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8);
+ void vinserti128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8);
+ void vextractf128(XMMRegister dst, XMMRegister src, uint8_t imm8);
+ void vextracti128(XMMRegister dst, XMMRegister src, uint8_t imm8);
+ void vinsertf128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8);
+ void vinserti128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8);
+ void vextractf128(Address dst, XMMRegister src, uint8_t imm8);
+ void vextracti128(Address dst, XMMRegister src, uint8_t imm8);
- // Load/store high 128bit of YMM registers which does not destroy other half.
- void vinsertf128h(XMMRegister dst, Address src);
- void vinserti128h(XMMRegister dst, Address src);
- void vextractf128h(Address dst, XMMRegister src);
- void vextracti128h(Address dst, XMMRegister src);
+ // 256bit copy from/to 512bit (ZMM) vector registers
+ void vinserti64x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8);
+ void vinsertf64x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8);
+ void vextracti64x4(XMMRegister dst, XMMRegister src, uint8_t imm8);
+ void vextractf64x4(XMMRegister dst, XMMRegister src, uint8_t imm8);
+ void vextractf64x4(Address dst, XMMRegister src, uint8_t imm8);
+ void vinsertf64x4(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8);
- // Copy low 256bit into high 256bit of ZMM registers.
- void vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value);
- void vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value);
- void vextracti64x4h(XMMRegister dst, XMMRegister src, int value);
- void vextractf64x4h(XMMRegister dst, XMMRegister src, int value);
- void vextractf64x4h(Address dst, XMMRegister src, int value);
- void vinsertf64x4h(XMMRegister dst, Address src, int value);
-
- // 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);
- void vextractf32x4h(Address dst, XMMRegister src, int value);
- void vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value);
- void vinsertf32x4h(XMMRegister dst, Address src, int value);
+ // 128bit copy from/to 256bit (YMM) or 512bit (ZMM) vector registers
+ void vextracti64x2(XMMRegister dst, XMMRegister src, uint8_t imm8);
+ void vextractf64x2(XMMRegister dst, XMMRegister src, uint8_t imm8);
+ void vextractf32x4(XMMRegister dst, XMMRegister src, uint8_t imm8);
+ void vextractf32x4(Address dst, XMMRegister src, uint8_t imm8);
+ void vinsertf32x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8);
+ void vinsertf32x4(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8);
// duplicate 4-bytes integer data from src into 8 locations in dest
void vpbroadcastd(XMMRegister dst, XMMRegister src);
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
index 4bca248d815..8eb6764770f 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
@@ -3445,7 +3445,7 @@ void MacroAssembler::movptr(Address dst, Register src) {
void MacroAssembler::movdqu(Address dst, XMMRegister src) {
if (UseAVX > 2 && !VM_Version::supports_avx512vl() && (src->encoding() > 15)) {
- Assembler::vextractf32x4h(dst, src, 0);
+ Assembler::vextractf32x4(dst, src, 0);
} else {
Assembler::movdqu(dst, src);
}
@@ -3453,7 +3453,7 @@ void MacroAssembler::movdqu(Address dst, XMMRegister src) {
void MacroAssembler::movdqu(XMMRegister dst, Address src) {
if (UseAVX > 2 && !VM_Version::supports_avx512vl() && (dst->encoding() > 15)) {
- Assembler::vinsertf32x4h(dst, src, 0);
+ Assembler::vinsertf32x4(dst, dst, src, 0);
} else {
Assembler::movdqu(dst, src);
}
@@ -3478,7 +3478,7 @@ void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src) {
void MacroAssembler::vmovdqu(Address dst, XMMRegister src) {
if (UseAVX > 2 && !VM_Version::supports_avx512vl() && (src->encoding() > 15)) {
- Assembler::vextractf64x4h(dst, src, 0);
+ vextractf64x4_low(dst, src);
} else {
Assembler::vmovdqu(dst, src);
}
@@ -3486,7 +3486,7 @@ void MacroAssembler::vmovdqu(Address dst, XMMRegister src) {
void MacroAssembler::vmovdqu(XMMRegister dst, Address src) {
if (UseAVX > 2 && !VM_Version::supports_avx512vl() && (dst->encoding() > 15)) {
- Assembler::vinsertf64x4h(dst, src, 0);
+ vinsertf64x4_low(dst, src);
} else {
Assembler::vmovdqu(dst, src);
}
@@ -5649,14 +5649,14 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int
// Save upper half of ZMM registers
subptr(rsp, 32*num_xmm_regs);
for (int n = 0; n < num_xmm_regs; n++) {
- vextractf64x4h(Address(rsp, n*32), as_XMMRegister(n), 1);
+ vextractf64x4_high(Address(rsp, n*32), as_XMMRegister(n));
}
}
assert(UseAVX > 0, "256 bit vectors are supported only with AVX");
// Save upper half of YMM registers
subptr(rsp, 16*num_xmm_regs);
for (int n = 0; n < num_xmm_regs; n++) {
- vextractf128h(Address(rsp, n*16), as_XMMRegister(n));
+ vextractf128_high(Address(rsp, n*16), as_XMMRegister(n));
}
}
#endif
@@ -5665,7 +5665,7 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int
#ifdef _LP64
if (VM_Version::supports_evex()) {
for (int n = 0; n < num_xmm_regs; n++) {
- vextractf32x4h(Address(rsp, n*16), as_XMMRegister(n), 0);
+ vextractf32x4(Address(rsp, n*16), as_XMMRegister(n), 0);
}
} else {
for (int n = 0; n < num_xmm_regs; n++) {
@@ -5753,7 +5753,7 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int
#ifdef _LP64
if (VM_Version::supports_evex()) {
for (int n = 0; n < num_xmm_regs; n++) {
- vinsertf32x4h(as_XMMRegister(n), Address(rsp, n*16), 0);
+ vinsertf32x4(as_XMMRegister(n), as_XMMRegister(n), Address(rsp, n*16), 0);
}
} else {
for (int n = 0; n < num_xmm_regs; n++) {
@@ -5771,12 +5771,12 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int
if (MaxVectorSize > 16) {
// Restore upper half of YMM registers.
for (int n = 0; n < num_xmm_regs; n++) {
- vinsertf128h(as_XMMRegister(n), Address(rsp, n*16));
+ vinsertf128_high(as_XMMRegister(n), Address(rsp, n*16));
}
addptr(rsp, 16*num_xmm_regs);
if(UseAVX > 2) {
for (int n = 0; n < num_xmm_regs; n++) {
- vinsertf64x4h(as_XMMRegister(n), Address(rsp, n*32), 1);
+ vinsertf64x4_high(as_XMMRegister(n), Address(rsp, n*32));
}
addptr(rsp, 32*num_xmm_regs);
}
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
index d33473606aa..e325bbcdb2d 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -1215,14 +1215,131 @@ public:
void vpxor(XMMRegister dst, XMMRegister src) { Assembler::vpxor(dst, dst, src, true); }
void vpxor(XMMRegister dst, Address src) { Assembler::vpxor(dst, dst, src, true); }
- // Move packed integer values from low 128 bit to hign 128 bit in 256 bit vector.
- void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) {
- if (UseAVX > 1) // vinserti128h is available only in AVX2
- Assembler::vinserti128h(dst, nds, src);
- else
- Assembler::vinsertf128h(dst, nds, src);
+ void vinserti128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) {
+ if (UseAVX > 1) { // vinserti128 is available only in AVX2
+ Assembler::vinserti128(dst, nds, src, imm8);
+ } else {
+ Assembler::vinsertf128(dst, nds, src, imm8);
+ }
}
+ void vinserti128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) {
+ if (UseAVX > 1) { // vinserti128 is available only in AVX2
+ Assembler::vinserti128(dst, nds, src, imm8);
+ } else {
+ Assembler::vinsertf128(dst, nds, src, imm8);
+ }
+ }
+
+ void vextracti128(XMMRegister dst, XMMRegister src, uint8_t imm8) {
+ if (UseAVX > 1) { // vextracti128 is available only in AVX2
+ Assembler::vextracti128(dst, src, imm8);
+ } else {
+ Assembler::vextractf128(dst, src, imm8);
+ }
+ }
+
+ void vextracti128(Address dst, XMMRegister src, uint8_t imm8) {
+ if (UseAVX > 1) { // vextracti128 is available only in AVX2
+ Assembler::vextracti128(dst, src, imm8);
+ } else {
+ Assembler::vextractf128(dst, src, imm8);
+ }
+ }
+
+ // 128bit copy to/from high 128 bits of 256bit (YMM) vector registers
+ void vinserti128_high(XMMRegister dst, XMMRegister src) {
+ vinserti128(dst, dst, src, 1);
+ }
+ void vinserti128_high(XMMRegister dst, Address src) {
+ vinserti128(dst, dst, src, 1);
+ }
+ void vextracti128_high(XMMRegister dst, XMMRegister src) {
+ vextracti128(dst, src, 1);
+ }
+ void vextracti128_high(Address dst, XMMRegister src) {
+ vextracti128(dst, src, 1);
+ }
+ void vinsertf128_high(XMMRegister dst, XMMRegister src) {
+ vinsertf128(dst, dst, src, 1);
+ }
+ void vinsertf128_high(XMMRegister dst, Address src) {
+ vinsertf128(dst, dst, src, 1);
+ }
+ void vextractf128_high(XMMRegister dst, XMMRegister src) {
+ vextractf128(dst, src, 1);
+ }
+ void vextractf128_high(Address dst, XMMRegister src) {
+ vextractf128(dst, src, 1);
+ }
+
+ // 256bit copy to/from high 256 bits of 512bit (ZMM) vector registers
+ void vinserti64x4_high(XMMRegister dst, XMMRegister src) {
+ vinserti64x4(dst, dst, src, 1);
+ }
+ void vinsertf64x4_high(XMMRegister dst, XMMRegister src) {
+ vinsertf64x4(dst, dst, src, 1);
+ }
+ void vextracti64x4_high(XMMRegister dst, XMMRegister src) {
+ vextracti64x4(dst, src, 1);
+ }
+ void vextractf64x4_high(XMMRegister dst, XMMRegister src) {
+ vextractf64x4(dst, src, 1);
+ }
+ void vextractf64x4_high(Address dst, XMMRegister src) {
+ vextractf64x4(dst, src, 1);
+ }
+ void vinsertf64x4_high(XMMRegister dst, Address src) {
+ vinsertf64x4(dst, dst, src, 1);
+ }
+
+ // 128bit copy to/from low 128 bits of 256bit (YMM) vector registers
+ void vinserti128_low(XMMRegister dst, XMMRegister src) {
+ vinserti128(dst, dst, src, 0);
+ }
+ void vinserti128_low(XMMRegister dst, Address src) {
+ vinserti128(dst, dst, src, 0);
+ }
+ void vextracti128_low(XMMRegister dst, XMMRegister src) {
+ vextracti128(dst, src, 0);
+ }
+ void vextracti128_low(Address dst, XMMRegister src) {
+ vextracti128(dst, src, 0);
+ }
+ void vinsertf128_low(XMMRegister dst, XMMRegister src) {
+ vinsertf128(dst, dst, src, 0);
+ }
+ void vinsertf128_low(XMMRegister dst, Address src) {
+ vinsertf128(dst, dst, src, 0);
+ }
+ void vextractf128_low(XMMRegister dst, XMMRegister src) {
+ vextractf128(dst, src, 0);
+ }
+ void vextractf128_low(Address dst, XMMRegister src) {
+ vextractf128(dst, src, 0);
+ }
+
+ // 256bit copy to/from low 256 bits of 512bit (ZMM) vector registers
+ void vinserti64x4_low(XMMRegister dst, XMMRegister src) {
+ vinserti64x4(dst, dst, src, 0);
+ }
+ void vinsertf64x4_low(XMMRegister dst, XMMRegister src) {
+ vinsertf64x4(dst, dst, src, 0);
+ }
+ void vextracti64x4_low(XMMRegister dst, XMMRegister src) {
+ vextracti64x4(dst, src, 0);
+ }
+ void vextractf64x4_low(XMMRegister dst, XMMRegister src) {
+ vextractf64x4(dst, src, 0);
+ }
+ void vextractf64x4_low(Address dst, XMMRegister src) {
+ vextractf64x4(dst, src, 0);
+ }
+ void vinsertf64x4_low(XMMRegister dst, Address src) {
+ vinsertf64x4(dst, dst, src, 0);
+ }
+
+
// Carry-Less Multiplication Quadword
void vpclmulldq(XMMRegister dst, XMMRegister nds, XMMRegister src) {
// 0x00 - multiply lower 64 bits [0:63]
diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp
index af6797ef95a..b2bc4fce1aa 100644
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp
@@ -208,13 +208,13 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
__ subptr(rsp, ymm_bytes);
// Save upper half of YMM registers
for (int n = 0; n < num_xmm_regs; n++) {
- __ vextractf128h(Address(rsp, n*16), as_XMMRegister(n));
+ __ vextractf128_high(Address(rsp, n*16), as_XMMRegister(n));
}
if (UseAVX > 2) {
__ subptr(rsp, zmm_bytes);
// Save upper half of ZMM registers
for (int n = 0; n < num_xmm_regs; n++) {
- __ vextractf64x4h(Address(rsp, n*32), as_XMMRegister(n), 1);
+ __ vextractf64x4_high(Address(rsp, n*32), as_XMMRegister(n));
}
}
}
@@ -304,13 +304,13 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve
if (UseAVX > 2) {
// Restore upper half of ZMM registers.
for (int n = 0; n < num_xmm_regs; n++) {
- __ vinsertf64x4h(as_XMMRegister(n), Address(rsp, n*32), 1);
+ __ vinsertf64x4_high(as_XMMRegister(n), Address(rsp, n*32));
}
__ addptr(rsp, zmm_bytes);
}
// Restore upper half of YMM registers.
for (int n = 0; n < num_xmm_regs; n++) {
- __ vinsertf128h(as_XMMRegister(n), Address(rsp, n*16));
+ __ vinsertf128_high(as_XMMRegister(n), Address(rsp, n*16));
}
__ addptr(rsp, ymm_bytes);
}
diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
index 686530b7e09..75f248fb1a3 100644
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
@@ -179,13 +179,13 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
// Save upper half of YMM registers(0..15)
int base_addr = XSAVE_AREA_YMM_BEGIN;
for (int n = 0; n < 16; n++) {
- __ vextractf128h(Address(rsp, base_addr+n*16), as_XMMRegister(n));
+ __ vextractf128_high(Address(rsp, base_addr+n*16), as_XMMRegister(n));
}
if (VM_Version::supports_evex()) {
// Save upper half of ZMM registers(0..15)
base_addr = XSAVE_AREA_ZMM_BEGIN;
for (int n = 0; n < 16; n++) {
- __ vextractf64x4h(Address(rsp, base_addr+n*32), as_XMMRegister(n), 1);
+ __ vextractf64x4_high(Address(rsp, base_addr+n*32), as_XMMRegister(n));
}
// Save full ZMM registers(16..num_xmm_regs)
base_addr = XSAVE_AREA_UPPERBANK;
@@ -333,13 +333,13 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve
// Restore upper half of YMM registers (0..15)
int base_addr = XSAVE_AREA_YMM_BEGIN;
for (int n = 0; n < 16; n++) {
- __ vinsertf128h(as_XMMRegister(n), Address(rsp, base_addr+n*16));
+ __ vinsertf128_high(as_XMMRegister(n), Address(rsp, base_addr+n*16));
}
if (VM_Version::supports_evex()) {
// Restore upper half of ZMM registers (0..15)
base_addr = XSAVE_AREA_ZMM_BEGIN;
for (int n = 0; n < 16; n++) {
- __ vinsertf64x4h(as_XMMRegister(n), Address(rsp, base_addr+n*32), 1);
+ __ vinsertf64x4_high(as_XMMRegister(n), Address(rsp, base_addr+n*32));
}
// Restore full ZMM registers(16..num_xmm_regs)
base_addr = XSAVE_AREA_UPPERBANK;
diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
index 2f4adc88506..d1df1eac653 100644
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp
@@ -275,7 +275,7 @@ class StubGenerator: public StubCodeGenerator {
}
if (VM_Version::supports_evex()) {
for (int i = xmm_save_first; i <= last_reg; i++) {
- __ vextractf32x4h(xmm_save(i), as_XMMRegister(i), 0);
+ __ vextractf32x4(xmm_save(i), as_XMMRegister(i), 0);
}
} else {
for (int i = xmm_save_first; i <= last_reg; i++) {
@@ -393,7 +393,7 @@ class StubGenerator: public StubCodeGenerator {
// emit the restores for xmm regs
if (VM_Version::supports_evex()) {
for (int i = xmm_save_first; i <= last_reg; i++) {
- __ vinsertf32x4h(as_XMMRegister(i), xmm_save(i), 0);
+ __ vinsertf32x4(as_XMMRegister(i), as_XMMRegister(i), xmm_save(i), 0);
}
} else {
for (int i = xmm_save_first; i <= last_reg; i++) {
diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
index 7472ad4def1..94c7e156d7e 100644
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -385,7 +385,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator {
__ movdl(xmm0, rcx);
__ pshufd(xmm0, xmm0, 0x00);
- __ vinsertf128h(xmm0, xmm0, xmm0);
+ __ vinsertf128_high(xmm0, xmm0);
__ vmovdqu(xmm7, xmm0);
#ifdef _LP64
__ vmovdqu(xmm8, xmm0);
diff --git a/hotspot/src/cpu/x86/vm/x86.ad b/hotspot/src/cpu/x86/vm/x86.ad
index a316b914a52..603e00beef4 100644
--- a/hotspot/src/cpu/x86/vm/x86.ad
+++ b/hotspot/src/cpu/x86/vm/x86.ad
@@ -3179,13 +3179,13 @@ instruct Repl32B(vecY dst, rRegI src) %{
"punpcklbw $dst,$dst\n\t"
"pshuflw $dst,$dst,0x00\n\t"
"punpcklqdq $dst,$dst\n\t"
- "vinserti128h $dst,$dst,$dst\t! replicate32B" %}
+ "vinserti128_high $dst,$dst\t! replicate32B" %}
ins_encode %{
__ movdl($dst$$XMMRegister, $src$$Register);
__ punpcklbw($dst$$XMMRegister, $dst$$XMMRegister);
__ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00);
__ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3196,12 +3196,12 @@ instruct Repl32B_mem(vecY dst, memory mem) %{
format %{ "punpcklbw $dst,$mem\n\t"
"pshuflw $dst,$dst,0x00\n\t"
"punpcklqdq $dst,$dst\n\t"
- "vinserti128h $dst,$dst,$dst\t! replicate32B" %}
+ "vinserti128_high $dst,$dst\t! replicate32B" %}
ins_encode %{
__ punpcklbw($dst$$XMMRegister, $mem$$Address);
__ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00);
__ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3223,11 +3223,11 @@ instruct Repl32B_imm(vecY dst, immI con) %{
match(Set dst (ReplicateB con));
format %{ "movq $dst,[$constantaddress]\n\t"
"punpcklqdq $dst,$dst\n\t"
- "vinserti128h $dst,$dst,$dst\t! lreplicate32B($con)" %}
+ "vinserti128_high $dst,$dst\t! lreplicate32B($con)" %}
ins_encode %{
__ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 1)));
__ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3298,12 +3298,12 @@ instruct Repl16S(vecY dst, rRegI src) %{
format %{ "movd $dst,$src\n\t"
"pshuflw $dst,$dst,0x00\n\t"
"punpcklqdq $dst,$dst\n\t"
- "vinserti128h $dst,$dst,$dst\t! replicate16S" %}
+ "vinserti128_high $dst,$dst\t! replicate16S" %}
ins_encode %{
__ movdl($dst$$XMMRegister, $src$$Register);
__ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00);
__ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3313,11 +3313,11 @@ instruct Repl16S_mem(vecY dst, memory mem) %{
match(Set dst (ReplicateS (LoadS mem)));
format %{ "pshuflw $dst,$mem,0x00\n\t"
"punpcklqdq $dst,$dst\n\t"
- "vinserti128h $dst,$dst,$dst\t! replicate16S" %}
+ "vinserti128_high $dst,$dst\t! replicate16S" %}
ins_encode %{
__ pshuflw($dst$$XMMRegister, $mem$$Address, 0x00);
__ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3327,11 +3327,11 @@ instruct Repl16S_imm(vecY dst, immI con) %{
match(Set dst (ReplicateS con));
format %{ "movq $dst,[$constantaddress]\n\t"
"punpcklqdq $dst,$dst\n\t"
- "vinserti128h $dst,$dst,$dst\t! replicate16S($con)" %}
+ "vinserti128_high $dst,$dst\t! replicate16S($con)" %}
ins_encode %{
__ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 2)));
__ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3363,11 +3363,11 @@ instruct Repl8I(vecY dst, rRegI src) %{
match(Set dst (ReplicateI src));
format %{ "movd $dst,$src\n\t"
"pshufd $dst,$dst,0x00\n\t"
- "vinserti128h $dst,$dst,$dst\t! replicate8I" %}
+ "vinserti128_high $dst,$dst\t! replicate8I" %}
ins_encode %{
__ movdl($dst$$XMMRegister, $src$$Register);
__ pshufd($dst$$XMMRegister, $dst$$XMMRegister, 0x00);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3376,10 +3376,10 @@ instruct Repl8I_mem(vecY dst, memory mem) %{
predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl());
match(Set dst (ReplicateI (LoadI mem)));
format %{ "pshufd $dst,$mem,0x00\n\t"
- "vinserti128h $dst,$dst,$dst\t! replicate8I" %}
+ "vinserti128_high $dst,$dst\t! replicate8I" %}
ins_encode %{
__ pshufd($dst$$XMMRegister, $mem$$Address, 0x00);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3401,11 +3401,11 @@ instruct Repl8I_imm(vecY dst, immI con) %{
match(Set dst (ReplicateI con));
format %{ "movq $dst,[$constantaddress]\t! replicate8I($con)\n\t"
"punpcklqdq $dst,$dst\n\t"
- "vinserti128h $dst,$dst,$dst" %}
+ "vinserti128_high $dst,$dst" %}
ins_encode %{
__ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 4)));
__ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3430,11 +3430,11 @@ instruct Repl4L(vecY dst, rRegL src) %{
match(Set dst (ReplicateL src));
format %{ "movdq $dst,$src\n\t"
"punpcklqdq $dst,$dst\n\t"
- "vinserti128h $dst,$dst,$dst\t! replicate4L" %}
+ "vinserti128_high $dst,$dst\t! replicate4L" %}
ins_encode %{
__ movdq($dst$$XMMRegister, $src$$Register);
__ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3447,13 +3447,13 @@ instruct Repl4L(vecY dst, eRegL src, regD tmp) %{
"movdl $tmp,$src.hi\n\t"
"punpckldq $dst,$tmp\n\t"
"punpcklqdq $dst,$dst\n\t"
- "vinserti128h $dst,$dst,$dst\t! replicate4L" %}
+ "vinserti128_high $dst,$dst\t! replicate4L" %}
ins_encode %{
__ movdl($dst$$XMMRegister, $src$$Register);
__ movdl($tmp$$XMMRegister, HIGH_FROM_LOW($src$$Register));
__ punpckldq($dst$$XMMRegister, $tmp$$XMMRegister);
__ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3464,11 +3464,11 @@ instruct Repl4L_imm(vecY dst, immL con) %{
match(Set dst (ReplicateL con));
format %{ "movq $dst,[$constantaddress]\n\t"
"punpcklqdq $dst,$dst\n\t"
- "vinserti128h $dst,$dst,$dst\t! replicate4L($con)" %}
+ "vinserti128_high $dst,$dst\t! replicate4L($con)" %}
ins_encode %{
__ movq($dst$$XMMRegister, $constantaddress($con));
__ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3478,11 +3478,11 @@ instruct Repl4L_mem(vecY dst, memory mem) %{
match(Set dst (ReplicateL (LoadL mem)));
format %{ "movq $dst,$mem\n\t"
"punpcklqdq $dst,$dst\n\t"
- "vinserti128h $dst,$dst,$dst\t! replicate4L" %}
+ "vinserti128_high $dst,$dst\t! replicate4L" %}
ins_encode %{
__ movq($dst$$XMMRegister, $mem$$Address);
__ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister);
- __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3511,10 +3511,10 @@ instruct Repl8F(vecY dst, regF src) %{
predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl());
match(Set dst (ReplicateF src));
format %{ "pshufd $dst,$src,0x00\n\t"
- "vinsertf128h $dst,$dst,$dst\t! replicate8F" %}
+ "vinsertf128_high $dst,$dst\t! replicate8F" %}
ins_encode %{
__ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x00);
- __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3523,10 +3523,10 @@ instruct Repl8F_mem(vecY dst, memory mem) %{
predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl());
match(Set dst (ReplicateF (LoadF mem)));
format %{ "pshufd $dst,$mem,0x00\n\t"
- "vinsertf128h $dst,$dst,$dst\t! replicate8F" %}
+ "vinsertf128_high $dst,$dst\t! replicate8F" %}
ins_encode %{
__ pshufd($dst$$XMMRegister, $mem$$Address, 0x00);
- __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3576,10 +3576,10 @@ instruct Repl4D(vecY dst, regD src) %{
predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl());
match(Set dst (ReplicateD src));
format %{ "pshufd $dst,$src,0x44\n\t"
- "vinsertf128h $dst,$dst,$dst\t! replicate4D" %}
+ "vinsertf128_high $dst,$dst\t! replicate4D" %}
ins_encode %{
__ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x44);
- __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -3588,10 +3588,10 @@ instruct Repl4D_mem(vecY dst, memory mem) %{
predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl());
match(Set dst (ReplicateD (LoadD mem)));
format %{ "pshufd $dst,$mem,0x44\n\t"
- "vinsertf128h $dst,$dst,$dst\t! replicate4D" %}
+ "vinsertf128_high $dst,$dst\t! replicate4D" %}
ins_encode %{
__ pshufd($dst$$XMMRegister, $mem$$Address, 0x44);
- __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister);
+ __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister);
%}
ins_pipe( pipe_slow );
%}
@@ -4791,7 +4791,7 @@ instruct rvadd8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, regF tmp, regF
effect(TEMP tmp, TEMP tmp2);
format %{ "vphaddd $tmp,$src2,$src2\n\t"
"vphaddd $tmp,$tmp,$tmp2\n\t"
- "vextracti128 $tmp2,$tmp\n\t"
+ "vextracti128_high $tmp2,$tmp\n\t"
"vpaddd $tmp,$tmp,$tmp2\n\t"
"movd $tmp2,$src1\n\t"
"vpaddd $tmp2,$tmp2,$tmp\n\t"
@@ -4800,7 +4800,7 @@ instruct rvadd8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, regF tmp, regF
int vector_len = 1;
__ vphaddd($tmp$$XMMRegister, $src2$$XMMRegister, $src2$$XMMRegister, vector_len);
__ vphaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, vector_len);
- __ vextracti128h($tmp2$$XMMRegister, $tmp$$XMMRegister);
+ __ vextracti128_high($tmp2$$XMMRegister, $tmp$$XMMRegister);
__ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, 0);
__ movdl($tmp2$$XMMRegister, $src1$$Register);
__ vpaddd($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0);
@@ -4813,7 +4813,7 @@ instruct rvadd8I_reduction_reg_evex(rRegI dst, rRegI src1, vecY src2, regF tmp,
predicate(UseAVX > 2);
match(Set dst (AddReductionVI src1 src2));
effect(TEMP tmp, TEMP tmp2);
- format %{ "vextracti128 $tmp,$src2\n\t"
+ format %{ "vextracti128_high $tmp,$src2\n\t"
"vpaddd $tmp,$tmp,$src2\n\t"
"pshufd $tmp2,$tmp,0xE\n\t"
"vpaddd $tmp,$tmp,$tmp2\n\t"
@@ -4824,7 +4824,7 @@ instruct rvadd8I_reduction_reg_evex(rRegI dst, rRegI src1, vecY src2, regF tmp,
"movd $dst,$tmp2\t! add reduction8I" %}
ins_encode %{
int vector_len = 0;
- __ vextracti128h($tmp$$XMMRegister, $src2$$XMMRegister);
+ __ vextracti128_high($tmp$$XMMRegister, $src2$$XMMRegister);
__ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $src2$$XMMRegister, vector_len);
__ pshufd($tmp2$$XMMRegister, $tmp$$XMMRegister, 0xE);
__ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, vector_len);
@@ -4841,9 +4841,9 @@ instruct rvadd16I_reduction_reg_evex(rRegI dst, rRegI src1, vecZ src2, regF tmp,
predicate(UseAVX > 2);
match(Set dst (AddReductionVI src1 src2));
effect(TEMP tmp, TEMP tmp2, TEMP tmp3);
- format %{ "vextracti64x4 $tmp3,$src2,0x1\n\t"
+ format %{ "vextracti64x4_high $tmp3,$src2\n\t"
"vpaddd $tmp3,$tmp3,$src2\n\t"
- "vextracti128 $tmp,$tmp3\n\t"
+ "vextracti128_high $tmp,$tmp3\n\t"
"vpaddd $tmp,$tmp,$tmp3\n\t"
"pshufd $tmp2,$tmp,0xE\n\t"
"vpaddd $tmp,$tmp,$tmp2\n\t"
@@ -4853,9 +4853,9 @@ instruct rvadd16I_reduction_reg_evex(rRegI dst, rRegI src1, vecZ src2, regF tmp,
"vpaddd $tmp2,$tmp,$tmp2\n\t"
"movd $dst,$tmp2\t! mul reduction16I" %}
ins_encode %{
- __ vextracti64x4h($tmp3$$XMMRegister, $src2$$XMMRegister, 1);
+ __ vextracti64x4_high($tmp3$$XMMRegister, $src2$$XMMRegister);
__ vpaddd($tmp3$$XMMRegister, $tmp3$$XMMRegister, $src2$$XMMRegister, 1);
- __ vextracti128h($tmp$$XMMRegister, $tmp3$$XMMRegister);
+ __ vextracti128_high($tmp$$XMMRegister, $tmp3$$XMMRegister);
__ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp3$$XMMRegister, 0);
__ pshufd($tmp2$$XMMRegister, $tmp$$XMMRegister, 0xE);
__ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, 0);
@@ -4892,7 +4892,7 @@ instruct rvadd4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, regF tmp, regF
predicate(UseAVX > 2);
match(Set dst (AddReductionVL src1 src2));
effect(TEMP tmp, TEMP tmp2);
- format %{ "vextracti128 $tmp,$src2\n\t"
+ format %{ "vextracti128_high $tmp,$src2\n\t"
"vpaddq $tmp2,$tmp,$src2\n\t"
"pshufd $tmp,$tmp2,0xE\n\t"
"vpaddq $tmp2,$tmp2,$tmp\n\t"
@@ -4900,7 +4900,7 @@ instruct rvadd4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, regF tmp, regF
"vpaddq $tmp2,$tmp2,$tmp\n\t"
"movdq $dst,$tmp2\t! add reduction4L" %}
ins_encode %{
- __ vextracti128h($tmp$$XMMRegister, $src2$$XMMRegister);
+ __ vextracti128_high($tmp$$XMMRegister, $src2$$XMMRegister);
__ vpaddq($tmp2$$XMMRegister, $tmp$$XMMRegister, $src2$$XMMRegister, 0);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE);
__ vpaddq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0);
@@ -4915,9 +4915,9 @@ instruct rvadd8L_reduction_reg(rRegL dst, rRegL src1, vecZ src2, regF tmp, regF
predicate(UseAVX > 2);
match(Set dst (AddReductionVL src1 src2));
effect(TEMP tmp, TEMP tmp2);
- format %{ "vextracti64x4 $tmp2,$src2,0x1\n\t"
+ format %{ "vextracti64x4_high $tmp2,$src2\n\t"
"vpaddq $tmp2,$tmp2,$src2\n\t"
- "vextracti128 $tmp,$tmp2\n\t"
+ "vextracti128_high $tmp,$tmp2\n\t"
"vpaddq $tmp2,$tmp2,$tmp\n\t"
"pshufd $tmp,$tmp2,0xE\n\t"
"vpaddq $tmp2,$tmp2,$tmp\n\t"
@@ -4925,9 +4925,9 @@ instruct rvadd8L_reduction_reg(rRegL dst, rRegL src1, vecZ src2, regF tmp, regF
"vpaddq $tmp2,$tmp2,$tmp\n\t"
"movdq $dst,$tmp2\t! add reduction8L" %}
ins_encode %{
- __ vextracti64x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 1);
+ __ vextracti64x4_high($tmp2$$XMMRegister, $src2$$XMMRegister);
__ vpaddq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $src2$$XMMRegister, 1);
- __ vextracti128h($tmp$$XMMRegister, $tmp2$$XMMRegister);
+ __ vextracti128_high($tmp$$XMMRegister, $tmp2$$XMMRegister);
__ vpaddq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE);
__ vpaddq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0);
@@ -5026,7 +5026,7 @@ instruct radd8F_reduction_reg(regF dst, vecY src2, regF tmp, regF tmp2) %{
"vaddss $dst,$dst,$tmp\n\t"
"pshufd $tmp,$src2,0x03\n\t"
"vaddss $dst,$dst,$tmp\n\t"
- "vextractf128 $tmp2,$src2\n\t"
+ "vextractf128_high $tmp2,$src2\n\t"
"vaddss $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0x01\n\t"
"vaddss $dst,$dst,$tmp\n\t"
@@ -5042,7 +5042,7 @@ instruct radd8F_reduction_reg(regF dst, vecY src2, regF tmp, regF tmp2) %{
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0x03);
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf128h($tmp2$$XMMRegister, $src2$$XMMRegister);
+ __ vextractf128_high($tmp2$$XMMRegister, $src2$$XMMRegister);
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01);
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
@@ -5065,7 +5065,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{
"vaddss $dst,$dst,$tmp\n\t"
"pshufd $tmp,$src2,0x03\n\t"
"vaddss $dst,$dst,$tmp\n\t"
- "vextractf32x4 $tmp2,$src2, 0x1\n\t"
+ "vextractf32x4 $tmp2,$src2,0x1\n\t"
"vaddss $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0x01\n\t"
"vaddss $dst,$dst,$tmp\n\t"
@@ -5073,7 +5073,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{
"vaddss $dst,$dst,$tmp\n\t"
"pshufd $tmp,$tmp2,0x03\n\t"
"vaddss $dst,$dst,$tmp\n\t"
- "vextractf32x4 $tmp2,$src2, 0x2\n\t"
+ "vextractf32x4 $tmp2,$src2,0x2\n\t"
"vaddss $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0x01\n\t"
"vaddss $dst,$dst,$tmp\n\t"
@@ -5081,7 +5081,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{
"vaddss $dst,$dst,$tmp\n\t"
"pshufd $tmp,$tmp2,0x03\n\t"
"vaddss $dst,$dst,$tmp\n\t"
- "vextractf32x4 $tmp2,$src2, 0x3\n\t"
+ "vextractf32x4 $tmp2,$src2,0x3\n\t"
"vaddss $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0x01\n\t"
"vaddss $dst,$dst,$tmp\n\t"
@@ -5097,7 +5097,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0x03);
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1);
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01);
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
@@ -5105,7 +5105,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x03);
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2);
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01);
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
@@ -5113,7 +5113,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x03);
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3);
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01);
__ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
@@ -5162,7 +5162,7 @@ instruct rvadd4D_reduction_reg(regD dst, vecY src2, regD tmp, regD tmp2) %{
format %{ "vaddsd $dst,$dst,$src2\n\t"
"pshufd $tmp,$src2,0xE\n\t"
"vaddsd $dst,$dst,$tmp\n\t"
- "vextractf32x4h $tmp2,$src2, 0x1\n\t"
+ "vextractf32x4 $tmp2,$src2,0x1\n\t"
"vaddsd $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0xE\n\t"
"vaddsd $dst,$dst,$tmp\t! add reduction4D" %}
@@ -5170,7 +5170,7 @@ instruct rvadd4D_reduction_reg(regD dst, vecY src2, regD tmp, regD tmp2) %{
__ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $src2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0xE);
__ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1);
__ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE);
__ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
@@ -5185,15 +5185,15 @@ instruct rvadd8D_reduction_reg(regD dst, vecZ src2, regD tmp, regD tmp2) %{
format %{ "vaddsd $dst,$dst,$src2\n\t"
"pshufd $tmp,$src2,0xE\n\t"
"vaddsd $dst,$dst,$tmp\n\t"
- "vextractf32x4 $tmp2,$src2, 0x1\n\t"
+ "vextractf32x4 $tmp2,$src2,0x1\n\t"
"vaddsd $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0xE\n\t"
"vaddsd $dst,$dst,$tmp\n\t"
- "vextractf32x4 $tmp2,$src2, 0x2\n\t"
+ "vextractf32x4 $tmp2,$src2,0x2\n\t"
"vaddsd $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0xE\n\t"
"vaddsd $dst,$dst,$tmp\n\t"
- "vextractf32x4 $tmp2,$src2, 0x3\n\t"
+ "vextractf32x4 $tmp2,$src2,0x3\n\t"
"vaddsd $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0xE\n\t"
"vaddsd $dst,$dst,$tmp\t! add reduction8D" %}
@@ -5201,15 +5201,15 @@ instruct rvadd8D_reduction_reg(regD dst, vecZ src2, regD tmp, regD tmp2) %{
__ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $src2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0xE);
__ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1);
__ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE);
__ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2);
__ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE);
__ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3);
__ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE);
__ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
@@ -5307,7 +5307,7 @@ instruct rvmul8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, regF tmp, regF
predicate(UseAVX > 0);
match(Set dst (MulReductionVI src1 src2));
effect(TEMP tmp, TEMP tmp2);
- format %{ "vextracti128 $tmp,$src2\n\t"
+ format %{ "vextracti128_high $tmp,$src2\n\t"
"vpmulld $tmp,$tmp,$src2\n\t"
"pshufd $tmp2,$tmp,0xE\n\t"
"vpmulld $tmp,$tmp,$tmp2\n\t"
@@ -5318,7 +5318,7 @@ instruct rvmul8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, regF tmp, regF
"movd $dst,$tmp2\t! mul reduction8I" %}
ins_encode %{
int vector_len = 0;
- __ vextracti128h($tmp$$XMMRegister, $src2$$XMMRegister);
+ __ vextracti128_high($tmp$$XMMRegister, $src2$$XMMRegister);
__ vpmulld($tmp$$XMMRegister, $tmp$$XMMRegister, $src2$$XMMRegister, vector_len);
__ pshufd($tmp2$$XMMRegister, $tmp$$XMMRegister, 0xE);
__ vpmulld($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, vector_len);
@@ -5335,9 +5335,9 @@ instruct rvmul16I_reduction_reg(rRegI dst, rRegI src1, vecZ src2, regF tmp, regF
predicate(UseAVX > 2);
match(Set dst (MulReductionVI src1 src2));
effect(TEMP tmp, TEMP tmp2, TEMP tmp3);
- format %{ "vextracti64x4 $tmp3,$src2,0x1\n\t"
+ format %{ "vextracti64x4_high $tmp3,$src2\n\t"
"vpmulld $tmp3,$tmp3,$src2\n\t"
- "vextracti128 $tmp,$tmp3\n\t"
+ "vextracti128_high $tmp,$tmp3\n\t"
"vpmulld $tmp,$tmp,$src2\n\t"
"pshufd $tmp2,$tmp,0xE\n\t"
"vpmulld $tmp,$tmp,$tmp2\n\t"
@@ -5347,9 +5347,9 @@ instruct rvmul16I_reduction_reg(rRegI dst, rRegI src1, vecZ src2, regF tmp, regF
"vpmulld $tmp2,$tmp,$tmp2\n\t"
"movd $dst,$tmp2\t! mul reduction16I" %}
ins_encode %{
- __ vextracti64x4h($tmp3$$XMMRegister, $src2$$XMMRegister, 1);
+ __ vextracti64x4_high($tmp3$$XMMRegister, $src2$$XMMRegister);
__ vpmulld($tmp3$$XMMRegister, $tmp3$$XMMRegister, $src2$$XMMRegister, 1);
- __ vextracti128h($tmp$$XMMRegister, $tmp3$$XMMRegister);
+ __ vextracti128_high($tmp$$XMMRegister, $tmp3$$XMMRegister);
__ vpmulld($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp3$$XMMRegister, 0);
__ pshufd($tmp2$$XMMRegister, $tmp$$XMMRegister, 0xE);
__ vpmulld($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, 0);
@@ -5386,7 +5386,7 @@ instruct rvmul4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, regF tmp, regF
predicate(UseAVX > 2 && VM_Version::supports_avx512dq());
match(Set dst (MulReductionVL src1 src2));
effect(TEMP tmp, TEMP tmp2);
- format %{ "vextracti128 $tmp,$src2\n\t"
+ format %{ "vextracti128_high $tmp,$src2\n\t"
"vpmullq $tmp2,$tmp,$src2\n\t"
"pshufd $tmp,$tmp2,0xE\n\t"
"vpmullq $tmp2,$tmp2,$tmp\n\t"
@@ -5394,7 +5394,7 @@ instruct rvmul4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, regF tmp, regF
"vpmullq $tmp2,$tmp2,$tmp\n\t"
"movdq $dst,$tmp2\t! mul reduction4L" %}
ins_encode %{
- __ vextracti128h($tmp$$XMMRegister, $src2$$XMMRegister);
+ __ vextracti128_high($tmp$$XMMRegister, $src2$$XMMRegister);
__ vpmullq($tmp2$$XMMRegister, $tmp$$XMMRegister, $src2$$XMMRegister, 0);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE);
__ vpmullq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0);
@@ -5409,9 +5409,9 @@ instruct rvmul8L_reduction_reg(rRegL dst, rRegL src1, vecZ src2, regF tmp, regF
predicate(UseAVX > 2 && VM_Version::supports_avx512dq());
match(Set dst (MulReductionVL src1 src2));
effect(TEMP tmp, TEMP tmp2);
- format %{ "vextracti64x4 $tmp2,$src2,0x1\n\t"
+ format %{ "vextracti64x4_high $tmp2,$src2\n\t"
"vpmullq $tmp2,$tmp2,$src2\n\t"
- "vextracti128 $tmp,$tmp2\n\t"
+ "vextracti128_high $tmp,$tmp2\n\t"
"vpmullq $tmp2,$tmp2,$tmp\n\t"
"pshufd $tmp,$tmp2,0xE\n\t"
"vpmullq $tmp2,$tmp2,$tmp\n\t"
@@ -5419,9 +5419,9 @@ instruct rvmul8L_reduction_reg(rRegL dst, rRegL src1, vecZ src2, regF tmp, regF
"vpmullq $tmp2,$tmp2,$tmp\n\t"
"movdq $dst,$tmp2\t! mul reduction8L" %}
ins_encode %{
- __ vextracti64x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 1);
+ __ vextracti64x4_high($tmp2$$XMMRegister, $src2$$XMMRegister);
__ vpmullq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $src2$$XMMRegister, 1);
- __ vextracti128h($tmp$$XMMRegister, $tmp2$$XMMRegister);
+ __ vextracti128_high($tmp$$XMMRegister, $tmp2$$XMMRegister);
__ vpmullq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE);
__ vpmullq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0);
@@ -5520,7 +5520,7 @@ instruct rvmul8F_reduction_reg(regF dst, vecY src2, regF tmp, regF tmp2) %{
"vmulss $dst,$dst,$tmp\n\t"
"pshufd $tmp,$src2,0x03\n\t"
"vmulss $dst,$dst,$tmp\n\t"
- "vextractf128 $tmp2,$src2\n\t"
+ "vextractf128_high $tmp2,$src2\n\t"
"vmulss $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0x01\n\t"
"vmulss $dst,$dst,$tmp\n\t"
@@ -5536,7 +5536,7 @@ instruct rvmul8F_reduction_reg(regF dst, vecY src2, regF tmp, regF tmp2) %{
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0x03);
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf128h($tmp2$$XMMRegister, $src2$$XMMRegister);
+ __ vextractf128_high($tmp2$$XMMRegister, $src2$$XMMRegister);
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01);
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
@@ -5559,7 +5559,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{
"vmulss $dst,$dst,$tmp\n\t"
"pshufd $tmp,$src2,0x03\n\t"
"vmulss $dst,$dst,$tmp\n\t"
- "vextractf32x4 $tmp2,$src2, 0x1\n\t"
+ "vextractf32x4 $tmp2,$src2,0x1\n\t"
"vmulss $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0x01\n\t"
"vmulss $dst,$dst,$tmp\n\t"
@@ -5567,7 +5567,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{
"vmulss $dst,$dst,$tmp\n\t"
"pshufd $tmp,$tmp2,0x03\n\t"
"vmulss $dst,$dst,$tmp\n\t"
- "vextractf32x4 $tmp2,$src2, 0x2\n\t"
+ "vextractf32x4 $tmp2,$src2,0x2\n\t"
"vmulss $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0x01\n\t"
"vmulss $dst,$dst,$tmp\n\t"
@@ -5575,7 +5575,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{
"vmulss $dst,$dst,$tmp\n\t"
"pshufd $tmp,$tmp2,0x03\n\t"
"vmulss $dst,$dst,$tmp\n\t"
- "vextractf32x4 $tmp2,$src2, 0x3\n\t"
+ "vextractf32x4 $tmp2,$src2,0x3\n\t"
"vmulss $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0x01\n\t"
"vmulss $dst,$dst,$tmp\n\t"
@@ -5591,7 +5591,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0x03);
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1);
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01);
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
@@ -5599,7 +5599,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x03);
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2);
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01);
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
@@ -5607,7 +5607,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x03);
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3);
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01);
__ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
@@ -5656,7 +5656,7 @@ instruct rvmul4D_reduction_reg(regD dst, vecY src2, regD tmp, regD tmp2) %{
format %{ "vmulsd $dst,$dst,$src2\n\t"
"pshufd $tmp,$src2,0xE\n\t"
"vmulsd $dst,$dst,$tmp\n\t"
- "vextractf128 $tmp2,$src2\n\t"
+ "vextractf128_high $tmp2,$src2\n\t"
"vmulsd $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0xE\n\t"
"vmulsd $dst,$dst,$tmp\t! mul reduction4D" %}
@@ -5664,7 +5664,7 @@ instruct rvmul4D_reduction_reg(regD dst, vecY src2, regD tmp, regD tmp2) %{
__ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $src2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0xE);
__ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf128h($tmp2$$XMMRegister, $src2$$XMMRegister);
+ __ vextractf128_high($tmp2$$XMMRegister, $src2$$XMMRegister);
__ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE);
__ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
@@ -5679,15 +5679,15 @@ instruct rvmul8D_reduction_reg(regD dst, vecZ src2, regD tmp, regD tmp2) %{
format %{ "vmulsd $dst,$dst,$src2\n\t"
"pshufd $tmp,$src2,0xE\n\t"
"vmulsd $dst,$dst,$tmp\n\t"
- "vextractf32x4 $tmp2,$src2, 0x1\n\t"
+ "vextractf32x4 $tmp2,$src2,0x1\n\t"
"vmulsd $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$src2,0xE\n\t"
"vmulsd $dst,$dst,$tmp\n\t"
- "vextractf32x4 $tmp2,$src2, 0x2\n\t"
+ "vextractf32x4 $tmp2,$src2,0x2\n\t"
"vmulsd $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0xE\n\t"
"vmulsd $dst,$dst,$tmp\n\t"
- "vextractf32x4 $tmp2,$src2, 0x3\n\t"
+ "vextractf32x4 $tmp2,$src2,0x3\n\t"
"vmulsd $dst,$dst,$tmp2\n\t"
"pshufd $tmp,$tmp2,0xE\n\t"
"vmulsd $dst,$dst,$tmp\t! mul reduction8D" %}
@@ -5695,15 +5695,15 @@ instruct rvmul8D_reduction_reg(regD dst, vecZ src2, regD tmp, regD tmp2) %{
__ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $src2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0xE);
__ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1);
__ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE);
__ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2);
__ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE);
__ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
- __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3);
+ __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3);
__ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister);
__ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE);
__ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister);
From f4b4c5d7b0e312183ce7d69437868ee5520a6ee4 Mon Sep 17 00:00:00 2001
From: Ed Nevill
Date: Tue, 8 Mar 2016 14:39:50 +0000
Subject: [PATCH 061/311] 8150394: aarch64: add support for 8.1 LSE CAS
instructions
Co-authored-by: Ananth Jasty
Reviewed-by: aph
---
hotspot/src/cpu/aarch64/vm/aarch64.ad | 27 +++--
.../src/cpu/aarch64/vm/assembler_aarch64.hpp | 66 +++++++++--
.../aarch64/vm/c1_LIRAssembler_aarch64.cpp | 70 ++++++-----
.../src/cpu/aarch64/vm/globals_aarch64.hpp | 5 +
.../cpu/aarch64/vm/macroAssembler_aarch64.cpp | 112 ++++++++++++------
.../cpu/aarch64/vm/macroAssembler_aarch64.hpp | 17 +--
.../src/cpu/aarch64/vm/register_aarch64.hpp | 3 +
.../src/cpu/aarch64/vm/vm_version_aarch64.cpp | 14 +++
8 files changed, 223 insertions(+), 91 deletions(-)
diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad
index 832c9e765ba..7689614b710 100644
--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad
@@ -4132,14 +4132,14 @@ encode %{
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
- &Assembler::ldxr, &MacroAssembler::cmp, &Assembler::stlxr);
+ Assembler::xword, /*acquire*/ false, /*release*/ true);
%}
enc_class aarch64_enc_cmpxchgw(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
- &Assembler::ldxrw, &MacroAssembler::cmpw, &Assembler::stlxrw);
+ Assembler::word, /*acquire*/ false, /*release*/ true);
%}
@@ -4151,14 +4151,14 @@ encode %{
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
- &Assembler::ldaxr, &MacroAssembler::cmp, &Assembler::stlxr);
+ Assembler::xword, /*acquire*/ true, /*release*/ true);
%}
enc_class aarch64_enc_cmpxchgw_acq(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
- &Assembler::ldaxrw, &MacroAssembler::cmpw, &Assembler::stlxrw);
+ Assembler::word, /*acquire*/ true, /*release*/ true);
%}
@@ -4676,7 +4676,12 @@ encode %{
// Compare object markOop with mark and if equal exchange scratch1
// with object markOop.
- {
+ if (UseLSE) {
+ __ mov(tmp, disp_hdr);
+ __ casal(Assembler::xword, tmp, box, oop);
+ __ cmp(tmp, disp_hdr);
+ __ br(Assembler::EQ, cont);
+ } else {
Label retry_load;
__ bind(retry_load);
__ ldaxr(tmp, oop);
@@ -4726,7 +4731,11 @@ encode %{
__ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes()-markOopDesc::monitor_value));
__ mov(disp_hdr, zr);
- {
+ if (UseLSE) {
+ __ mov(rscratch1, disp_hdr);
+ __ casal(Assembler::xword, rscratch1, rthread, tmp);
+ __ cmp(rscratch1, disp_hdr);
+ } else {
Label retry_load, fail;
__ bind(retry_load);
__ ldaxr(rscratch1, tmp);
@@ -4815,7 +4824,11 @@ encode %{
// see the stack address of the basicLock in the markOop of the
// object.
- {
+ if (UseLSE) {
+ __ mov(tmp, box);
+ __ casl(Assembler::xword, tmp, disp_hdr, oop);
+ __ cmp(tmp, box);
+ } else {
Label retry_load;
__ bind(retry_load);
__ ldxr(tmp, oop);
diff --git a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
index ca617716562..85e0f2e4eca 100644
--- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp
@@ -972,7 +972,7 @@ public:
// System
void system(int op0, int op1, int CRn, int CRm, int op2,
- Register rt = (Register)0b11111)
+ Register rt = dummy_reg)
{
starti;
f(0b11010101000, 31, 21);
@@ -1082,7 +1082,7 @@ public:
#define INSN(NAME, opc) \
void NAME() { \
- branch_reg((Register)0b11111, opc); \
+ branch_reg(dummy_reg, opc); \
}
INSN(eret, 0b0100);
@@ -1094,10 +1094,22 @@ public:
enum operand_size { byte, halfword, word, xword };
void load_store_exclusive(Register Rs, Register Rt1, Register Rt2,
- Register Rn, enum operand_size sz, int op, int o0) {
+ Register Rn, enum operand_size sz, int op, bool ordered) {
starti;
f(sz, 31, 30), f(0b001000, 29, 24), f(op, 23, 21);
- rf(Rs, 16), f(o0, 15), rf(Rt2, 10), rf(Rn, 5), rf(Rt1, 0);
+ rf(Rs, 16), f(ordered, 15), rf(Rt2, 10), rf(Rn, 5), rf(Rt1, 0);
+ }
+
+ void load_exclusive(Register dst, Register addr,
+ enum operand_size sz, bool ordered) {
+ load_store_exclusive(dummy_reg, dst, dummy_reg, addr,
+ sz, 0b010, ordered);
+ }
+
+ void store_exclusive(Register status, Register new_val, Register addr,
+ enum operand_size sz, bool ordered) {
+ load_store_exclusive(status, new_val, dummy_reg, addr,
+ sz, 0b000, ordered);
}
#define INSN4(NAME, sz, op, o0) /* Four registers */ \
@@ -1109,19 +1121,19 @@ public:
#define INSN3(NAME, sz, op, o0) /* Three registers */ \
void NAME(Register Rs, Register Rt, Register Rn) { \
guarantee(Rs != Rn && Rs != Rt, "unpredictable instruction"); \
- load_store_exclusive(Rs, Rt, (Register)0b11111, Rn, sz, op, o0); \
+ load_store_exclusive(Rs, Rt, dummy_reg, Rn, sz, op, o0); \
}
#define INSN2(NAME, sz, op, o0) /* Two registers */ \
void NAME(Register Rt, Register Rn) { \
- load_store_exclusive((Register)0b11111, Rt, (Register)0b11111, \
+ load_store_exclusive(dummy_reg, Rt, dummy_reg, \
Rn, sz, op, o0); \
}
#define INSN_FOO(NAME, sz, op, o0) /* Three registers, encoded differently */ \
void NAME(Register Rt1, Register Rt2, Register Rn) { \
guarantee(Rt1 != Rt2, "unpredictable instruction"); \
- load_store_exclusive((Register)0b11111, Rt1, Rt2, Rn, sz, op, o0); \
+ load_store_exclusive(dummy_reg, Rt1, Rt2, Rn, sz, op, o0); \
}
// bytes
@@ -1169,6 +1181,46 @@ public:
#undef INSN4
#undef INSN_FOO
+ // 8.1 Compare and swap extensions
+ void lse_cas(Register Rs, Register Rt, Register Rn,
+ enum operand_size sz, bool a, bool r, bool not_pair) {
+ starti;
+ if (! not_pair) { // Pair
+ assert(sz == word || sz == xword, "invalid size");
+ /* The size bit is in bit 30, not 31 */
+ sz = (operand_size)(sz == word ? 0b00:0b01);
+ }
+ f(sz, 31, 30), f(0b001000, 29, 24), f(1, 23), f(a, 22), f(1, 21);
+ rf(Rs, 16), f(r, 15), f(0b11111, 14, 10), rf(Rn, 5), rf(Rt, 0);
+ }
+
+ // CAS
+#define INSN(NAME, a, r) \
+ void NAME(operand_size sz, Register Rs, Register Rt, Register Rn) { \
+ assert(Rs != Rn && Rs != Rt, "unpredictable instruction"); \
+ lse_cas(Rs, Rt, Rn, sz, a, r, true); \
+ }
+ INSN(cas, false, false)
+ INSN(casa, true, false)
+ INSN(casl, false, true)
+ INSN(casal, true, true)
+#undef INSN
+
+ // CASP
+#define INSN(NAME, a, r) \
+ void NAME(operand_size sz, Register Rs, Register Rs1, \
+ Register Rt, Register Rt1, Register Rn) { \
+ assert((Rs->encoding() & 1) == 0 && (Rt->encoding() & 1) == 0 && \
+ Rs->successor() == Rs1 && Rt->successor() == Rt1 && \
+ Rs != Rn && Rs1 != Rn && Rs != Rt, "invalid registers"); \
+ lse_cas(Rs, Rt, Rn, sz, a, r, false); \
+ }
+ INSN(casp, false, false)
+ INSN(caspa, true, false)
+ INSN(caspl, false, true)
+ INSN(caspal, true, true)
+#undef INSN
+
// Load register (literal)
#define INSN(NAME, opc, V) \
void NAME(Register Rt, address dest) { \
diff --git a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp
index e32a3c76b79..a42f0a127b0 100644
--- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp
@@ -1556,38 +1556,52 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
}
void LIR_Assembler::casw(Register addr, Register newval, Register cmpval) {
- Label retry_load, nope;
- // flush and load exclusive from the memory location
- // and fail if it is not what we expect
- __ bind(retry_load);
- __ ldaxrw(rscratch1, addr);
- __ cmpw(rscratch1, cmpval);
- __ cset(rscratch1, Assembler::NE);
- __ br(Assembler::NE, nope);
- // if we store+flush with no intervening write rscratch1 wil be zero
- __ stlxrw(rscratch1, newval, addr);
- // retry so we only ever return after a load fails to compare
- // ensures we don't return a stale value after a failed write.
- __ cbnzw(rscratch1, retry_load);
- __ bind(nope);
+ if (UseLSE) {
+ __ mov(rscratch1, cmpval);
+ __ casal(Assembler::word, rscratch1, newval, addr);
+ __ cmpw(rscratch1, cmpval);
+ __ cset(rscratch1, Assembler::NE);
+ } else {
+ Label retry_load, nope;
+ // flush and load exclusive from the memory location
+ // and fail if it is not what we expect
+ __ bind(retry_load);
+ __ ldaxrw(rscratch1, addr);
+ __ cmpw(rscratch1, cmpval);
+ __ cset(rscratch1, Assembler::NE);
+ __ br(Assembler::NE, nope);
+ // if we store+flush with no intervening write rscratch1 wil be zero
+ __ stlxrw(rscratch1, newval, addr);
+ // retry so we only ever return after a load fails to compare
+ // ensures we don't return a stale value after a failed write.
+ __ cbnzw(rscratch1, retry_load);
+ __ bind(nope);
+ }
__ membar(__ AnyAny);
}
void LIR_Assembler::casl(Register addr, Register newval, Register cmpval) {
- Label retry_load, nope;
- // flush and load exclusive from the memory location
- // and fail if it is not what we expect
- __ bind(retry_load);
- __ ldaxr(rscratch1, addr);
- __ cmp(rscratch1, cmpval);
- __ cset(rscratch1, Assembler::NE);
- __ br(Assembler::NE, nope);
- // if we store+flush with no intervening write rscratch1 wil be zero
- __ stlxr(rscratch1, newval, addr);
- // retry so we only ever return after a load fails to compare
- // ensures we don't return a stale value after a failed write.
- __ cbnz(rscratch1, retry_load);
- __ bind(nope);
+ if (UseLSE) {
+ __ mov(rscratch1, cmpval);
+ __ casal(Assembler::xword, rscratch1, newval, addr);
+ __ cmp(rscratch1, cmpval);
+ __ cset(rscratch1, Assembler::NE);
+ } else {
+ Label retry_load, nope;
+ // flush and load exclusive from the memory location
+ // and fail if it is not what we expect
+ __ bind(retry_load);
+ __ ldaxr(rscratch1, addr);
+ __ cmp(rscratch1, cmpval);
+ __ cset(rscratch1, Assembler::NE);
+ __ br(Assembler::NE, nope);
+ // if we store+flush with no intervening write rscratch1 wil be zero
+ __ stlxr(rscratch1, newval, addr);
+ // retry so we only ever return after a load fails to compare
+ // ensures we don't return a stale value after a failed write.
+ __ cbnz(rscratch1, retry_load);
+ __ bind(nope);
+ }
__ membar(__ AnyAny);
}
diff --git a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
index 9380d429878..bb9dd4d2dc8 100644
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
@@ -103,6 +103,9 @@ define_pd_global(intx, InlineSmallCode, 1000);
\
product(bool, UseCRC32, false, \
"Use CRC32 instructions for CRC32 computation") \
+ \
+ product(bool, UseLSE, false, \
+ "Use LSE instructions") \
// Don't attempt to use Neon on builtin sim until builtin sim supports it
#define UseCRC32 false
@@ -123,6 +126,8 @@ define_pd_global(intx, InlineSmallCode, 1000);
"Use Neon for CRC32 computation") \
product(bool, UseCRC32, false, \
"Use CRC32 instructions for CRC32 computation") \
+ product(bool, UseLSE, false, \
+ "Use LSE instructions") \
product(bool, TraceTraps, false, "Trace all traps the signal handler")
#endif
diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
index 942518b116b..bfa9c8fba5b 100644
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
@@ -2070,25 +2070,32 @@ void MacroAssembler::cmpxchgptr(Register oldv, Register newv, Register addr, Reg
// oldv holds comparison value
// newv holds value to write in exchange
// addr identifies memory word to compare against/update
- // tmp returns 0/1 for success/failure
- Label retry_load, nope;
+ if (UseLSE) {
+ mov(tmp, oldv);
+ casal(Assembler::xword, oldv, newv, addr);
+ cmp(tmp, oldv);
+ br(Assembler::EQ, succeed);
+ membar(AnyAny);
+ } else {
+ Label retry_load, nope;
- bind(retry_load);
- // flush and load exclusive from the memory location
- // and fail if it is not what we expect
- ldaxr(tmp, addr);
- cmp(tmp, oldv);
- br(Assembler::NE, nope);
- // if we store+flush with no intervening write tmp wil be zero
- stlxr(tmp, newv, addr);
- cbzw(tmp, succeed);
- // retry so we only ever return after a load fails to compare
- // ensures we don't return a stale value after a failed write.
- b(retry_load);
- // if the memory word differs we return it in oldv and signal a fail
- bind(nope);
- membar(AnyAny);
- mov(oldv, tmp);
+ bind(retry_load);
+ // flush and load exclusive from the memory location
+ // and fail if it is not what we expect
+ ldaxr(tmp, addr);
+ cmp(tmp, oldv);
+ br(Assembler::NE, nope);
+ // if we store+flush with no intervening write tmp wil be zero
+ stlxr(tmp, newv, addr);
+ cbzw(tmp, succeed);
+ // retry so we only ever return after a load fails to compare
+ // ensures we don't return a stale value after a failed write.
+ b(retry_load);
+ // if the memory word differs we return it in oldv and signal a fail
+ bind(nope);
+ membar(AnyAny);
+ mov(oldv, tmp);
+ }
if (fail)
b(*fail);
}
@@ -2099,28 +2106,63 @@ void MacroAssembler::cmpxchgw(Register oldv, Register newv, Register addr, Regis
// newv holds value to write in exchange
// addr identifies memory word to compare against/update
// tmp returns 0/1 for success/failure
- Label retry_load, nope;
+ if (UseLSE) {
+ mov(tmp, oldv);
+ casal(Assembler::word, oldv, newv, addr);
+ cmp(tmp, oldv);
+ br(Assembler::EQ, succeed);
+ membar(AnyAny);
+ } else {
+ Label retry_load, nope;
- bind(retry_load);
- // flush and load exclusive from the memory location
- // and fail if it is not what we expect
- ldaxrw(tmp, addr);
- cmp(tmp, oldv);
- br(Assembler::NE, nope);
- // if we store+flush with no intervening write tmp wil be zero
- stlxrw(tmp, newv, addr);
- cbzw(tmp, succeed);
- // retry so we only ever return after a load fails to compare
- // ensures we don't return a stale value after a failed write.
- b(retry_load);
- // if the memory word differs we return it in oldv and signal a fail
- bind(nope);
- membar(AnyAny);
- mov(oldv, tmp);
+ bind(retry_load);
+ // flush and load exclusive from the memory location
+ // and fail if it is not what we expect
+ ldaxrw(tmp, addr);
+ cmp(tmp, oldv);
+ br(Assembler::NE, nope);
+ // if we store+flush with no intervening write tmp wil be zero
+ stlxrw(tmp, newv, addr);
+ cbzw(tmp, succeed);
+ // retry so we only ever return after a load fails to compare
+ // ensures we don't return a stale value after a failed write.
+ b(retry_load);
+ // if the memory word differs we return it in oldv and signal a fail
+ bind(nope);
+ membar(AnyAny);
+ mov(oldv, tmp);
+ }
if (fail)
b(*fail);
}
+// A generic CAS; success or failure is in the EQ flag.
+void MacroAssembler::cmpxchg(Register addr, Register expected,
+ Register new_val,
+ enum operand_size size,
+ bool acquire, bool release,
+ Register tmp) {
+ if (UseLSE) {
+ mov(tmp, expected);
+ lse_cas(tmp, new_val, addr, size, acquire, release, /*not_pair*/ true);
+ cmp(tmp, expected);
+ } else {
+ BLOCK_COMMENT("cmpxchg {");
+ Label retry_load, done;
+ bind(retry_load);
+ load_exclusive(tmp, addr, size, acquire);
+ if (size == xword)
+ cmp(tmp, expected);
+ else
+ cmpw(tmp, expected);
+ br(Assembler::NE, done);
+ store_exclusive(tmp, new_val, addr, size, release);
+ cbnzw(tmp, retry_load);
+ bind(done);
+ BLOCK_COMMENT("} cmpxchg");
+ }
+}
+
static bool different(Register a, RegisterOrConstant b, Register c) {
if (b.is_constant())
return a != c;
diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
index e042b5055eb..64ef4f65eca 100644
--- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp
@@ -971,21 +971,10 @@ public:
}
// A generic CAS; success or failure is in the EQ flag.
- template
void cmpxchg(Register addr, Register expected, Register new_val,
- T1 load_insn,
- void (MacroAssembler::*cmp_insn)(Register, Register),
- T2 store_insn,
- Register tmp = rscratch1) {
- Label retry_load, done;
- bind(retry_load);
- (this->*load_insn)(tmp, addr);
- (this->*cmp_insn)(tmp, expected);
- br(Assembler::NE, done);
- (this->*store_insn)(tmp, new_val, addr);
- cbnzw(tmp, retry_load);
- bind(done);
- }
+ enum operand_size size,
+ bool acquire, bool release,
+ Register tmp = rscratch1);
// Calls
diff --git a/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp
index 762b8b0f1ce..6e935f687b1 100644
--- a/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp
@@ -107,6 +107,9 @@ CONSTANT_REGISTER_DECLARATION(Register, r31_sp, (31));
CONSTANT_REGISTER_DECLARATION(Register, zr, (32));
CONSTANT_REGISTER_DECLARATION(Register, sp, (33));
+// Used as a filler in instructions where a register field is unused.
+const Register dummy_reg = r31_sp;
+
// Use FloatRegister as shortcut
class FloatRegisterImpl;
typedef FloatRegisterImpl* FloatRegister;
diff --git a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp
index 21859656b52..40275cabfa0 100644
--- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp
@@ -61,6 +61,10 @@
#define HWCAP_CRC32 (1<<7)
#endif
+#ifndef HWCAP_ATOMICS
+#define HWCAP_ATOMICS (1<<8)
+#endif
+
int VM_Version::_cpu;
int VM_Version::_model;
int VM_Version::_model2;
@@ -172,6 +176,7 @@ void VM_Version::get_processor_features() {
if (auxv & HWCAP_AES) strcat(buf, ", aes");
if (auxv & HWCAP_SHA1) strcat(buf, ", sha1");
if (auxv & HWCAP_SHA2) strcat(buf, ", sha256");
+ if (auxv & HWCAP_ATOMICS) strcat(buf, ", lse");
_features_string = os::strdup(buf);
@@ -191,6 +196,15 @@ void VM_Version::get_processor_features() {
FLAG_SET_DEFAULT(UseVectorizedMismatchIntrinsic, false);
}
+ if (auxv & HWCAP_ATOMICS) {
+ if (FLAG_IS_DEFAULT(UseLSE))
+ FLAG_SET_DEFAULT(UseLSE, true);
+ } else {
+ if (UseLSE) {
+ warning("UseLSE specified, but not supported on this CPU");
+ }
+ }
+
if (auxv & HWCAP_AES) {
UseAES = UseAES || FLAG_IS_DEFAULT(UseAES);
UseAESIntrinsics =
From af0f23a6173cf2936a7ce1dcf236ef4bab44abc3 Mon Sep 17 00:00:00 2001
From: Ed Nevill
Date: Sat, 20 Feb 2016 15:11:42 +0000
Subject: [PATCH 062/311] 8150082: aarch64: optimise small array copy
Reviewed-by: aph
---
.../cpu/aarch64/vm/stubGenerator_aarch64.cpp | 175 +++++++++++++-----
1 file changed, 126 insertions(+), 49 deletions(-)
diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
index 942d7bc5cb7..b50ad0b1181 100644
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
@@ -729,7 +729,7 @@ class StubGenerator: public StubCodeGenerator {
//
// count is a count of words.
//
- // Precondition: count >= 2
+ // Precondition: count >= 8
//
// Postconditions:
//
@@ -750,7 +750,7 @@ class StubGenerator: public StubCodeGenerator {
assert_different_registers(rscratch1, t0, t1, t2, t3, t4, t5, t6, t7);
assert_different_registers(s, d, count, rscratch1);
- Label again, large, small;
+ Label again, drain;
const char *stub_name;
if (direction == copy_forwards)
stub_name = "foward_copy_longs";
@@ -759,51 +759,21 @@ class StubGenerator: public StubCodeGenerator {
StubCodeMark mark(this, "StubRoutines", stub_name);
__ align(CodeEntryAlignment);
__ bind(start);
- __ cmp(count, 8);
- __ br(Assembler::LO, small);
if (direction == copy_forwards) {
__ sub(s, s, 2 * wordSize);
__ sub(d, d, 2 * wordSize);
}
- __ subs(count, count, 16);
- __ br(Assembler::GE, large);
-
- // 8 <= count < 16 words. Copy 8.
- __ ldp(t0, t1, Address(s, 2 * unit));
- __ ldp(t2, t3, Address(s, 4 * unit));
- __ ldp(t4, t5, Address(s, 6 * unit));
- __ ldp(t6, t7, Address(__ pre(s, 8 * unit)));
-
- __ stp(t0, t1, Address(d, 2 * unit));
- __ stp(t2, t3, Address(d, 4 * unit));
- __ stp(t4, t5, Address(d, 6 * unit));
- __ stp(t6, t7, Address(__ pre(d, 8 * unit)));
-
- if (direction == copy_forwards) {
- __ add(s, s, 2 * wordSize);
- __ add(d, d, 2 * wordSize);
- }
+#ifdef ASSERT
+ // Make sure we are never given < 8 words
{
- Label L1, L2;
- __ bind(small);
- __ tbz(count, exact_log2(4), L1);
- __ ldp(t0, t1, Address(__ adjust(s, 2 * unit, direction == copy_backwards)));
- __ ldp(t2, t3, Address(__ adjust(s, 2 * unit, direction == copy_backwards)));
- __ stp(t0, t1, Address(__ adjust(d, 2 * unit, direction == copy_backwards)));
- __ stp(t2, t3, Address(__ adjust(d, 2 * unit, direction == copy_backwards)));
- __ bind(L1);
-
- __ tbz(count, 1, L2);
- __ ldp(t0, t1, Address(__ adjust(s, 2 * unit, direction == copy_backwards)));
- __ stp(t0, t1, Address(__ adjust(d, 2 * unit, direction == copy_backwards)));
- __ bind(L2);
+ Label L;
+ __ cmp(count, 8);
+ __ br(Assembler::GE, L);
+ __ stop("genrate_copy_longs called with < 8 words");
+ __ bind(L);
}
-
- __ ret(lr);
-
- __ align(CodeEntryAlignment);
- __ bind(large);
+#endif
// Fill 8 registers
__ ldp(t0, t1, Address(s, 2 * unit));
@@ -811,6 +781,9 @@ class StubGenerator: public StubCodeGenerator {
__ ldp(t4, t5, Address(s, 6 * unit));
__ ldp(t6, t7, Address(__ pre(s, 8 * unit)));
+ __ subs(count, count, 16);
+ __ br(Assembler::LO, drain);
+
int prefetch = PrefetchCopyIntervalInBytes;
bool use_stride = false;
if (direction == copy_backwards) {
@@ -837,6 +810,7 @@ class StubGenerator: public StubCodeGenerator {
__ br(Assembler::HS, again);
// Drain
+ __ bind(drain);
__ stp(t0, t1, Address(d, 2 * unit));
__ stp(t2, t3, Address(d, 4 * unit));
__ stp(t4, t5, Address(d, 6 * unit));
@@ -931,16 +905,119 @@ class StubGenerator: public StubCodeGenerator {
int granularity = uabs(step);
const Register t0 = r3, t1 = r4;
+ // <= 96 bytes do inline. Direction doesn't matter because we always
+ // load all the data before writing anything
+ Label copy4, copy8, copy16, copy32, copy80, copy128, copy_big, finish;
+ const Register t2 = r5, t3 = r6, t4 = r7, t5 = r8;
+ const Register t6 = r9, t7 = r10, t8 = r11, t9 = r12;
+ const Register send = r17, dend = r18;
+
+ if (PrefetchCopyIntervalInBytes > 0)
+ __ prfm(Address(s, 0), PLDL1KEEP);
+
+ __ cmp(count, 80/granularity);
+ __ br(Assembler::HI, copy_big);
+
+ __ lea(send, Address(s, count, Address::lsl(exact_log2(granularity))));
+ __ lea(dend, Address(d, count, Address::lsl(exact_log2(granularity))));
+
+ __ cmp(count, 16/granularity);
+ __ br(Assembler::LS, copy16);
+
+ __ cmp(count, 64/granularity);
+ __ br(Assembler::HI, copy80);
+
+ __ cmp(count, 32/granularity);
+ __ br(Assembler::LS, copy32);
+
+ // 33..64 bytes
+ __ ldp(t0, t1, Address(s, 0));
+ __ ldp(t2, t3, Address(s, 16));
+ __ ldp(t4, t5, Address(send, -32));
+ __ ldp(t6, t7, Address(send, -16));
+
+ __ stp(t0, t1, Address(d, 0));
+ __ stp(t2, t3, Address(d, 16));
+ __ stp(t4, t5, Address(dend, -32));
+ __ stp(t6, t7, Address(dend, -16));
+ __ b(finish);
+
+ // 17..32 bytes
+ __ bind(copy32);
+ __ ldp(t0, t1, Address(s, 0));
+ __ ldp(t2, t3, Address(send, -16));
+ __ stp(t0, t1, Address(d, 0));
+ __ stp(t2, t3, Address(dend, -16));
+ __ b(finish);
+
+ // 65..80 bytes
+ __ bind(copy80);
+ __ ldp(t0, t1, Address(s, 0));
+ __ ldp(t2, t3, Address(s, 16));
+ __ ldp(t4, t5, Address(s, 32));
+ __ ldp(t6, t7, Address(s, 48));
+ __ ldp(t8, t9, Address(send, -16));
+
+ __ stp(t0, t1, Address(d, 0));
+ __ stp(t2, t3, Address(d, 16));
+ __ stp(t4, t5, Address(d, 32));
+ __ stp(t6, t7, Address(d, 48));
+ __ stp(t8, t9, Address(dend, -16));
+ __ b(finish);
+
+ // 0..16 bytes
+ __ bind(copy16);
+ __ cmp(count, 8/granularity);
+ __ br(Assembler::LO, copy8);
+
+ // 8..16 bytes
+ __ ldr(t0, Address(s, 0));
+ __ ldr(t1, Address(send, -8));
+ __ str(t0, Address(d, 0));
+ __ str(t1, Address(dend, -8));
+ __ b(finish);
+
+ if (granularity < 8) {
+ // 4..7 bytes
+ __ bind(copy8);
+ __ tbz(count, 2 - exact_log2(granularity), copy4);
+ __ ldrw(t0, Address(s, 0));
+ __ ldrw(t1, Address(send, -4));
+ __ strw(t0, Address(d, 0));
+ __ strw(t1, Address(dend, -4));
+ __ b(finish);
+ if (granularity < 4) {
+ // 0..3 bytes
+ __ bind(copy4);
+ __ cbz(count, finish); // get rid of 0 case
+ if (granularity == 2) {
+ __ ldrh(t0, Address(s, 0));
+ __ strh(t0, Address(d, 0));
+ } else { // granularity == 1
+ // Now 1..3 bytes. Handle the 1 and 2 byte case by copying
+ // the first and last byte.
+ // Handle the 3 byte case by loading and storing base + count/2
+ // (count == 1 (s+0)->(d+0), count == 2,3 (s+1) -> (d+1))
+ // This does means in the 1 byte case we load/store the same
+ // byte 3 times.
+ __ lsr(count, count, 1);
+ __ ldrb(t0, Address(s, 0));
+ __ ldrb(t1, Address(send, -1));
+ __ ldrb(t2, Address(s, count));
+ __ strb(t0, Address(d, 0));
+ __ strb(t1, Address(dend, -1));
+ __ strb(t2, Address(d, count));
+ }
+ __ b(finish);
+ }
+ }
+
+ __ bind(copy_big);
if (is_backwards) {
__ lea(s, Address(s, count, Address::lsl(exact_log2(-step))));
__ lea(d, Address(d, count, Address::lsl(exact_log2(-step))));
}
- Label tail;
-
- __ cmp(count, 16/granularity);
- __ br(Assembler::LO, tail);
-
// Now we've got the small case out of the way we can align the
// source address on a 2-word boundary.
@@ -986,8 +1063,6 @@ class StubGenerator: public StubCodeGenerator {
#endif
}
- __ cmp(count, 16/granularity);
- __ br(Assembler::LT, tail);
__ bind(aligned);
// s is now 2-word-aligned.
@@ -1001,9 +1076,11 @@ class StubGenerator: public StubCodeGenerator {
__ bl(copy_b);
// And the tail.
-
- __ bind(tail);
copy_memory_small(s, d, count, tmp, step);
+
+ if (granularity >= 8) __ bind(copy8);
+ if (granularity >= 4) __ bind(copy4);
+ __ bind(finish);
}
From 5f3739f293a12342e4bdde33719451d51972ef60 Mon Sep 17 00:00:00 2001
From: Ed Nevill
Date: Sat, 20 Feb 2016 15:15:35 +0000
Subject: [PATCH 063/311] 8150313: aarch64: optimise array copy using SIMD
instructions
Reviewed-by: aph
---
.../src/cpu/aarch64/vm/globals_aarch64.hpp | 3 +
.../cpu/aarch64/vm/stubGenerator_aarch64.cpp | 133 +++++++++++-------
2 files changed, 89 insertions(+), 47 deletions(-)
diff --git a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
index bb9dd4d2dc8..60edc02fc2a 100644
--- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
+++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp
@@ -109,6 +109,7 @@ define_pd_global(intx, InlineSmallCode, 1000);
// Don't attempt to use Neon on builtin sim until builtin sim supports it
#define UseCRC32 false
+#define UseSIMDForMemoryOps false
#else
#define UseBuiltinSim false
@@ -126,6 +127,8 @@ define_pd_global(intx, InlineSmallCode, 1000);
"Use Neon for CRC32 computation") \
product(bool, UseCRC32, false, \
"Use CRC32 instructions for CRC32 computation") \
+ product(bool, UseSIMDForMemoryOps, false, \
+ "Use SIMD instructions in generated memory move code") \
product(bool, UseLSE, false, \
"Use LSE instructions") \
product(bool, TraceTraps, false, "Trace all traps the signal handler")
diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
index b50ad0b1181..6ac553302c3 100644
--- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
+++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp
@@ -741,6 +741,7 @@ class StubGenerator: public StubCodeGenerator {
void generate_copy_longs(Label &start, Register s, Register d, Register count,
copy_direction direction) {
int unit = wordSize * direction;
+ int bias = (UseSIMDForMemoryOps ? 4:2) * wordSize;
int offset;
const Register t0 = r3, t1 = r4, t2 = r5, t3 = r6,
@@ -760,8 +761,8 @@ class StubGenerator: public StubCodeGenerator {
__ align(CodeEntryAlignment);
__ bind(start);
if (direction == copy_forwards) {
- __ sub(s, s, 2 * wordSize);
- __ sub(d, d, 2 * wordSize);
+ __ sub(s, s, bias);
+ __ sub(d, d, bias);
}
#ifdef ASSERT
@@ -776,10 +777,15 @@ class StubGenerator: public StubCodeGenerator {
#endif
// Fill 8 registers
- __ ldp(t0, t1, Address(s, 2 * unit));
- __ ldp(t2, t3, Address(s, 4 * unit));
- __ ldp(t4, t5, Address(s, 6 * unit));
- __ ldp(t6, t7, Address(__ pre(s, 8 * unit)));
+ if (UseSIMDForMemoryOps) {
+ __ ldpq(v0, v1, Address(s, 4 * unit));
+ __ ldpq(v2, v3, Address(__ pre(s, 8 * unit)));
+ } else {
+ __ ldp(t0, t1, Address(s, 2 * unit));
+ __ ldp(t2, t3, Address(s, 4 * unit));
+ __ ldp(t4, t5, Address(s, 6 * unit));
+ __ ldp(t6, t7, Address(__ pre(s, 8 * unit)));
+ }
__ subs(count, count, 16);
__ br(Assembler::LO, drain);
@@ -797,39 +803,56 @@ class StubGenerator: public StubCodeGenerator {
if (PrefetchCopyIntervalInBytes > 0)
__ prfm(use_stride ? Address(s, stride) : Address(s, prefetch), PLDL1KEEP);
- __ stp(t0, t1, Address(d, 2 * unit));
- __ ldp(t0, t1, Address(s, 2 * unit));
- __ stp(t2, t3, Address(d, 4 * unit));
- __ ldp(t2, t3, Address(s, 4 * unit));
- __ stp(t4, t5, Address(d, 6 * unit));
- __ ldp(t4, t5, Address(s, 6 * unit));
- __ stp(t6, t7, Address(__ pre(d, 8 * unit)));
- __ ldp(t6, t7, Address(__ pre(s, 8 * unit)));
+ if (UseSIMDForMemoryOps) {
+ __ stpq(v0, v1, Address(d, 4 * unit));
+ __ ldpq(v0, v1, Address(s, 4 * unit));
+ __ stpq(v2, v3, Address(__ pre(d, 8 * unit)));
+ __ ldpq(v2, v3, Address(__ pre(s, 8 * unit)));
+ } else {
+ __ stp(t0, t1, Address(d, 2 * unit));
+ __ ldp(t0, t1, Address(s, 2 * unit));
+ __ stp(t2, t3, Address(d, 4 * unit));
+ __ ldp(t2, t3, Address(s, 4 * unit));
+ __ stp(t4, t5, Address(d, 6 * unit));
+ __ ldp(t4, t5, Address(s, 6 * unit));
+ __ stp(t6, t7, Address(__ pre(d, 8 * unit)));
+ __ ldp(t6, t7, Address(__ pre(s, 8 * unit)));
+ }
__ subs(count, count, 8);
__ br(Assembler::HS, again);
// Drain
__ bind(drain);
- __ stp(t0, t1, Address(d, 2 * unit));
- __ stp(t2, t3, Address(d, 4 * unit));
- __ stp(t4, t5, Address(d, 6 * unit));
- __ stp(t6, t7, Address(__ pre(d, 8 * unit)));
-
- if (direction == copy_forwards) {
- __ add(s, s, 2 * wordSize);
- __ add(d, d, 2 * wordSize);
+ if (UseSIMDForMemoryOps) {
+ __ stpq(v0, v1, Address(d, 4 * unit));
+ __ stpq(v2, v3, Address(__ pre(d, 8 * unit)));
+ } else {
+ __ stp(t0, t1, Address(d, 2 * unit));
+ __ stp(t2, t3, Address(d, 4 * unit));
+ __ stp(t4, t5, Address(d, 6 * unit));
+ __ stp(t6, t7, Address(__ pre(d, 8 * unit)));
}
{
Label L1, L2;
__ tbz(count, exact_log2(4), L1);
- __ ldp(t0, t1, Address(__ adjust(s, 2 * unit, direction == copy_backwards)));
- __ ldp(t2, t3, Address(__ adjust(s, 2 * unit, direction == copy_backwards)));
- __ stp(t0, t1, Address(__ adjust(d, 2 * unit, direction == copy_backwards)));
- __ stp(t2, t3, Address(__ adjust(d, 2 * unit, direction == copy_backwards)));
+ if (UseSIMDForMemoryOps) {
+ __ ldpq(v0, v1, Address(__ pre(s, 4 * unit)));
+ __ stpq(v0, v1, Address(__ pre(d, 4 * unit)));
+ } else {
+ __ ldp(t0, t1, Address(s, 2 * unit));
+ __ ldp(t2, t3, Address(__ pre(s, 4 * unit)));
+ __ stp(t0, t1, Address(d, 2 * unit));
+ __ stp(t2, t3, Address(__ pre(d, 4 * unit)));
+ }
__ bind(L1);
+ if (direction == copy_forwards) {
+ __ add(s, s, 2 * wordSize);
+ __ add(d, d, 2 * wordSize);
+ }
+
__ tbz(count, 1, L2);
__ ldp(t0, t1, Address(__ adjust(s, 2 * unit, direction == copy_backwards)));
__ stp(t0, t1, Address(__ adjust(d, 2 * unit, direction == copy_backwards)));
@@ -914,8 +937,7 @@ class StubGenerator: public StubCodeGenerator {
if (PrefetchCopyIntervalInBytes > 0)
__ prfm(Address(s, 0), PLDL1KEEP);
-
- __ cmp(count, 80/granularity);
+ __ cmp(count, (UseSIMDForMemoryOps ? 96:80)/granularity);
__ br(Assembler::HI, copy_big);
__ lea(send, Address(s, count, Address::lsl(exact_log2(granularity))));
@@ -931,15 +953,22 @@ class StubGenerator: public StubCodeGenerator {
__ br(Assembler::LS, copy32);
// 33..64 bytes
- __ ldp(t0, t1, Address(s, 0));
- __ ldp(t2, t3, Address(s, 16));
- __ ldp(t4, t5, Address(send, -32));
- __ ldp(t6, t7, Address(send, -16));
+ if (UseSIMDForMemoryOps) {
+ __ ldpq(v0, v1, Address(s, 0));
+ __ ldpq(v2, v3, Address(send, -32));
+ __ stpq(v0, v1, Address(d, 0));
+ __ stpq(v2, v3, Address(dend, -32));
+ } else {
+ __ ldp(t0, t1, Address(s, 0));
+ __ ldp(t2, t3, Address(s, 16));
+ __ ldp(t4, t5, Address(send, -32));
+ __ ldp(t6, t7, Address(send, -16));
- __ stp(t0, t1, Address(d, 0));
- __ stp(t2, t3, Address(d, 16));
- __ stp(t4, t5, Address(dend, -32));
- __ stp(t6, t7, Address(dend, -16));
+ __ stp(t0, t1, Address(d, 0));
+ __ stp(t2, t3, Address(d, 16));
+ __ stp(t4, t5, Address(dend, -32));
+ __ stp(t6, t7, Address(dend, -16));
+ }
__ b(finish);
// 17..32 bytes
@@ -950,19 +979,29 @@ class StubGenerator: public StubCodeGenerator {
__ stp(t2, t3, Address(dend, -16));
__ b(finish);
- // 65..80 bytes
+ // 65..80/96 bytes
+ // (96 bytes if SIMD because we do 32 byes per instruction)
__ bind(copy80);
- __ ldp(t0, t1, Address(s, 0));
- __ ldp(t2, t3, Address(s, 16));
- __ ldp(t4, t5, Address(s, 32));
- __ ldp(t6, t7, Address(s, 48));
- __ ldp(t8, t9, Address(send, -16));
+ if (UseSIMDForMemoryOps) {
+ __ ldpq(v0, v1, Address(s, 0));
+ __ ldpq(v2, v3, Address(s, 32));
+ __ ldpq(v4, v5, Address(send, -32));
+ __ stpq(v0, v1, Address(d, 0));
+ __ stpq(v2, v3, Address(d, 32));
+ __ stpq(v4, v5, Address(dend, -32));
+ } else {
+ __ ldp(t0, t1, Address(s, 0));
+ __ ldp(t2, t3, Address(s, 16));
+ __ ldp(t4, t5, Address(s, 32));
+ __ ldp(t6, t7, Address(s, 48));
+ __ ldp(t8, t9, Address(send, -16));
- __ stp(t0, t1, Address(d, 0));
- __ stp(t2, t3, Address(d, 16));
- __ stp(t4, t5, Address(d, 32));
- __ stp(t6, t7, Address(d, 48));
- __ stp(t8, t9, Address(dend, -16));
+ __ stp(t0, t1, Address(d, 0));
+ __ stp(t2, t3, Address(d, 16));
+ __ stp(t4, t5, Address(d, 32));
+ __ stp(t6, t7, Address(d, 48));
+ __ stp(t8, t9, Address(dend, -16));
+ }
__ b(finish);
// 0..16 bytes
From 2011115a3ec220b69d4cfc715869dff26d4e350a Mon Sep 17 00:00:00 2001
From: Magnus Ihse Bursie
Date: Mon, 22 Feb 2016 11:22:55 +0100
Subject: [PATCH 064/311] 8150203: Incremental update from build-infra project
Reviewed-by: erikj
---
common/autoconf/flags.m4 | 1 +
common/autoconf/generated-configure.sh | 16 +++++++++++-----
common/autoconf/libraries.m4 | 14 +++++++++-----
common/autoconf/spec.gmk.in | 2 ++
make/Init.gmk | 3 +++
make/common/NativeCompilation.gmk | 9 ++++++---
6 files changed, 32 insertions(+), 13 deletions(-)
diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4
index c949c93c5cf..1cc71d47058 100644
--- a/common/autoconf/flags.m4
+++ b/common/autoconf/flags.m4
@@ -891,6 +891,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
AC_SUBST(JDKLIB_LIBS)
AC_SUBST(JDKEXE_LIBS)
AC_SUBST(LDFLAGS_CXX_JDK)
+ AC_SUBST(LDFLAGS_HASH_STYLE)
LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB"
LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE"
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index 20d766e7d4e..839422ccb9c 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -701,6 +701,7 @@ COMPILER_SUPPORTS_TARGET_BITS_FLAG
ZERO_ARCHFLAG
LDFLAGS_TESTEXE
LDFLAGS_TESTLIB
+LDFLAGS_HASH_STYLE
LDFLAGS_CXX_JDK
JDKEXE_LIBS
JDKLIB_LIBS
@@ -4230,7 +4231,7 @@ pkgadd_help() {
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, 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
@@ -4860,7 +4861,7 @@ VS_SDK_PLATFORM_NAME_2013=
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1455271513
+DATE_WHEN_GENERATED=1456136545
###############################################################################
#
@@ -46881,6 +46882,7 @@ $as_echo "$supports" >&6; }
+
LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB"
LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE"
@@ -58630,7 +58632,8 @@ fi
# Setup libm (the maths library)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
+ if test "x$OPENJDK_TARGET_OS" != "xwindows"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5
$as_echo_n "checking for cos in -lm... " >&6; }
if ${ac_cv_lib_m_cos+:} false; then :
$as_echo_n "(cached) " >&6
@@ -58675,12 +58678,15 @@ _ACEOF
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: Maths library was not found" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Maths library was not found" >&5
$as_echo "$as_me: Maths library was not found" >&6;}
fi
- LIBM=-lm
+ LIBM="-lm"
+ else
+ LIBM=""
+ fi
# Setup libdl (for dynamic library loading)
diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4
index 7bae405555e..a6a8bd4f19b 100644
--- a/common/autoconf/libraries.m4
+++ b/common/autoconf/libraries.m4
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, 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
@@ -160,10 +160,14 @@ AC_DEFUN_ONCE([LIB_SETUP_LLVM],
AC_DEFUN_ONCE([LIB_SETUP_MISC_LIBS],
[
# Setup libm (the maths library)
- AC_CHECK_LIB(m, cos, [], [
- AC_MSG_NOTICE([Maths library was not found])
- ])
- LIBM=-lm
+ if test "x$OPENJDK_TARGET_OS" != "xwindows"; then
+ AC_CHECK_LIB(m, cos, [], [
+ AC_MSG_NOTICE([Maths library was not found])
+ ])
+ LIBM="-lm"
+ else
+ LIBM=""
+ fi
AC_SUBST(LIBM)
# Setup libdl (for dynamic library loading)
diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in
index 2a6c872cf27..1b178681404 100644
--- a/common/autoconf/spec.gmk.in
+++ b/common/autoconf/spec.gmk.in
@@ -351,6 +351,8 @@ CXXFLAGS_JDKLIB:=@CXXFLAGS_JDKLIB@
CFLAGS_JDKEXE:=@CFLAGS_JDKEXE@
CXXFLAGS_JDKEXE:=@CXXFLAGS_JDKEXE@
+LDFLAGS_HASH_STYLE := @LDFLAGS_HASH_STYLE@
+
CXX:=@FIXPATH@ @CCACHE@ @ICECC@ @CXX@
CPP:=@FIXPATH@ @CPP@
diff --git a/make/Init.gmk b/make/Init.gmk
index 4ed492c68fc..ee67aeaa65f 100644
--- a/make/Init.gmk
+++ b/make/Init.gmk
@@ -154,6 +154,9 @@ ifeq ($(HAS_SPEC),)
# Do nothing
endif
+ # Do not let make delete spec files even if aborted while doing a reconfigure
+ .PRECIOUS: $(SPECS)
+
# Unless reconfigure is explicitely called, let all main targets depend on
# the spec files to be up to date.
ifeq ($(findstring reconfigure, $(INIT_TARGETS)), )
diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk
index 53637fcb953..f16a85182c8 100644
--- a/make/common/NativeCompilation.gmk
+++ b/make/common/NativeCompilation.gmk
@@ -651,12 +651,15 @@ define SetupNativeCompilationBody
$$($1_RES): $$($1_VERSIONINFO_RESOURCE) $$($1_RES_VARDEPS_FILE)
$$(call LogInfo, Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$(notdir $$($1_TARGET))))
+ $$(call MakeDir, $$(@D) $$($1_OBJECT_DIR))
$$(call ExecuteWithLog, $$@, \
$$($1_RC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \
$$($1_VERSIONINFO_RESOURCE))
# Windows RC compiler does not support -showIncludes, so we mis-use CL for this.
- $$($1_CC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \
- $(CC_OUT_OPTION)$$($1_RES_DEP).obj $$($1_VERSIONINFO_RESOURCE) > $$($1_RES_DEP).raw 2>&1 || true ; \
+ $$(call ExecuteWithLog, $$($1_RES_DEP).obj, \
+ $$($1_CC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \
+ $(CC_OUT_OPTION)$$($1_RES_DEP).obj -P -Fi$$($1_RES_DEP).pp \
+ $$($1_VERSIONINFO_RESOURCE)) > $$($1_RES_DEP).raw 2>&1 || true ; \
$(ECHO) $$($1_RES): \\ > $$($1_RES_DEP) ; \
$(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEP).raw >> $$($1_RES_DEP) ; \
$(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_RES_DEP) > $$($1_RES_DEP_TARGETS)
@@ -670,7 +673,7 @@ define SetupNativeCompilationBody
$1_REAL_MAPFILE := $$($1_OBJECT_DIR)/mapfile
$$($1_REAL_MAPFILE) : $$($1_MAPFILE) $$($1_REORDER)
- $$(MKDIR) -p $$(@D)
+ $$(call MakeDir, $$(@D))
$$(CP) $$($1_MAPFILE) $$@.tmp
$$(SED) -e 's=OUTPUTDIR=$$($1_OBJECT_DIR)=' $$($1_REORDER) >> $$@.tmp
$$(MV) $$@.tmp $$@
From 589abd0822a17c5ba206eff93bd4e49bc4c83e92 Mon Sep 17 00:00:00 2001
From: Magnus Ihse Bursie
Date: Mon, 22 Feb 2016 11:23:03 +0100
Subject: [PATCH 065/311] 8150203: Incremental update from build-infra project
Reviewed-by: erikj
---
jdk/make/gensrc/GensrcMisc.gmk | 16 +++++++++-------
jdk/make/lib/Awt2dLibraries.gmk | 6 +++---
jdk/make/lib/CoreLibraries.gmk | 6 +++---
jdk/make/lib/Lib-java.instrument.gmk | 3 +--
jdk/make/lib/Lib-jdk.jdi.gmk | 3 +--
jdk/make/lib/Lib-jdk.jdwp.agent.gmk | 3 +--
.../build/tools/dtdbuilder/DTDParser.java | 6 +-----
7 files changed, 19 insertions(+), 24 deletions(-)
diff --git a/jdk/make/gensrc/GensrcMisc.gmk b/jdk/make/gensrc/GensrcMisc.gmk
index bc70e0e01f0..ffefb50a5b0 100644
--- a/jdk/make/gensrc/GensrcMisc.gmk
+++ b/jdk/make/gensrc/GensrcMisc.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, 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
@@ -53,6 +53,8 @@ SOR_COPYRIGHT_YEARS = $(shell $(CAT) $(GENSRC_SOR_SRC)/$(GENSRC_SOR_SRC_FILE) |
$(eval $(call SetupNativeCompilation, BUILD_GENSRC_SOR_EXE, \
SRC := $(GENSRC_SOR_SRC), \
INCLUDE_FILES := $(GENSRC_SOR_SRC_FILE), \
+ CFLAGS_windows := -nologo, \
+ LDFLAGS_windows := -nologo, \
TOOLCHAIN := TOOLCHAIN_BUILD, \
OBJECT_DIR := $(GENSRC_SOR_BIN), \
OUTPUT_DIR := $(GENSRC_SOR_BIN), \
@@ -61,12 +63,12 @@ $(eval $(call SetupNativeCompilation, BUILD_GENSRC_SOR_EXE, \
SOR_PREGEN_FILE := $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/classes/sun/nio/ch/SocketOptionRegistry-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH).java.template
ifeq ($(wildcard $(SOR_PREGEN_FILE)), )
- $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(BUILD_GENSRC_SOR_EXE)
+ $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(BUILD_GENSRC_SOR_EXE_TARGET)
$(MKDIR) -p $(@D)
$(RM) $@ $@.tmp
NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \
$(JDK_TOPDIR)/make/scripts/addNotices.sh "$(SOR_COPYRIGHT_YEARS)" > $@.tmp
- $(BUILD_GENSRC_SOR_EXE) >> $@.tmp
+ $(BUILD_GENSRC_SOR_EXE_TARGET) >> $@.tmp
$(MV) $@.tmp $@
else
$(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(SOR_PREGEN_FILE)
@@ -97,12 +99,12 @@ ifneq ($(OPENJDK_TARGET_OS), windows)
UC_PREGEN_FILE := $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/classes/sun/nio/fs/UnixConstants-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH).java.template
ifeq ($(wildcard $(UC_PREGEN_FILE)), )
- $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(BUILD_GENSRC_UC_EXE)
+ $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(BUILD_GENSRC_UC_EXE_TARGET)
$(MKDIR) -p $(@D)
$(RM) $@ $@.tmp
NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \
$(JDK_TOPDIR)/make/scripts/addNotices.sh "$(UC_COPYRIGHT_YEARS)" > $@.tmp
- $(BUILD_GENSRC_UC_EXE) >> $@.tmp
+ $(BUILD_GENSRC_UC_EXE_TARGET) >> $@.tmp
$(MV) $@.tmp $@
else
$(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(UC_PREGEN_FILE)
@@ -132,12 +134,12 @@ ifeq ($(OPENJDK_TARGET_OS), solaris)
OUTPUT_DIR := $(GENSRC_SOL_BIN), \
PROGRAM := genSolarisConstants))
- $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java: $(BUILD_GENSRC_SOL_EXE)
+ $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java: $(BUILD_GENSRC_SOL_EXE_TARGET)
$(MKDIR) -p $(@D)
$(RM) $@ $@.tmp
NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \
$(JDK_TOPDIR)/make/scripts/addNotices.sh "$(SOL_COPYRIGHT_YEARS)" > $@.tmp
- $(BUILD_GENSRC_SOL_EXE) >> $@.tmp
+ $(BUILD_GENSRC_SOL_EXE_TARGET) >> $@.tmp
$(MV) $@.tmp $@
diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk
index ad58edb2823..d6ba6443bf2 100644
--- a/jdk/make/lib/Awt2dLibraries.gmk
+++ b/jdk/make/lib/Awt2dLibraries.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, 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
@@ -593,8 +593,8 @@ ifeq ($(BUILD_HEADLESS), true)
LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \
REORDER := $(LIBAWT_HEADLESS_REORDER), \
LIBS_unix := -lawt -ljvm -ljava, \
- LIBS_linux := -lm $(LIBDL), \
- LIBS_solaris := -lm $(LIBDL) $(LIBCXX) -lc, \
+ LIBS_linux := $(LIBM) $(LIBDL), \
+ LIBS_solaris := $(LIBM) $(LIBDL) $(LIBCXX) -lc, \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libawt_headless, \
))
diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk
index ea7c7f3c991..bd707071427 100644
--- a/jdk/make/lib/CoreLibraries.gmk
+++ b/jdk/make/lib/CoreLibraries.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, 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
@@ -163,7 +163,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \
LIBS_unix := -ljvm -lverify, \
LIBS_linux := $(LIBDL) $(BUILD_LIBFDLIBM), \
LIBS_solaris := -lsocket -lnsl -lscf $(LIBDL) $(BUILD_LIBFDLIBM) -lc, \
- LIBS_aix := $(LIBDL) $(BUILD_LIBFDLIBM) -lm,\
+ LIBS_aix := $(LIBDL) $(BUILD_LIBFDLIBM) $(LIBM),\
LIBS_macosx := -lfdlibm \
-framework CoreFoundation \
-framework Foundation \
@@ -225,7 +225,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBZIP, \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_windows := -export:ZIP_Open -export:ZIP_Close -export:ZIP_FindEntry \
-export:ZIP_ReadEntry -export:ZIP_GetNextEntry \
- -export:ZIP_InflateFully -export:ZIP_CRC32, \
+ -export:ZIP_InflateFully, \
LIBS_unix := -ljvm -ljava $(LIBZ), \
LIBS_solaris := -lc, \
LIBS_windows := jvm.lib $(WIN_JAVA_LIB), \
diff --git a/jdk/make/lib/Lib-java.instrument.gmk b/jdk/make/lib/Lib-java.instrument.gmk
index 02df76073af..44ba88dad40 100644
--- a/jdk/make/lib/Lib-java.instrument.gmk
+++ b/jdk/make/lib/Lib-java.instrument.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, 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
@@ -67,7 +67,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBINSTRUMENT, \
-L$(call FindLibDirForModule, java.base)/jli, \
LDFLAGS_macosx := -Wl$(COMMA)-all_load, \
LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \
- LDFLAGS_windows := -export:Agent_OnAttach, \
LIBS := $(JDKLIB_LIBS), \
LIBS_unix := -ljava $(LIBZ), \
LIBS_linux := -ljli $(LIBDL), \
diff --git a/jdk/make/lib/Lib-jdk.jdi.gmk b/jdk/make/lib/Lib-jdk.jdi.gmk
index 8bed1f9abd1..bb1edfd1c23 100644
--- a/jdk/make/lib/Lib-jdk.jdi.gmk
+++ b/jdk/make/lib/Lib-jdk.jdi.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, 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
@@ -47,7 +47,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \
$(LIBDT_SHMEM_CPPFLAGS), \
LDFLAGS := $(LDFLAGS_JDKLIB), \
- LDFLAGS_windows := -export:jdwpTransport_OnLoad, \
LIBS := $(JDKLIB_LIBS), \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
RC_FLAGS := $(RC_FLAGS) \
diff --git a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk
index 198dc2c2433..84c05ba6368 100644
--- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk
+++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2016, 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
@@ -46,7 +46,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBDT_SOCKET, \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libdt_socket/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
- LDFLAGS_windows := -export:jdwpTransport_OnLoad, \
LIBS_linux := -lpthread, \
LIBS_solaris := -lnsl -lsocket -lc, \
LIBS_windows := $(JDKLIB_LIBS) ws2_32.lib, \
diff --git a/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java b/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java
index 0dee68e367f..8ef7cfe13b0 100644
--- a/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java
+++ b/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -908,16 +908,12 @@ class DTDParser implements DTDConstants {
this.dtd = dtd;
this.in = new DTDInputStream(in, dtd);
- long tm = System.currentTimeMillis();
ch = this.in.read();
parseSection();
if (ch != -1) {
error("premature");
}
-
- tm = System.currentTimeMillis() - tm;
- System.err.println("[Parsed DTD " + dtd + " in " + tm + "ms]");
} catch (IOException e) {
error("ioexception");
} catch (Exception e) {
From 4b8c19d6b707315811bd697f2221dccb6c494d63 Mon Sep 17 00:00:00 2001
From: Volker Simonis
Date: Mon, 22 Feb 2016 11:27:09 +0100
Subject: [PATCH 066/311] 8150197: Integrate AIX fixes from build-infra
Reviewed-by: erikj
---
common/autoconf/flags.m4 | 24 ++++++++++++++++++++---
common/autoconf/generated-configure.sh | 27 ++++++++++++++++++++++----
common/autoconf/spec.gmk.in | 4 ++++
make/common/NativeCompilation.gmk | 5 +++++
4 files changed, 53 insertions(+), 7 deletions(-)
diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4
index 1cc71d47058..6b08cbb0a4f 100644
--- a/common/autoconf/flags.m4
+++ b/common/autoconf/flags.m4
@@ -123,12 +123,16 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS],
[
# COMPILER_TARGET_BITS_FLAG : option for selecting 32- or 64-bit output
# COMPILER_COMMAND_FILE_FLAG : option for passing a command file to the compiler
+ # COMPILER_BINDCMD_FILE_FLAG : option for specifying a file which saves the binder
+ # commands produced by the link step (currently AIX only)
if test "x$TOOLCHAIN_TYPE" = xxlc; then
COMPILER_TARGET_BITS_FLAG="-q"
COMPILER_COMMAND_FILE_FLAG="-f"
+ COMPILER_BINDCMD_FILE_FLAG="-bloadmap:"
else
COMPILER_TARGET_BITS_FLAG="-m"
COMPILER_COMMAND_FILE_FLAG="@"
+ COMPILER_BINDCMD_FILE_FLAG=""
# The solstudio linker does not support @-files.
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
@@ -152,6 +156,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS],
fi
AC_SUBST(COMPILER_TARGET_BITS_FLAG)
AC_SUBST(COMPILER_COMMAND_FILE_FLAG)
+ AC_SUBST(COMPILER_BINDCMD_FILE_FLAG)
# FIXME: figure out if we should select AR flags depending on OS or toolchain.
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
@@ -294,10 +299,23 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS],
SET_SHARED_LIBRARY_NAME='-h [$]1'
SET_SHARED_LIBRARY_MAPFILE='-M[$]1'
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
- PICFLAG="-qpic=large"
+ # '-qpic' defaults to 'qpic=small'. This means that the compiler generates only
+ # one instruction for accessing the TOC. If the TOC grows larger than 64K, the linker
+ # will have to patch this single instruction with a call to some out-of-order code which
+ # does the load from the TOC. This is of course slow. But in that case we also would have
+ # to use '-bbigtoc' for linking anyway so we could also change the PICFLAG to 'qpic=large'.
+ # With 'qpic=large' the compiler will by default generate a two-instruction sequence which
+ # can be patched directly by the linker and does not require a jump to out-of-order code.
+ # Another alternative instead of using 'qpic=large -bbigtoc' may be to use '-qminimaltoc'
+ # instead. This creates a distinct TOC for every compilation unit (and thus requires two
+ # loads for accessing a global variable). But there are rumors that this may be seen as a
+ # 'performance feature' because of improved code locality of the symbols used in a
+ # compilation unit.
+ PICFLAG="-qpic"
+ JVM_CFLAGS="$JVM_CFLAGS $PICFLAG"
C_FLAG_REORDER=''
CXX_FLAG_REORDER=''
- SHARED_LIBRARY_FLAGS="-qmkshrobj"
+ SHARED_LIBRARY_FLAGS="-qmkshrobj -bM:SRE -bnoentry"
SET_EXECUTABLE_ORIGIN=""
SET_SHARED_LIBRARY_ORIGIN=''
SET_SHARED_LIBRARY_NAME=''
@@ -835,7 +853,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
LDFLAGS_CXX_SOLSTUDIO="-norunpath"
LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib"
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
- LDFLAGS_XLC="-brtl -bnolibpath -bexpall -bernotok"
+ LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok"
LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC"
fi
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index 839422ccb9c..7a9d7900667 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -744,6 +744,7 @@ EXE_OUT_OPTION
CC_OUT_OPTION
STRIPFLAGS
ARFLAGS
+COMPILER_BINDCMD_FILE_FLAG
COMPILER_COMMAND_FILE_FLAG
COMPILER_TARGET_BITS_FLAG
JT_HOME
@@ -4861,7 +4862,7 @@ VS_SDK_PLATFORM_NAME_2013=
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1456136545
+DATE_WHEN_GENERATED=1456136781
###############################################################################
#
@@ -45392,12 +45393,16 @@ $as_echo "$tool_specified" >&6; }
# COMPILER_TARGET_BITS_FLAG : option for selecting 32- or 64-bit output
# COMPILER_COMMAND_FILE_FLAG : option for passing a command file to the compiler
+ # COMPILER_BINDCMD_FILE_FLAG : option for specifying a file which saves the binder
+ # commands produced by the link step (currently AIX only)
if test "x$TOOLCHAIN_TYPE" = xxlc; then
COMPILER_TARGET_BITS_FLAG="-q"
COMPILER_COMMAND_FILE_FLAG="-f"
+ COMPILER_BINDCMD_FILE_FLAG="-bloadmap:"
else
COMPILER_TARGET_BITS_FLAG="-m"
COMPILER_COMMAND_FILE_FLAG="@"
+ COMPILER_BINDCMD_FILE_FLAG=""
# The solstudio linker does not support @-files.
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
@@ -45425,6 +45430,7 @@ $as_echo "no" >&6; }
+
# FIXME: figure out if we should select AR flags depending on OS or toolchain.
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
ARFLAGS="-r"
@@ -46199,10 +46205,23 @@ $as_echo "$ac_cv_c_bigendian" >&6; }
SET_SHARED_LIBRARY_NAME='-h $1'
SET_SHARED_LIBRARY_MAPFILE='-M$1'
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
- PICFLAG="-qpic=large"
+ # '-qpic' defaults to 'qpic=small'. This means that the compiler generates only
+ # one instruction for accessing the TOC. If the TOC grows larger than 64K, the linker
+ # will have to patch this single instruction with a call to some out-of-order code which
+ # does the load from the TOC. This is of course slow. But in that case we also would have
+ # to use '-bbigtoc' for linking anyway so we could also change the PICFLAG to 'qpic=large'.
+ # With 'qpic=large' the compiler will by default generate a two-instruction sequence which
+ # can be patched directly by the linker and does not require a jump to out-of-order code.
+ # Another alternative instead of using 'qpic=large -bbigtoc' may be to use '-qminimaltoc'
+ # instead. This creates a distinct TOC for every compilation unit (and thus requires two
+ # loads for accessing a global variable). But there are rumors that this may be seen as a
+ # 'performance feature' because of improved code locality of the symbols used in a
+ # compilation unit.
+ PICFLAG="-qpic"
+ JVM_CFLAGS="$JVM_CFLAGS $PICFLAG"
C_FLAG_REORDER=''
CXX_FLAG_REORDER=''
- SHARED_LIBRARY_FLAGS="-qmkshrobj"
+ SHARED_LIBRARY_FLAGS="-qmkshrobj -bM:SRE -bnoentry"
SET_EXECUTABLE_ORIGIN=""
SET_SHARED_LIBRARY_ORIGIN=''
SET_SHARED_LIBRARY_NAME=''
@@ -46825,7 +46844,7 @@ $as_echo "$supports" >&6; }
LDFLAGS_CXX_SOLSTUDIO="-norunpath"
LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib"
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
- LDFLAGS_XLC="-brtl -bnolibpath -bexpall -bernotok"
+ LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok"
LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC"
fi
diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in
index 1b178681404..d8322ebce9c 100644
--- a/common/autoconf/spec.gmk.in
+++ b/common/autoconf/spec.gmk.in
@@ -314,6 +314,10 @@ COMPILER_SUPPORTS_TARGET_BITS_FLAG=@COMPILER_SUPPORTS_TARGET_BITS_FLAG@
# Option used to pass a command file to the compiler
COMPILER_COMMAND_FILE_FLAG:=@COMPILER_COMMAND_FILE_FLAG@
+# Option for specifying a file which saves the binder commands
+# produced by the link step (for debugging, currently AIX only)
+COMPILER_BINDCMD_FILE_FLAG:=@COMPILER_BINDCMD_FILE_FLAG@
+
CC_OUT_OPTION:=@CC_OUT_OPTION@
EXE_OUT_OPTION:=@EXE_OUT_OPTION@
LD_OUT_OPTION:=@LD_OUT_OPTION@
diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk
index f16a85182c8..ffae49df541 100644
--- a/make/common/NativeCompilation.gmk
+++ b/make/common/NativeCompilation.gmk
@@ -771,6 +771,11 @@ define SetupNativeCompilationBody
$1_EXTRA_LDFLAGS += "-implib:$$($1_OBJECT_DIR)/$$($1_LIBRARY).lib"
endif
+ # Create loadmap on AIX. Helps in diagnosing some problems.
+ ifneq ($(COMPILER_BINDCMD_FILE_FLAG),)
+ $1_EXTRA_LDFLAGS += $(COMPILER_BINDCMD_FILE_FLAG)$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).loadmap
+ endif
+
$1_EXTRA_LIBS += $(GLOBAL_LIBS)
$1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \
From 0c28c2ee37928055b5aaafd7ec3e0e5ca46c5025 Mon Sep 17 00:00:00 2001
From: Jon Masamitsu
Date: Mon, 22 Feb 2016 09:41:56 -0800
Subject: [PATCH 067/311] 8150302: Reference processing logging prints the
"from list" incorrectly
Reviewed-by: tamao, brutisso
---
hotspot/src/share/vm/gc/shared/referenceProcessor.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp
index 544cf81001d..7b3616ff168 100644
--- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp
+++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp
@@ -339,7 +339,7 @@ void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list,
// all linked Reference objects. Note that it is important to not dirty any
// cards during reference processing since this will cause card table
// verification to fail for G1.
- log_develop_trace(gc, ref)("ReferenceProcessor::enqueue_discovered_reflist list " INTPTR_FORMAT, p2i(refs_list.head()));
+ log_develop_trace(gc, ref)("ReferenceProcessor::enqueue_discovered_reflist list " INTPTR_FORMAT, p2i(&refs_list));
oop obj = NULL;
oop next_d = refs_list.head();
@@ -502,7 +502,7 @@ ReferenceProcessor::process_phase1(DiscoveredList& refs_list,
// Close the reachable set
complete_gc->do_void();
log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " dead Refs out of " SIZE_FORMAT " discovered Refs by policy, from list " INTPTR_FORMAT,
- iter.removed(), iter.processed(), p2i(refs_list.head()));
+ iter.removed(), iter.processed(), p2i(&refs_list));
}
// Traverse the list and remove any Refs that are not active, or
@@ -536,7 +536,7 @@ ReferenceProcessor::pp2_work(DiscoveredList& refs_list,
if (iter.processed() > 0) {
log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " active Refs out of " SIZE_FORMAT
" Refs in discovered list " INTPTR_FORMAT,
- iter.removed(), iter.processed(), p2i(refs_list.head()));
+ iter.removed(), iter.processed(), p2i(&refs_list));
}
)
}
@@ -575,7 +575,7 @@ ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList& refs_list,
if (iter.processed() > 0) {
log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " active Refs out of " SIZE_FORMAT
" Refs in discovered list " INTPTR_FORMAT,
- iter.removed(), iter.processed(), p2i(refs_list.head()));
+ iter.removed(), iter.processed(), p2i(&refs_list));
}
)
}
@@ -1198,7 +1198,7 @@ ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list,
NOT_PRODUCT(
if (iter.processed() > 0) {
log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " Refs out of " SIZE_FORMAT " Refs in discovered list " INTPTR_FORMAT,
- iter.removed(), iter.processed(), p2i(refs_list.head()));
+ iter.removed(), iter.processed(), p2i(&refs_list));
}
)
}
From 5b5e0a63e76a979ee2e3db3adf3c76151320406a Mon Sep 17 00:00:00 2001
From: Christoph Langer
Date: Mon, 22 Feb 2016 11:00:06 -0800
Subject: [PATCH 068/311] 8149915: enabling validate-annotations feature for
xsd schema with annotation causes NPE
Reviewed-by: joehw
---
.../internal/impl/XML11DTDScannerImpl.java | 10 -
.../internal/impl/XMLDTDScannerImpl.java | 3 +-
.../impl/XMLDocumentFragmentScannerImpl.java | 19 +-
.../internal/impl/XMLDocumentScannerImpl.java | 6 +-
.../internal/impl/XMLEntityManager.java | 21 +-
.../impl/XMLNSDocumentScannerImpl.java | 8 +-
.../xerces/internal/impl/XMLScanner.java | 9 +-
.../xs/traversers/XSAttributeChecker.java | 8 +-
.../impl/xs/traversers/XSDHandler.java | 224 +++++++++---------
.../internal/parsers/XML11Configuration.java | 159 ++++++-------
.../xerces/internal/util/HTTPInputSource.java | 6 +-
.../jaxp/unittest/validation/Bug8149915.xsd | 7 +
.../jaxp/unittest/validation/SchemaTest.java | 50 ++++
13 files changed, 270 insertions(+), 260 deletions(-)
create mode 100644 jaxp/test/javax/xml/jaxp/unittest/validation/Bug8149915.xsd
create mode 100644 jaxp/test/javax/xml/jaxp/unittest/validation/SchemaTest.java
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java
index e3336e3bee4..d6648b75bcb 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java
@@ -97,19 +97,9 @@ import com.sun.org.apache.xerces.internal.xni.XNIException;
public class XML11DTDScannerImpl
extends XMLDTDScannerImpl {
- /** Array of 3 strings. */
- private String[] fStrings = new String[3];
-
- /** String. */
- private XMLString fString = new XMLString();
-
/** String buffer. */
private XMLStringBuffer fStringBuffer = new XMLStringBuffer();
- /** String buffer. */
- private XMLStringBuffer fStringBuffer2 = new XMLStringBuffer();
- private XMLStringBuffer fStringBuffer3 = new XMLStringBuffer();
-
//
// Constructors
//
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java
index 591e4601efe..4daa5f0e333 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -46,7 +46,6 @@ import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler;
import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
-import com.sun.xml.internal.stream.Entity;
/**
* This class is responsible for scanning the declarations found
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java
index 1ea57877573..e31e838c8e8 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -23,7 +23,6 @@ package com.sun.org.apache.xerces.internal.impl;
import com.sun.xml.internal.stream.XMLBufferListener;
import com.sun.xml.internal.stream.XMLEntityStorage;
-import com.sun.xml.internal.stream.XMLInputFactoryImpl;
import com.sun.xml.internal.stream.dtd.DTDGrammarUtil;
import java.io.EOFException;
@@ -50,17 +49,11 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
import com.sun.org.apache.xerces.internal.xni.Augmentations;
import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler;
-import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
-import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit;
-import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.State;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
-import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
-import javax.xml.XMLConstants;
import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.events.XMLEvent;
/**
*
@@ -210,12 +203,12 @@ public class XMLDocumentFragmentScannerImpl
null,
null,
null,
- EXTERNAL_ACCESS_DEFAULT
+ null
};
private static final char [] cdata = {'[','C','D','A','T','A','['};
static final char [] xmlDecl = {'<','?','x','m','l'};
- private static final char [] endTag = {'<','/'};
+ // private static final char [] endTag = {'<','/'};
// debugging
/** Debug scanner state. */
@@ -2066,7 +2059,7 @@ public class XMLDocumentFragmentScannerImpl
*/
String checkAccess(String systemId, String allowedProtocols) throws IOException {
String baseSystemId = fEntityScanner.getBaseSystemId();
- String expandedSystemId = fEntityManager.expandSystemId(systemId, baseSystemId,fStrictURI);
+ String expandedSystemId = XMLEntityManager.expandSystemId(systemId, baseSystemId, fStrictURI);
return SecuritySupport.checkAccess(expandedSystemId, allowedProtocols, Constants.ACCESS_EXTERNAL_ALL);
}
@@ -2602,8 +2595,6 @@ public class XMLDocumentFragmentScannerImpl
//
// Driver methods
//
- private boolean fContinueDispatching = true;
- private boolean fScanningForMarkup = true;
/**
* decides the appropriate state of the parser
@@ -3266,7 +3257,7 @@ public class XMLDocumentFragmentScannerImpl
protected XMLString getString(){
if(fAttributeCacheUsedCount < initialCacheCount || fAttributeCacheUsedCount < attributeValueCache.size()){
- return (XMLString)attributeValueCache.get(fAttributeCacheUsedCount++);
+ return attributeValueCache.get(fAttributeCacheUsedCount++);
} else{
XMLString str = new XMLString();
fAttributeCacheUsedCount++;
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java
index 5a48b73aa52..7f1bbf10226 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -31,7 +31,6 @@ import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
import com.sun.org.apache.xerces.internal.xni.Augmentations;
import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
-import com.sun.org.apache.xerces.internal.xni.XMLString;
import com.sun.org.apache.xerces.internal.xni.XNIException;
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
@@ -224,9 +223,6 @@ public class XMLDocumentScannerImpl
/** A DTD Description. */
private final XMLDTDDescription fDTDDescription = new XMLDTDDescription(null, null, null, null, null);
- /** String. */
- private XMLString fString = new XMLString();
-
private static final char [] DOCTYPE = {'D','O','C','T','Y','P','E'};
private static final char [] COMMENTSTRING = {'-','-'};
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java
index ff96275c433..f08a1275dfa 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -370,7 +370,7 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver {
protected Map fEntities = new HashMap<>();
/** Entity stack. */
- protected Stack fEntityStack = new Stack();
+ protected Stack fEntityStack = new Stack<>();
/** Current entity. */
protected Entity.ScannedEntity fCurrentEntity = null;
@@ -633,10 +633,10 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver {
final HTTPInputSource httpInputSource = (HTTPInputSource) xmlInputSource;
// set request properties
- Iterator propIter = httpInputSource.getHTTPRequestProperties();
+ Iterator> propIter = httpInputSource.getHTTPRequestProperties();
while (propIter.hasNext()) {
- Map.Entry entry = (Map.Entry) propIter.next();
- urlConnection.setRequestProperty((String) entry.getKey(), (String) entry.getValue());
+ Map.Entry entry = propIter.next();
+ urlConnection.setRequestProperty(entry.getKey(), entry.getValue());
}
// set preference for redirection
@@ -1057,7 +1057,6 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver {
String literalSystemId = resourceIdentifier.getLiteralSystemId();
String baseSystemId = resourceIdentifier.getBaseSystemId();
String expandedSystemId = resourceIdentifier.getExpandedSystemId();
- String namespace = resourceIdentifier.getNamespace();
// if no base systemId given, assume that it's relative
// to the systemId of the current scanned entity
@@ -2067,14 +2066,6 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver {
// system id has to be a valid URI
if (strict) {
-
-
- // check if there is a system id before
- // trying to expand it.
- if (systemId == null) {
- return null;
- }
-
try {
// if it's already an absolute one, return it
new URI(systemId);
@@ -2968,7 +2959,7 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver {
if (!fCurrentEntity.xmlDeclChunkRead)
{
fCurrentEntity.xmlDeclChunkRead = true;
- len = fCurrentEntity.DEFAULT_XMLDECL_BUFFER_SIZE;
+ len = DEFAULT_XMLDECL_BUFFER_SIZE;
}
return fInputStream.read(b, off, len);
}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java
index 8badd36d876..2cdb0001322 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -25,8 +25,6 @@ import com.sun.org.apache.xerces.internal.xni.XMLString;
import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidatorFilter;
import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
-import com.sun.org.apache.xerces.internal.util.XMLAttributesIteratorImpl;
-import com.sun.org.apache.xerces.internal.util.XMLStringBuffer;
import com.sun.org.apache.xerces.internal.util.XMLSymbols;
import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
import com.sun.org.apache.xerces.internal.xni.QName;
@@ -34,13 +32,9 @@ import com.sun.org.apache.xerces.internal.xni.XNIException;
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
-import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
-import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.events.XMLEvent;
/**
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java
index 10c484ac3a3..5ead2dd1fc6 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -25,7 +25,6 @@ import com.sun.org.apache.xerces.internal.util.Status;
import com.sun.xml.internal.stream.XMLEntityStorage;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.HashMap;
import javax.xml.stream.events.XMLEvent;
import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
import com.sun.org.apache.xerces.internal.util.SymbolTable;
@@ -120,8 +119,8 @@ public abstract class XMLScanner
//we should have a feature when set to true computes this value
private boolean fNeedNonNormalizedValue = false;
- protected ArrayList attributeValueCache = new ArrayList();
- protected ArrayList stringBufferCache = new ArrayList();
+ protected ArrayList attributeValueCache = new ArrayList<>();
+ protected ArrayList stringBufferCache = new ArrayList<>();
protected int fStringBufferIndex = 0;
protected boolean fAttributeCacheInitDone = false;
protected int fAttributeCacheUsedCount = 0;
@@ -1470,7 +1469,7 @@ public abstract class XMLScanner
XMLStringBuffer getStringBuffer(){
if((fStringBufferIndex < initialCacheCount )|| (fStringBufferIndex < stringBufferCache.size())){
- return (XMLStringBuffer)stringBufferCache.get(fStringBufferIndex++);
+ return stringBufferCache.get(fStringBufferIndex++);
}else{
XMLStringBuffer tmpObj = new XMLStringBuffer();
fStringBufferIndex++;
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java
index f9a9fe309ac..816cdaa4757 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -1172,7 +1172,7 @@ public class XSAttributeChecker {
if (max != SchemaSymbols.OCCURRENCE_UNBOUNDED) {
// maxOccurLimit is only check in secure mode
- if (fSchemaHandler.fSecureProcessing != null) {
+ if (fSchemaHandler.fSecurityManager != null) {
String localName = element.getLocalName();
// The maxOccurs restriction no longer applies to elements
@@ -1191,8 +1191,8 @@ public class XSAttributeChecker {
if (!optimize) {
//Revisit :: IMO this is not right place to check
// maxOccurNodeLimit.
- int maxOccurNodeLimit = fSchemaHandler.fSecureProcessing.getLimit(XMLSecurityManager.Limit.MAX_OCCUR_NODE_LIMIT);
- if (max > maxOccurNodeLimit && !fSchemaHandler.fSecureProcessing.isNoLimit(maxOccurNodeLimit)) {
+ int maxOccurNodeLimit = fSchemaHandler.fSecurityManager.getLimit(XMLSecurityManager.Limit.MAX_OCCUR_NODE_LIMIT);
+ if (max > maxOccurNodeLimit && !fSchemaHandler.fSecurityManager.isNoLimit(maxOccurNodeLimit)) {
reportSchemaFatalError("MaxOccurLimit", new Object[] {new Integer(maxOccurNodeLimit)}, element);
// reset max values in case processing continues on error
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java
index 852a09fb87f..d1671179b00 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -194,6 +194,7 @@ public class XSDHandler {
/** Property identifier: entity resolver. */
public static final String ENTITY_RESOLVER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
+
/** Property identifier: entity manager. */
protected static final String ENTITY_MANAGER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
@@ -214,16 +215,13 @@ public class XSDHandler {
protected static final String SECURITY_MANAGER =
Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
- private static final String SECURE_PROCESSING =
- Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
-
/** Property identifier: locale. */
protected static final String LOCALE =
Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
- /** Property identifier: Security property manager. */
+ /** Property identifier: Security property manager. */
private static final String XML_SECURITY_PROPERTY_MANAGER =
- Constants.XML_SECURITY_PROPERTY_MANAGER;
+ Constants.XML_SECURITY_PROPERTY_MANAGER;
protected static final boolean DEBUG_NODE_POOL = false;
@@ -243,17 +241,12 @@ public class XSDHandler {
// as unlikely as possible to cause collisions.
public final static String REDEF_IDENTIFIER = "_fn3dktizrknc9pi";
- //
- //protected data that can be accessable by any traverser
+ //protected data that can be accessible by any traverser
protected XSDeclarationPool fDeclPool = null;
- /**
- * Security manager in effect.
- *
- * Protected to allow access by any traverser.
- */
- protected XMLSecurityManager fSecureProcessing = null;
+ // the Security manager in effect.
+ protected XMLSecurityManager fSecurityManager = null;
private String fAccessExternalSchema;
private String fAccessExternalDTD;
@@ -266,27 +259,28 @@ public class XSDHandler {
// XSDocumentInfoRegistry we can easily get the corresponding
// XSDocumentInfo object.
private boolean registryEmpty = true;
- private Map fUnparsedAttributeRegistry = new HashMap();
- private Map fUnparsedAttributeGroupRegistry = new HashMap();
- private Map fUnparsedElementRegistry = new HashMap();
- private Map fUnparsedGroupRegistry = new HashMap();
- private Map fUnparsedIdentityConstraintRegistry = new HashMap();
- private Map fUnparsedNotationRegistry = new HashMap();
- private Map fUnparsedTypeRegistry = new HashMap();
+ private Map fUnparsedAttributeRegistry = new HashMap<>();
+ private Map fUnparsedAttributeGroupRegistry = new HashMap<>();
+ private Map fUnparsedElementRegistry = new HashMap<>();
+ private Map fUnparsedGroupRegistry = new HashMap<>();
+ private Map fUnparsedIdentityConstraintRegistry = new HashMap<>();
+ private Map fUnparsedNotationRegistry = new HashMap<>();
+ private Map fUnparsedTypeRegistry = new HashMap<>();
// Compensation for the above maps to locate XSDocumentInfo,
// Since we may take Schema Element directly, so can not get the
// corresponding XSDocumentInfo object just using above maps.
- private Map fUnparsedAttributeRegistrySub = new HashMap();
- private Map fUnparsedAttributeGroupRegistrySub = new HashMap();
- private Map fUnparsedElementRegistrySub = new HashMap();
- private Map fUnparsedGroupRegistrySub = new HashMap();
- private Map fUnparsedIdentityConstraintRegistrySub = new HashMap();
- private Map fUnparsedNotationRegistrySub = new HashMap();
- private Map fUnparsedTypeRegistrySub = new HashMap();
+ private Map fUnparsedAttributeRegistrySub = new HashMap<>();
+ private Map fUnparsedAttributeGroupRegistrySub = new HashMap<>();
+ private Map fUnparsedElementRegistrySub = new HashMap<>();
+ private Map fUnparsedGroupRegistrySub = new HashMap<>();
+ private Map fUnparsedIdentityConstraintRegistrySub = new HashMap<>();
+ private Map fUnparsedNotationRegistrySub = new HashMap<>();
+ private Map fUnparsedTypeRegistrySub = new HashMap<>();
// Stores XSDocumentInfo (keyed by component name), to check for duplicate
// components declared within the same xsd document
- private Map fUnparsedRegistriesExt[] = new HashMap[] {
+ @SuppressWarnings("unchecked")
+ private Map fUnparsedRegistriesExt[] = new HashMap[] {
null,
null, // ATTRIBUTE_TYPE
null, // ATTRIBUTEGROUP_TYPE
@@ -300,17 +294,19 @@ public class XSDHandler {
// this map is keyed on by XSDocumentInfo objects. Its values
// are Vectors containing the XSDocumentInfo objects d,
// ed or d by the key XSDocumentInfo.
- private Map fDependencyMap = new HashMap();
+ private Map> fDependencyMap = new HashMap<>();
// this map is keyed on by a target namespace. Its values
// are Vectors containing namespaces imported by schema documents
// with the key target namespace.
- // if an imprted schema has absent namespace, the value "null" is stored.
- private Map fImportMap = new HashMap();
+ // if an imported schema has absent namespace, the value "null" is stored.
+ private Map fImportMap = new HashMap<> ();
+
// all namespaces that imports other namespaces
// if the importing schema has absent namespace, empty string is stored.
// (because the key of a map can't be null.)
- private Vector fAllTNSs = new Vector();
+ private Vector fAllTNSs = new Vector<>();
+
// stores instance document mappings between namespaces and schema hints
private Map fLocationPairs = null;
@@ -333,7 +329,7 @@ public class XSDHandler {
if(ele.getOwnerDocument() instanceof com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM){
documentURI = ((com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM) ele.getOwnerDocument()).getDocumentURI();
}
- return documentURI != null ? documentURI : (String) fDoc2SystemId.get(ele);
+ return documentURI != null ? documentURI : fDoc2SystemId.get(ele);
}
// This vector stores strings which are combinations of the
@@ -341,11 +337,11 @@ public class XSDHandler {
// schema document. This combination is used so that the user's
// EntityResolver can provide a consistent way of identifying a
// schema document that is included in multiple other schemas.
- private Map fTraversed = new HashMap();
+ private Map fTraversed = new HashMap<>();
// this map contains a mapping from Schema Element to its systemId
// this is useful to resolve a uri relative to the referring document
- private Map fDoc2SystemId = new HashMap();
+ private Map fDoc2SystemId = new HashMap<>();
// the primary XSDocumentInfo we were called to parse
private XSDocumentInfo fRoot = null;
@@ -387,7 +383,15 @@ public class XSDHandler {
// the XMLErrorReporter
private XMLErrorReporter fErrorReporter;
- private XMLEntityResolver fEntityResolver;
+
+ // the XMLErrorHandler
+ private XMLErrorHandler fErrorHandler;
+
+ // the Locale
+ private Locale fLocale;
+
+ // the XMLEntityManager
+ private XMLEntityResolver fEntityManager;
// the XSAttributeChecker
private XSAttributeChecker fAttributeChecker;
@@ -404,6 +408,9 @@ public class XSDHandler {
// the Grammar Pool
private XMLGrammarPool fGrammarPool;
+ // the security property manager
+ private XMLSecurityPropertyManager fSecurityPropertyMgr = null;
+
//************ Traversers **********
XSDAttributeGroupTraverser fAttributeGroupTraverser;
XSDAttributeTraverser fAttributeTraverser;
@@ -638,7 +645,7 @@ public class XSDHandler {
// for all grammars with s
for (int i = fAllTNSs.size() - 1; i >= 0; i--) {
// get its target namespace
- String tns = (String)fAllTNSs.elementAt(i);
+ String tns = fAllTNSs.elementAt(i);
// get all namespaces it imports
Vector ins = (Vector)fImportMap.get(tns);
// get the grammar
@@ -696,12 +703,13 @@ public class XSDHandler {
fAnnotationValidator.setFeature(VALIDATION, true);
fAnnotationValidator.setFeature(XMLSCHEMA_VALIDATION, true);
fAnnotationValidator.setProperty(XMLGRAMMAR_POOL, fGrammarBucketAdapter);
+ /** set security manager and XML Security Property Manager **/
+ fAnnotationValidator.setProperty(SECURITY_MANAGER, (fSecurityManager != null) ? fSecurityManager : new XMLSecurityManager(true));
+ fAnnotationValidator.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
/** Set error handler. **/
- XMLErrorHandler errorHandler = fErrorReporter.getErrorHandler();
- fAnnotationValidator.setProperty(ERROR_HANDLER, (errorHandler != null) ? errorHandler : new DefaultErrorHandler());
+ fAnnotationValidator.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler());
/** Set locale. **/
- Locale locale = fErrorReporter.getLocale();
- fAnnotationValidator.setProperty(LOCALE, locale);
+ fAnnotationValidator.setProperty(LOCALE, fLocale);
}
/**
@@ -880,10 +888,10 @@ public class XSDHandler {
// store the document and its location
// REVISIT: don't expose the DOM tree
- sg.addDocument(null, (String)fDoc2SystemId.get(currSchemaInfo.fSchemaElement));
+ sg.addDocument(null, fDoc2SystemId.get(currSchemaInfo.fSchemaElement));
fDoc2XSDocumentMap.put(schemaRoot, currSchemaInfo);
- Vector dependencies = new Vector();
+ Vector dependencies = new Vector<>();
Element rootNode = schemaRoot;
Element newSchemaRoot = null;
@@ -1334,9 +1342,9 @@ public class XSDHandler {
} // end for
// now we're done with this one!
- DOMUtil.setHidden(currDoc, fHiddenNodes);
+ DOMUtil.setHidden(currDoc, fHiddenNodes);
// now add the schemas this guy depends on
- Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc);
+ Vector currSchemaDepends = fDependencyMap.get(currSchemaDoc);
for (int i = 0; i < currSchemaDepends.size(); i++) {
schemasToProcess.push(currSchemaDepends.elementAt(i));
}
@@ -1466,7 +1474,7 @@ public class XSDHandler {
DOMUtil.setHidden(currDoc, fHiddenNodes);
// now add the schemas this guy depends on
- Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc);
+ Vector currSchemaDepends = fDependencyMap.get(currSchemaDoc);
for (int i = 0; i < currSchemaDepends.size(); i++) {
schemasToProcess.push(currSchemaDepends.elementAt(i));
}
@@ -1915,7 +1923,7 @@ public class XSDHandler {
}
public String schemaDocument2SystemId(XSDocumentInfo schemaDoc) {
- return (String)fDoc2SystemId.get(schemaDoc.fSchemaElement);
+ return fDoc2SystemId.get(schemaDoc.fSchemaElement);
}
// This method determines whether there is a group
@@ -2044,7 +2052,7 @@ public class XSDHandler {
XMLInputSource schemaSource = null;
try {
Map pairs = usePairs ? fLocationPairs : Collections.emptyMap();
- schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver);
+ schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityManager);
}
catch (IOException ex) {
if (mustResolve) {
@@ -2097,7 +2105,7 @@ public class XSDHandler {
XMLInputSource schemaSource = null;
try {
Map pairs = usePairs ? fLocationPairs : Collections.emptyMap();
- schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver);
+ schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityManager);
}
catch (IOException ex) {
if (mustResolve) {
@@ -2152,7 +2160,7 @@ public class XSDHandler {
if (referType != XSDDescription.CONTEXT_PREPARSE){
schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false);
key = new XSDKey(schemaId, referType, schemaNamespace);
- if((schemaElement = (Element)fTraversed.get(key)) != null) {
+ if((schemaElement = fTraversed.get(key)) != null) {
fLastSchemaWasDuplicate = true;
return schemaElement;
}
@@ -2211,7 +2219,7 @@ public class XSDHandler {
if (referType != XSDDescription.CONTEXT_PREPARSE) {
schemaId = XMLEntityManager.expandSystemId(inputSource.getSystemId(), schemaSource.getBaseSystemId(), false);
key = new XSDKey(schemaId, referType, schemaNamespace);
- if ((schemaElement = (Element) fTraversed.get(key)) != null) {
+ if ((schemaElement = fTraversed.get(key)) != null) {
fLastSchemaWasDuplicate = true;
return schemaElement;
}
@@ -2238,9 +2246,8 @@ public class XSDHandler {
namespacePrefixes = true;
// If this is a Xerces SAX parser set the security manager if there is one
if (parser instanceof SAXParser) {
- Object securityManager = fSchemaParser.getProperty(SECURITY_MANAGER);
- if (securityManager != null) {
- parser.setProperty(SECURITY_MANAGER, securityManager);
+ if (fSecurityManager != null) {
+ parser.setProperty(SECURITY_MANAGER, fSecurityManager);
}
}
}
@@ -2347,7 +2354,7 @@ public class XSDHandler {
}
if (isDocument) {
key = new XSDKey(schemaId, referType, schemaNamespace);
- if ((schemaElement = (Element) fTraversed.get(key)) != null) {
+ if ((schemaElement = fTraversed.get(key)) != null) {
fLastSchemaWasDuplicate = true;
return schemaElement;
}
@@ -2402,7 +2409,7 @@ public class XSDHandler {
}
if (isDocument) {
key = new XSDKey(schemaId, referType, schemaNamespace);
- if ((schemaElement = (Element) fTraversed.get(key)) != null) {
+ if ((schemaElement = fTraversed.get(key)) != null) {
fLastSchemaWasDuplicate = true;
return schemaElement;
}
@@ -3502,40 +3509,21 @@ public class XSDHandler {
// set symbol table
fSymbolTable = (SymbolTable) componentManager.getProperty(SYMBOL_TABLE);
- fSecureProcessing = null;
- if( componentManager!=null ) {
- fSecureProcessing = (XMLSecurityManager) componentManager.getProperty(SECURE_PROCESSING, null);
- }
+ // set security manager
+ fSecurityManager = (XMLSecurityManager) componentManager.getProperty(SECURITY_MANAGER, null);
+
+ //set entity manager
+ fEntityManager = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER);
//set entity resolver
- fEntityResolver = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER);
XMLEntityResolver er = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER);
if (er != null)
fSchemaParser.setEntityResolver(er);
// set error reporter
- fErrorReporter =
- (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER);
- try {
- XMLErrorHandler currErrorHandler = fErrorReporter.getErrorHandler();
- // Setting a parser property can be much more expensive
- // than checking its value. Don't set the ERROR_HANDLER
- // or LOCALE properties unless they've actually changed.
- if (currErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) {
- fSchemaParser.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler());
- if (fAnnotationValidator != null) {
- fAnnotationValidator.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler());
- }
- }
- Locale currentLocale = fErrorReporter.getLocale();
- if (currentLocale != fSchemaParser.getProperty(LOCALE)) {
- fSchemaParser.setProperty(LOCALE, currentLocale);
- if (fAnnotationValidator != null) {
- fAnnotationValidator.setProperty(LOCALE, currentLocale);
- }
- }
- }
- catch (XMLConfigurationException e) {}
+ fErrorReporter = (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER);
+ fErrorHandler = fErrorReporter.getErrorHandler();
+ fLocale = fErrorReporter.getLocale();
fValidateAnnotations = componentManager.getFeature(VALIDATE_ANNOTATIONS, false);
fHonourAllSchemaLocations = componentManager.getFeature(HONOUR_ALL_SCHEMALOCATIONS, false);
@@ -3543,56 +3531,66 @@ public class XSDHandler {
fTolerateDuplicates = componentManager.getFeature(TOLERATE_DUPLICATES, false);
try {
- fSchemaParser.setFeature(
- CONTINUE_AFTER_FATAL_ERROR,
- fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR));
- } catch (XMLConfigurationException e) {
+ // Setting a parser property can be much more expensive
+ // than checking its value. Don't set the ERROR_HANDLER
+ // or LOCALE properties unless they've actually changed.
+ if (fErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) {
+ fSchemaParser.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler());
+ if (fAnnotationValidator != null) {
+ fAnnotationValidator.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler());
+ }
+ }
+ if (fLocale != fSchemaParser.getProperty(LOCALE)) {
+ fSchemaParser.setProperty(LOCALE, fLocale);
+ if (fAnnotationValidator != null) {
+ fAnnotationValidator.setProperty(LOCALE, fLocale);
+ }
+ }
}
+ catch (XMLConfigurationException e) {}
+
+ try {
+ fSchemaParser.setFeature(CONTINUE_AFTER_FATAL_ERROR, fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR));
+ } catch (XMLConfigurationException e) {}
try {
if (componentManager.getFeature(ALLOW_JAVA_ENCODINGS, false)) {
fSchemaParser.setFeature(ALLOW_JAVA_ENCODINGS, true);
}
- } catch (XMLConfigurationException e) {
- }
+ } catch (XMLConfigurationException e) {}
+
try {
if (componentManager.getFeature(STANDARD_URI_CONFORMANT_FEATURE, false)) {
fSchemaParser.setFeature(STANDARD_URI_CONFORMANT_FEATURE, true);
}
- } catch (XMLConfigurationException e) {
- }
+ } catch (XMLConfigurationException e) {}
try {
- fGrammarPool =
- (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL);
+ fGrammarPool = (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL);
} catch (XMLConfigurationException e) {
fGrammarPool = null;
}
+
// security features
try {
if (componentManager.getFeature(DISALLOW_DOCTYPE, false)) {
fSchemaParser.setFeature(DISALLOW_DOCTYPE, true);
}
- } catch (XMLConfigurationException e) {
- }
+ } catch (XMLConfigurationException e) {}
+
try {
- Object security = componentManager.getProperty(SECURITY_MANAGER, null);
- if (security != null){
- fSchemaParser.setProperty(SECURITY_MANAGER, security);
+ if (fSecurityManager != null) {
+ fSchemaParser.setProperty(SECURITY_MANAGER, fSecurityManager);
}
- } catch (XMLConfigurationException e) {
- }
+ } catch (XMLConfigurationException e) {}
+
+ fSecurityPropertyMgr = (XMLSecurityPropertyManager) componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER);
- XMLSecurityPropertyManager securityPropertyMgr = (XMLSecurityPropertyManager)
- componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER);
//Passing on the setting to the parser
- fSchemaParser.setProperty(XML_SECURITY_PROPERTY_MANAGER, securityPropertyMgr);
+ fSchemaParser.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
- fAccessExternalDTD = securityPropertyMgr.getValue(
- XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD);
-
- fAccessExternalSchema = securityPropertyMgr.getValue(
- XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA);
+ fAccessExternalDTD = fSecurityPropertyMgr.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD);
+ fAccessExternalSchema = fSecurityPropertyMgr.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA);
} // reset(XMLComponentManager)
@@ -4051,7 +4049,7 @@ public class XSDHandler {
so long as there's some include/import/redefine path amongst them.
If they rver reverse this decision the code's right here though... - neilg
// now look in fDependencyMap to see if this is reachable
- if(((Vector)fDependencyMap.get(currSchema)).contains(declDocInfo)) {
+ if((fDependencyMap.get(currSchema)).contains(declDocInfo)) {
return declDocInfo;
}
// obviously the requesting doc didn't include, redefine or
@@ -4072,9 +4070,9 @@ public class XSDHandler {
if (DOMUtil.isHidden(startSchema.fSchemaElement, fHiddenNodes)) {
// make it visible
DOMUtil.setVisible(startSchema.fSchemaElement, fHiddenNodes);
- Vector dependingSchemas = (Vector)fDependencyMap.get(startSchema);
+ Vector dependingSchemas = fDependencyMap.get(startSchema);
for (int i = 0; i < dependingSchemas.size(); i++) {
- setSchemasVisible((XSDocumentInfo)dependingSchemas.elementAt(i));
+ setSchemasVisible(dependingSchemas.elementAt(i));
}
}
// if it's visible already than so must be its children
@@ -4107,7 +4105,7 @@ public class XSDHandler {
ElementImpl ele = (ElementImpl)e;
// get system id from document object
Document doc = ele.getOwnerDocument();
- String sid = (String)fDoc2SystemId.get(DOMUtil.getRoot(doc));
+ String sid = fDoc2SystemId.get(DOMUtil.getRoot(doc));
// line/column numbers are stored in the element node
int line = ele.getLineNumber();
int column = ele.getColumnNumber();
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java
index 459067067a1..3c4dd4f810e 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -52,7 +52,6 @@ import com.sun.org.apache.xerces.internal.util.FeatureState;
import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;
import com.sun.org.apache.xerces.internal.util.PropertyState;
import com.sun.org.apache.xerces.internal.util.SymbolTable;
-import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
@@ -166,59 +165,57 @@ public class XML11Configuration extends ParserConfigurationSettings
protected static final String USE_GRAMMAR_POOL_ONLY =
Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE;
- // feature identifiers
+ // feature identifiers
- /** Feature identifier: validation. */
- protected static final String VALIDATION =
- Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
+ /** Feature identifier: validation. */
+ protected static final String VALIDATION =
+ Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
- /** Feature identifier: namespaces. */
- protected static final String NAMESPACES =
- Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
+ /** Feature identifier: namespaces. */
+ protected static final String NAMESPACES =
+ Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
- /** Feature identifier: external general entities. */
- protected static final String EXTERNAL_GENERAL_ENTITIES =
- Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE;
+ /** Feature identifier: external general entities. */
+ protected static final String EXTERNAL_GENERAL_ENTITIES =
+ Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE;
- /** Feature identifier: external parameter entities. */
- protected static final String EXTERNAL_PARAMETER_ENTITIES =
- Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE;
+ /** Feature identifier: external parameter entities. */
+ protected static final String EXTERNAL_PARAMETER_ENTITIES =
+ Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE;
- /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */
- protected static final String IGNORE_XSI_TYPE =
- Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE;
+ /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */
+ protected static final String IGNORE_XSI_TYPE =
+ Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE;
- /** Feature identifier: whether to ignore ID/IDREF errors */
- protected static final String ID_IDREF_CHECKING =
- Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE;
+ /** Feature identifier: whether to ignore ID/IDREF errors */
+ protected static final String ID_IDREF_CHECKING =
+ Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE;
- /** Feature identifier: whether to ignore unparsed entity errors */
- protected static final String UNPARSED_ENTITY_CHECKING =
- Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE;
+ /** Feature identifier: whether to ignore unparsed entity errors */
+ protected static final String UNPARSED_ENTITY_CHECKING =
+ Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE;
- /** Feature identifier: whether to ignore identity constraint errors */
- protected static final String IDENTITY_CONSTRAINT_CHECKING =
- Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE;
+ /** Feature identifier: whether to ignore identity constraint errors */
+ protected static final String IDENTITY_CONSTRAINT_CHECKING =
+ Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE;
// property identifiers
+ /** Property identifier: xml string. */
+ protected static final String XML_STRING =
+ Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY;
- /** Property identifier: xml string. */
- protected static final String XML_STRING =
- Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY;
+ /** Property identifier: symbol table. */
+ protected static final String SYMBOL_TABLE =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
- /** Property identifier: symbol table. */
- protected static final String SYMBOL_TABLE =
- Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
-
- /** Property identifier: error handler. */
- protected static final String ERROR_HANDLER =
- Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
-
- /** Property identifier: entity resolver. */
- protected static final String ENTITY_RESOLVER =
- Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
+ /** Property identifier: error handler. */
+ protected static final String ERROR_HANDLER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
+ /** Property identifier: entity resolver. */
+ protected static final String ENTITY_RESOLVER =
+ Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
/** Property identifier: XML Schema validator. */
protected static final String SCHEMA_VALIDATOR =
@@ -232,8 +229,6 @@ public class XML11Configuration extends ParserConfigurationSettings
protected static final String SCHEMA_NONS_LOCATION =
Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION;
- // property identifiers
-
/** Property identifier: error reporter. */
protected static final String ERROR_REPORTER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
@@ -313,33 +308,33 @@ public class XML11Configuration extends ParserConfigurationSettings
// Data
//
- protected SymbolTable fSymbolTable;
+ protected SymbolTable fSymbolTable;
protected XMLInputSource fInputSource;
protected ValidationManager fValidationManager;
- protected XMLVersionDetector fVersionDetector;
+ protected XMLVersionDetector fVersionDetector;
protected XMLLocator fLocator;
- protected Locale fLocale;
+ protected Locale fLocale;
- /** XML 1.0 Components. */
- protected ArrayList fComponents;
+ /** XML 1.0 Components. */
+ protected ArrayList fComponents;
- /** XML 1.1. Components. */
- protected ArrayList fXML11Components = null;
+ /** XML 1.1. Components. */
+ protected ArrayList fXML11Components = null;
- /** Common components: XMLEntityManager, XMLErrorReporter, XMLSchemaValidator */
- protected ArrayList fCommonComponents = null;
+ /** Common components: XMLEntityManager, XMLErrorReporter, XMLSchemaValidator */
+ protected ArrayList fCommonComponents = null;
- /** The document handler. */
- protected XMLDocumentHandler fDocumentHandler;
+ /** The document handler. */
+ protected XMLDocumentHandler fDocumentHandler;
- /** The DTD handler. */
- protected XMLDTDHandler fDTDHandler;
+ /** The DTD handler. */
+ protected XMLDTDHandler fDTDHandler;
- /** The DTD content model handler. */
- protected XMLDTDContentModelHandler fDTDContentModelHandler;
+ /** The DTD content model handler. */
+ protected XMLDTDContentModelHandler fDTDContentModelHandler;
- /** Last component in the document pipeline */
- protected XMLDocumentSource fLastComponent;
+ /** Last component in the document pipeline */
+ protected XMLDocumentSource fLastComponent;
/**
* True if a parse is in progress. This state is needed because
@@ -477,15 +472,15 @@ public class XML11Configuration extends ParserConfigurationSettings
// create a vector to hold all the components in use
// XML 1.0 specialized components
- fComponents = new ArrayList();
+ fComponents = new ArrayList<>();
// XML 1.1 specialized components
- fXML11Components = new ArrayList();
+ fXML11Components = new ArrayList<>();
// Common components for XML 1.1. and XML 1.0
- fCommonComponents = new ArrayList();
+ fCommonComponents = new ArrayList<>();
// create table for features and properties
- fFeatures = new HashMap();
- fProperties = new HashMap();
+ fFeatures = new HashMap<>();
+ fProperties = new HashMap<>();
// add default recognized features
final String[] recognizedFeatures =
@@ -580,35 +575,35 @@ public class XML11Configuration extends ParserConfigurationSettings
}
fEntityManager = new XMLEntityManager();
- fProperties.put(ENTITY_MANAGER, fEntityManager);
+ fProperties.put(ENTITY_MANAGER, fEntityManager);
addCommonComponent(fEntityManager);
fErrorReporter = new XMLErrorReporter();
fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
- fProperties.put(ERROR_REPORTER, fErrorReporter);
+ fProperties.put(ERROR_REPORTER, fErrorReporter);
addCommonComponent(fErrorReporter);
fNamespaceScanner = new XMLNSDocumentScannerImpl();
- fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner);
+ fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner);
addComponent((XMLComponent) fNamespaceScanner);
fDTDScanner = new XMLDTDScannerImpl();
- fProperties.put(DTD_SCANNER, fDTDScanner);
+ fProperties.put(DTD_SCANNER, fDTDScanner);
addComponent((XMLComponent) fDTDScanner);
fDTDProcessor = new XMLDTDProcessor();
- fProperties.put(DTD_PROCESSOR, fDTDProcessor);
+ fProperties.put(DTD_PROCESSOR, fDTDProcessor);
addComponent((XMLComponent) fDTDProcessor);
fDTDValidator = new XMLNSDTDValidator();
- fProperties.put(DTD_VALIDATOR, fDTDValidator);
+ fProperties.put(DTD_VALIDATOR, fDTDValidator);
addComponent(fDTDValidator);
fDatatypeValidatorFactory = DTDDVFactory.getInstance();
- fProperties.put(DATATYPE_VALIDATOR_FACTORY, fDatatypeValidatorFactory);
+ fProperties.put(DATATYPE_VALIDATOR_FACTORY, fDatatypeValidatorFactory);
fValidationManager = new ValidationManager();
- fProperties.put(VALIDATION_MANAGER, fValidationManager);
+ fProperties.put(VALIDATION_MANAGER, fValidationManager);
fVersionDetector = new XMLVersionDetector();
@@ -935,20 +930,20 @@ public class XML11Configuration extends ParserConfigurationSettings
// forward to every XML 1.0 component
int count = fComponents.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fComponents.get(i);
+ XMLComponent c = fComponents.get(i);
c.setFeature(featureId, state);
}
// forward it to common components
count = fCommonComponents.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fCommonComponents.get(i);
+ XMLComponent c = fCommonComponents.get(i);
c.setFeature(featureId, state);
}
// forward to every XML 1.1 component
count = fXML11Components.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fXML11Components.get(i);
+ XMLComponent c = fXML11Components.get(i);
try{
c.setFeature(featureId, state);
}
@@ -996,19 +991,19 @@ public class XML11Configuration extends ParserConfigurationSettings
// forward to every XML 1.0 component
int count = fComponents.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fComponents.get(i);
+ XMLComponent c = fComponents.get(i);
c.setProperty(propertyId, value);
}
// forward it to every common Component
count = fCommonComponents.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fCommonComponents.get(i);
+ XMLComponent c = fCommonComponents.get(i);
c.setProperty(propertyId, value);
}
// forward it to every XML 1.1 component
count = fXML11Components.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fXML11Components.get(i);
+ XMLComponent c = fXML11Components.get(i);
try{
c.setProperty(propertyId, value);
}
@@ -1034,7 +1029,7 @@ public class XML11Configuration extends ParserConfigurationSettings
protected void reset() throws XNIException {
int count = fComponents.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fComponents.get(i);
+ XMLComponent c = fComponents.get(i);
c.reset(this);
}
@@ -1047,7 +1042,7 @@ public class XML11Configuration extends ParserConfigurationSettings
// reset common components
int count = fCommonComponents.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fCommonComponents.get(i);
+ XMLComponent c = fCommonComponents.get(i);
c.reset(this);
}
@@ -1061,7 +1056,7 @@ public class XML11Configuration extends ParserConfigurationSettings
// reset every component
int count = fXML11Components.size();
for (int i = 0; i < count; i++) {
- XMLComponent c = (XMLComponent) fXML11Components.get(i);
+ XMLComponent c = fXML11Components.get(i);
c.reset(this);
}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java
index f4e29a3a856..bdd0750d0fa 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java
@@ -51,7 +51,7 @@ public final class HTTPInputSource extends XMLInputSource {
protected boolean fFollowRedirects = true;
/** HTTP request properties. **/
- protected Map fHTTPRequestProperties = new HashMap();
+ protected Map fHTTPRequestProperties = new HashMap<>();
//
// Constructors
@@ -159,7 +159,7 @@ public final class HTTPInputSource extends XMLInputSource {
* been set
*/
public String getHTTPRequestProperty(String key) {
- return (String) fHTTPRequestProperties.get(key);
+ return fHTTPRequestProperties.get(key);
} // getHTTPRequestProperty(String):String
/**
@@ -172,7 +172,7 @@ public final class HTTPInputSource extends XMLInputSource {
* @return an iterator for the request properties this
* input source contains
*/
- public Iterator getHTTPRequestProperties() {
+ public Iterator> getHTTPRequestProperties() {
return fHTTPRequestProperties.entrySet().iterator();
} // getHTTPRequestProperties():Iterator
diff --git a/jaxp/test/javax/xml/jaxp/unittest/validation/Bug8149915.xsd b/jaxp/test/javax/xml/jaxp/unittest/validation/Bug8149915.xsd
new file mode 100644
index 00000000000..872033f5d1a
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/validation/Bug8149915.xsd
@@ -0,0 +1,7 @@
+
+
+
+ Testapp for XSD annotation issue
+ This is an XSD annotation, just for the sake of it.
+
+
diff --git a/jaxp/test/javax/xml/jaxp/unittest/validation/SchemaTest.java b/jaxp/test/javax/xml/jaxp/unittest/validation/SchemaTest.java
new file mode 100644
index 00000000000..f8a5e62ac55
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/validation/SchemaTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016, 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 validation;
+
+import java.io.File;
+
+import javax.xml.XMLConstants;
+import javax.xml.validation.SchemaFactory;
+
+import org.testng.annotations.Test;
+
+/*
+ * @summary Test Schema creation
+ * @bug 8149915
+ */
+public class SchemaTest {
+
+ /*
+ * @bug 8149915
+ * Verifies that the annotation validator is initialized with the security manager for schema
+ * creation with http://apache.org/xml/features/validate-annotations=true.
+ */
+ @Test
+ public void testValidation() throws Exception {
+ SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ factory.setFeature("http://apache.org/xml/features/validate-annotations", true);
+ factory.newSchema(new File(getClass().getResource("Bug8149915.xsd").getFile()));
+ }
+}
From 0698afcea9e69524f7169f56686ab68662042d1b Mon Sep 17 00:00:00 2001
From: Vicente Romero
Date: Mon, 22 Feb 2016 16:17:25 -0800
Subject: [PATCH 069/311] 8149600: javac, remove unused options, step 2
Reviewed-by: jjg, mcimadamore
---
.../com/sun/tools/javac/comp/Attr.java | 14 +-
.../com/sun/tools/javac/comp/Check.java | 14 +-
.../com/sun/tools/javac/jvm/ClassWriter.java | 44 +-----
.../classes/com/sun/tools/javac/jvm/Gen.java | 140 +-----------------
.../sun/tools/javac/main/JavaCompiler.java | 105 ++++---------
.../com/sun/tools/javac/main/Option.java | 2 +-
.../tools/javac/resources/compiler.properties | 14 --
.../tools/javac/resources/javac.properties | 8 -
.../com/sun/tools/javah/JavahTask.java | 10 +-
.../test/tools/javac/6257443/T6257443.java | 10 +-
.../test/tools/javac/6521805/T6521805a.java | 22 ---
.../test/tools/javac/6521805/T6521805a_1.out | 2 -
.../test/tools/javac/6521805/T6521805a_2.out | 2 -
.../api/taskListeners/EventsBalancedTest.java | 4 +-
.../tools/javac/diags/CheckResourceKeys.java | 9 +-
.../tools/javac/diags/examples.not-yet.txt | 3 -
.../examples/WarnSyntheticNameConflict.java | 34 -----
17 files changed, 53 insertions(+), 384 deletions(-)
delete mode 100644 langtools/test/tools/javac/6521805/T6521805a.java
delete mode 100644 langtools/test/tools/javac/6521805/T6521805a_1.out
delete mode 100644 langtools/test/tools/javac/6521805/T6521805a_2.out
delete mode 100644 langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
index f62d866bacb..efa57d8b854 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -155,8 +155,6 @@ public class Attr extends JCTree.Visitor {
allowDefaultMethods = source.allowDefaultMethods();
allowStaticInterfaceMethods = source.allowStaticInterfaceMethods();
sourceName = source.name;
- relax = (options.isSet("-retrofit") ||
- options.isSet("-relax"));
useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning");
statInfo = new ResultInfo(KindSelector.NIL, Type.noType);
@@ -168,10 +166,6 @@ public class Attr extends JCTree.Visitor {
recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext);
}
- /** Switch: relax some constraints for retrofit mode.
- */
- boolean relax;
-
/** Switch: support target-typing inference
*/
boolean allowPoly;
@@ -1025,8 +1019,7 @@ public class Attr extends JCTree.Visitor {
log.error(tree.pos(),
"default.allowed.in.intf.annotation.member");
}
- if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0 &&
- !relax)
+ if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0)
log.error(tree.pos(), "missing.meth.body.or.decl.abstract");
} else if ((tree.sym.flags() & (ABSTRACT|DEFAULT|PRIVATE)) == ABSTRACT) {
if ((owner.flags() & INTERFACE) != 0) {
@@ -4384,8 +4377,7 @@ public class Attr extends JCTree.Visitor {
// If this is a non-abstract class, check that it has no abstract
// methods or unimplemented methods of an implemented interface.
if ((c.flags() & (ABSTRACT | INTERFACE)) == 0) {
- if (!relax)
- chk.checkAllDefined(tree.pos(), c);
+ chk.checkAllDefined(tree.pos(), c);
}
if ((c.flags() & ANNOTATION) != 0) {
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
index a130f220926..357e44b1913 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
@@ -81,8 +81,6 @@ public class Check {
private final Types types;
private final TypeAnnotations typeAnnotations;
private final JCDiagnostic.Factory diags;
- private boolean warnOnSyntheticConflicts;
- private boolean suppressAbortOnBadClassFile;
private final JavaFileManager fileManager;
private final Source source;
private final Profile profile;
@@ -130,8 +128,6 @@ public class Check {
allowStrictMethodClashCheck = source.allowStrictMethodClashCheck();
allowPrivateSafeVarargs = source.allowPrivateSafeVarargs();
allowDiamondWithAnonymousClassCreation = source.allowDiamondWithAnonymousClassCreation();
- warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
- suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
warnOnAccessToSensitiveMembers = options.isSet("warnOnAccessToSensitiveMembers");
Target target = Target.instance(context);
@@ -269,8 +265,7 @@ public class Check {
*/
public Type completionError(DiagnosticPosition pos, CompletionFailure ex) {
log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, pos, "cant.access", ex.sym, ex.getDetailValue());
- if (ex instanceof ClassFinder.BadClassFile
- && !suppressAbortOnBadClassFile) throw new Abort();
+ if (ex instanceof ClassFinder.BadClassFile) throw new Abort();
else return syms.errType;
}
@@ -2632,12 +2627,7 @@ public class Check {
*/
private void syntheticError(DiagnosticPosition pos, Symbol sym) {
if (!sym.type.isErroneous()) {
- if (warnOnSyntheticConflicts) {
- log.warning(pos, "synthetic.name.conflict", sym, sym.location());
- }
- else {
- log.error(pos, "synthetic.name.conflict", sym, sym.location());
- }
+ log.error(pos, "synthetic.name.conflict", sym, sym.location());
}
}
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
index 1b1f8a15457..aa161b5ec76 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -72,18 +72,6 @@ public class ClassWriter extends ClassFile {
*/
private boolean verbose;
- /** Switch: scramble private field names.
- */
- private boolean scramble;
-
- /** Switch: scramble all field names.
- */
- private boolean scrambleAll;
-
- /** Switch: retrofit mode.
- */
- private boolean retrofit;
-
/** Switch: emit source file attribute.
*/
private boolean emitSourceFile;
@@ -184,9 +172,6 @@ public class ClassWriter extends ClassFile {
signatureGen = new CWSignatureGenerator(types);
verbose = options.isSet(VERBOSE);
- scramble = options.isSet("-scramble");
- scrambleAll = options.isSet("-scrambleAll");
- retrofit = options.isSet("-retrofit");
genCrt = options.isSet(XJCOV);
debugstackmap = options.isSet("debugstackmap");
@@ -491,26 +476,11 @@ public class ClassWriter extends ClassFile {
putChar(poolbuf, poolCountIdx, pool.pp);
}
- /** Given a field, return its name.
- */
- Name fieldName(Symbol sym) {
- if (scramble && (sym.flags() & PRIVATE) != 0 ||
- scrambleAll && (sym.flags() & (PROTECTED | PUBLIC)) == 0)
- return names.fromString("_$" + sym.name.getIndex());
- else
- return sym.name;
- }
-
/** Given a symbol, return its name-and-type.
*/
NameAndType nameType(Symbol sym) {
- return new NameAndType(fieldName(sym),
- retrofit
- ? sym.erasure(types)
- : sym.externalType(types), types);
- // if we retrofit, then the NameAndType has been read in as is
- // and no change is necessary. If we compile normally, the
- // NameAndType is generated from a symbol reference, and the
+ return new NameAndType(sym.name, sym.externalType(types), types);
+ // the NameAndType is generated from a symbol reference, and the
// adjustment of adding an additional this$n parameter needs to be made.
}
@@ -1055,10 +1025,10 @@ public class ClassWriter extends ClassFile {
databuf.appendChar(flags);
if (dumpFieldModifiers) {
PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
- pw.println("FIELD " + fieldName(v));
+ pw.println("FIELD " + v.name);
pw.println("---" + flagNames(v.flags()));
}
- databuf.appendChar(pool.put(fieldName(v)));
+ databuf.appendChar(pool.put(v.name));
databuf.appendChar(pool.put(typeSig(v.erasure(types))));
int acountIdx = beginAttrs();
int acount = 0;
@@ -1079,10 +1049,10 @@ public class ClassWriter extends ClassFile {
databuf.appendChar(flags);
if (dumpMethodModifiers) {
PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
- pw.println("METHOD " + fieldName(m));
+ pw.println("METHOD " + m.name);
pw.println("---" + flagNames(m.flags()));
}
- databuf.appendChar(pool.put(fieldName(m)));
+ databuf.appendChar(pool.put(m.name));
databuf.appendChar(pool.put(typeSig(m.externalType(types))));
int acountIdx = beginAttrs();
int acount = 0;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
index 83ed8adbef5..6280b8d5cf4 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -120,25 +120,11 @@ public class Gen extends JCTree.Visitor {
: options.isSet(G_CUSTOM, "vars");
genCrt = options.isSet(XJCOV);
debugCode = options.isSet("debugcode");
- allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
allowBetterNullChecks = target.hasObjects();
pool = new Pool(types);
// ignore cldc because we cannot have both stackmap formats
this.stackMap = StackMapFormat.JSR202;
-
- // by default, avoid jsr's for simple finalizers
- int setjsrlimit = 50;
- String jsrlimitString = options.get("jsrlimit");
- if (jsrlimitString != null) {
- try {
- setjsrlimit = Integer.parseInt(jsrlimitString);
- } catch (NumberFormatException ex) {
- // ignore ill-formed numbers for jsrlimit
- }
- }
- this.jsrlimit = setjsrlimit;
- this.useJsrLocally = false; // reset in visitTry
annotate = Annotate.instance(context);
}
@@ -148,19 +134,8 @@ public class Gen extends JCTree.Visitor {
private final boolean varDebugInfo;
private final boolean genCrt;
private final boolean debugCode;
- private final boolean allowInvokedynamic;
private final boolean allowBetterNullChecks;
- /** Default limit of (approximate) size of finalizer to inline.
- * Zero means always use jsr. 100 or greater means never use
- * jsr.
- */
- private final int jsrlimit;
-
- /** True if jsr is used.
- */
- private boolean useJsrLocally;
-
/** Code buffer, set by genMethod.
*/
private Code code;
@@ -1339,31 +1314,11 @@ public class Gen extends JCTree.Visitor {
// in a new environment which calls the finally block if there is one.
final Env tryEnv = env.dup(tree, new GenContext());
final Env oldEnv = env;
- if (!useJsrLocally) {
- useJsrLocally =
- (stackMap == StackMapFormat.NONE) &&
- (jsrlimit <= 0 ||
- jsrlimit < 100 &&
- estimateCodeComplexity(tree.finalizer)>jsrlimit);
- }
tryEnv.info.finalize = new GenFinalizer() {
void gen() {
- if (useJsrLocally) {
- if (tree.finalizer != null) {
- Code.State jsrState = code.state.dup();
- jsrState.push(Code.jsrReturnValue);
- tryEnv.info.cont =
- new Chain(code.emitJump(jsr),
- tryEnv.info.cont,
- jsrState);
- }
- Assert.check(tryEnv.info.gaps.length() % 2 == 0);
- tryEnv.info.gaps.append(code.curCP());
- } else {
- Assert.check(tryEnv.info.gaps.length() % 2 == 0);
- tryEnv.info.gaps.append(code.curCP());
- genLast();
- }
+ Assert.check(tryEnv.info.gaps.length() % 2 == 0);
+ tryEnv.info.gaps.append(code.curCP());
+ genLast();
}
void genLast() {
if (tree.finalizer != null)
@@ -1568,93 +1523,6 @@ public class Gen extends JCTree.Visitor {
}
}
- /** Very roughly estimate the number of instructions needed for
- * the given tree.
- */
- int estimateCodeComplexity(JCTree tree) {
- if (tree == null) return 0;
- class ComplexityScanner extends TreeScanner {
- int complexity = 0;
- public void scan(JCTree tree) {
- if (complexity > jsrlimit) return;
- super.scan(tree);
- }
- public void visitClassDef(JCClassDecl tree) {}
- public void visitDoLoop(JCDoWhileLoop tree)
- { super.visitDoLoop(tree); complexity++; }
- public void visitWhileLoop(JCWhileLoop tree)
- { super.visitWhileLoop(tree); complexity++; }
- public void visitForLoop(JCForLoop tree)
- { super.visitForLoop(tree); complexity++; }
- public void visitSwitch(JCSwitch tree)
- { super.visitSwitch(tree); complexity+=5; }
- public void visitCase(JCCase tree)
- { super.visitCase(tree); complexity++; }
- public void visitSynchronized(JCSynchronized tree)
- { super.visitSynchronized(tree); complexity+=6; }
- public void visitTry(JCTry tree)
- { super.visitTry(tree);
- if (tree.finalizer != null) complexity+=6; }
- public void visitCatch(JCCatch tree)
- { super.visitCatch(tree); complexity+=2; }
- public void visitConditional(JCConditional tree)
- { super.visitConditional(tree); complexity+=2; }
- public void visitIf(JCIf tree)
- { super.visitIf(tree); complexity+=2; }
- // note: for break, continue, and return we don't take unwind() into account.
- public void visitBreak(JCBreak tree)
- { super.visitBreak(tree); complexity+=1; }
- public void visitContinue(JCContinue tree)
- { super.visitContinue(tree); complexity+=1; }
- public void visitReturn(JCReturn tree)
- { super.visitReturn(tree); complexity+=1; }
- public void visitThrow(JCThrow tree)
- { super.visitThrow(tree); complexity+=1; }
- public void visitAssert(JCAssert tree)
- { super.visitAssert(tree); complexity+=5; }
- public void visitApply(JCMethodInvocation tree)
- { super.visitApply(tree); complexity+=2; }
- public void visitNewClass(JCNewClass tree)
- { scan(tree.encl); scan(tree.args); complexity+=2; }
- public void visitNewArray(JCNewArray tree)
- { super.visitNewArray(tree); complexity+=5; }
- public void visitAssign(JCAssign tree)
- { super.visitAssign(tree); complexity+=1; }
- public void visitAssignop(JCAssignOp tree)
- { super.visitAssignop(tree); complexity+=2; }
- public void visitUnary(JCUnary tree)
- { complexity+=1;
- if (tree.type.constValue() == null) super.visitUnary(tree); }
- public void visitBinary(JCBinary tree)
- { complexity+=1;
- if (tree.type.constValue() == null) super.visitBinary(tree); }
- public void visitTypeTest(JCInstanceOf tree)
- { super.visitTypeTest(tree); complexity+=1; }
- public void visitIndexed(JCArrayAccess tree)
- { super.visitIndexed(tree); complexity+=1; }
- public void visitSelect(JCFieldAccess tree)
- { super.visitSelect(tree);
- if (tree.sym.kind == VAR) complexity+=1; }
- public void visitIdent(JCIdent tree) {
- if (tree.sym.kind == VAR) {
- complexity+=1;
- if (tree.type.constValue() == null &&
- tree.sym.owner.kind == TYP)
- complexity+=1;
- }
- }
- public void visitLiteral(JCLiteral tree)
- { complexity+=1; }
- public void visitTree(JCTree tree) {}
- public void visitWildcard(JCWildcard tree) {
- throw new AssertionError(this.getClass().getName());
- }
- }
- ComplexityScanner scanner = new ComplexityScanner();
- tree.accept(scanner);
- return scanner.complexity;
- }
-
public void visitIf(JCIf tree) {
int limit = code.nextreg;
Chain thenExit = null;
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
index 40ca702ba82..4f72befa543 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
@@ -389,9 +389,6 @@ public class JavaCompiler {
verbose = options.isSet(VERBOSE);
sourceOutput = options.isSet(PRINTSOURCE); // used to be -s
- stubOutput = options.isSet("-stubs");
- relax = options.isSet("-relax");
- printFlat = options.isSet("-printflat");
encoding = options.get(ENCODING);
lineDebugInfo = options.isUnset(G_CUSTOM) ||
options.isSet(G_CUSTOM, "lines");
@@ -447,18 +444,6 @@ public class JavaCompiler {
*/
public boolean sourceOutput;
- /** Emit stub source files rather than class files.
- */
- public boolean stubOutput;
-
- /** Switch: relax some constraints for producing the jsr14 prototype.
- */
- boolean relax;
-
- /** Debug switch: Emit Java sources after inner class flattening.
- */
- public boolean printFlat;
-
/** The encoding to be used for source input.
*/
public String encoding;
@@ -611,7 +596,7 @@ public class JavaCompiler {
// where
public boolean keepComments = false;
protected boolean keepComments() {
- return keepComments || sourceOutput || stubOutput;
+ return keepComments || sourceOutput;
}
@@ -676,30 +661,6 @@ public class JavaCompiler {
}
}
- /** Emit plain Java source for a class.
- * @param env The attribution environment of the outermost class
- * containing this class.
- * @param cdef The class definition to be printed.
- */
- JavaFileObject printSource(Env env, JCClassDecl cdef) throws IOException {
- JavaFileObject outFile
- = fileManager.getJavaFileForOutput(CLASS_OUTPUT,
- cdef.sym.flatname.toString(),
- JavaFileObject.Kind.SOURCE,
- null);
- if (inputFiles.contains(outFile)) {
- log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile);
- return null;
- } else {
- try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) {
- new Pretty(out, true).printUnit(env.toplevel, cdef);
- if (verbose)
- log.printVerbose("wrote.file", outFile);
- }
- return outFile;
- }
- }
-
/** Generate code and emit a class file for a given class
* @param env The attribution environment of the outermost class
* containing this class.
@@ -720,6 +681,30 @@ public class JavaCompiler {
return null;
}
+ /** Emit plain Java source for a class.
+ * @param env The attribution environment of the outermost class
+ * containing this class.
+ * @param cdef The class definition to be printed.
+ */
+ JavaFileObject printSource(Env env, JCClassDecl cdef) throws IOException {
+ JavaFileObject outFile
+ = fileManager.getJavaFileForOutput(CLASS_OUTPUT,
+ cdef.sym.flatname.toString(),
+ JavaFileObject.Kind.SOURCE,
+ null);
+ if (inputFiles.contains(outFile)) {
+ log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile);
+ return null;
+ } else {
+ try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) {
+ new Pretty(out, true).printUnit(env.toplevel, cdef);
+ if (verbose)
+ log.printVerbose("wrote.file", outFile);
+ }
+ return outFile;
+ }
+ }
+
/** Compile a source file that has been accessed by the class finder.
* @param c The class the source file of which needs to be compiled.
*/
@@ -897,12 +882,6 @@ public class JavaCompiler {
throw new AssertionError("attempt to reuse JavaCompiler");
}
- /**
- * Set needRootClasses to true, in JavaCompiler subclass constructor
- * that want to collect public apis of classes supplied on the command line.
- */
- protected boolean needRootClasses = false;
-
/**
* The list of classes explicitly supplied on the command line for compilation.
* Not always populated.
@@ -966,7 +945,7 @@ public class JavaCompiler {
// If generating source, or if tracking public apis,
// then remember the classes declared in
// the original compilation units listed on the command line.
- if (needRootClasses || sourceOutput || stubOutput) {
+ if (sourceOutput) {
ListBuffer cdefs = new ListBuffer<>();
for (JCCompilationUnit unit : roots) {
for (List defs = unit.defs;
@@ -1275,11 +1254,6 @@ public class JavaCompiler {
if (shouldStop(CompileState.FLOW))
return;
- if (relax) {
- results.add(env);
- return;
- }
-
if (verboseCompilePolicy)
printNote("[flow " + env.enclClass.sym + "]");
JavaFileObject prev = log.useSource(
@@ -1419,9 +1393,9 @@ public class JavaCompiler {
TreeMaker localMake = make.forToplevel(env.toplevel);
if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF)) {
- if (!(stubOutput || sourceOutput || printFlat)) {
+ if (!(sourceOutput)) {
if (shouldStop(CompileState.LOWER))
- return;
+ return;
List pdef = lower.translateTopLevelClass(env, env.tree, localMake);
if (pdef.head != null) {
Assert.check(pdef.tail.isEmpty());
@@ -1431,19 +1405,6 @@ public class JavaCompiler {
return;
}
- if (stubOutput) {
- //emit stub Java source file, only for compilation
- //units enumerated explicitly on the command line
- JCClassDecl cdef = (JCClassDecl)env.tree;
- if (untranslated instanceof JCClassDecl &&
- rootClasses.contains((JCClassDecl)untranslated) &&
- ((cdef.mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 ||
- cdef.sym.packge().getQualifiedName() == names.java_lang)) {
- results.add(new Pair<>(env, removeMethodBodies(cdef)));
- }
- return;
- }
-
if (shouldStop(CompileState.TRANSTYPES))
return;
@@ -1504,16 +1465,12 @@ public class JavaCompiler {
if (shouldStop(CompileState.GENERATE))
return;
- boolean usePrintSource = (stubOutput || sourceOutput || printFlat);
-
for (Pair, JCClassDecl> x: queue) {
Env env = x.fst;
JCClassDecl cdef = x.snd;
if (verboseCompilePolicy) {
- printNote("[generate "
- + (usePrintSource ? " source" : "code")
- + " " + cdef.sym + "]");
+ printNote("[generate " + (sourceOutput ? " source" : "code") + " " + cdef.sym + "]");
}
if (!taskListener.isEmpty()) {
@@ -1526,9 +1483,9 @@ public class JavaCompiler {
env.toplevel.sourcefile);
try {
JavaFileObject file;
- if (usePrintSource)
+ if (sourceOutput) {
file = printSource(env, cdef);
- else {
+ } else {
if (fileManager.hasLocation(StandardLocation.NATIVE_HEADER_OUTPUT)
&& jniWriter.needsHeader(cdef.sym)) {
jniWriter.write(cdef.sym);
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java
index 0a291db707f..4867bdad290 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, 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
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
index 795f38032f7..281d8e82656 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
@@ -981,10 +981,6 @@ compiler.err.string.const.req=\
compiler.err.synthetic.name.conflict=\
the symbol {0} conflicts with a compiler-synthesized symbol in {1}
-# 0: symbol, 1: symbol
-compiler.warn.synthetic.name.conflict=\
- the symbol {0} conflicts with a compiler-synthesized symbol in {1}
-
compiler.err.throws.not.allowed.in.intf.annotation=\
throws clause not allowed in @interface members
@@ -1334,16 +1330,6 @@ compiler.misc.verbose.total=\
compiler.misc.verbose.wrote.file=\
[wrote {0}]
-## extra output when using -verbose (Retro)
-compiler.misc.verbose.retro=\
- [retrofitting {0}]
-
-compiler.misc.verbose.retro.with=\
- \tretrofitting {0} with {1}
-
-compiler.misc.verbose.retro.with.list=\
- \tretrofitting {0} with type parameters {1}, supertype {2}, interfaces {3}
-
## extra output when using -verbose (code/ClassReader)
# 0: string
compiler.misc.verbose.loading=\
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties
index d64280ab946..7246acf194f 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties
@@ -124,20 +124,12 @@ javac.opt.nogj=\
Don't accept generics in the language
javac.opt.moreinfo=\
Print extended information for type variables
-javac.opt.printflat=\
- Print abstract syntax tree after inner class conversion
javac.opt.printsearch=\
Print information where classfiles are searched
javac.opt.prompt=\
Stop after each error
-javac.opt.retrofit=\
- Retrofit existing classfiles with generic types
javac.opt.s=\
Emit java sources instead of classfiles
-javac.opt.scramble=\
- Scramble private identifiers in bytecode
-javac.opt.scrambleall=\
- Scramble package visible identifiers in bytecode
javac.opt.version=\
Version information
javac.opt.arg.pathname=\
diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java
index 56b369c8082..789069b49ed 100644
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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
@@ -170,12 +170,6 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask {
}
},
- new HiddenOption(false, "-stubs") {
- void process(JavahTask task, String opt, String arg) {
- // ignored; for backwards compatibility
- }
- },
-
new Option(false, "-v", "-verbose") {
void process(JavahTask task, String opt, String arg) {
task.verbose = true;
@@ -454,8 +448,6 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask {
if (llni)
g = new LLNI(doubleAlign, util);
else {
-// if (stubs)
-// throw new BadArgs("jni.no.stubs");
g = new JNI(util);
}
diff --git a/langtools/test/tools/javac/6257443/T6257443.java b/langtools/test/tools/javac/6257443/T6257443.java
index 5d81ed5d12f..91d3120908f 100644
--- a/langtools/test/tools/javac/6257443/T6257443.java
+++ b/langtools/test/tools/javac/6257443/T6257443.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, 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,13 +31,7 @@
*
* @clean foo.package-info
*
- * @compile -XD-printflat package-info.java
- * @run main/othervm T6257443 -no foo/package-info.class
- *
- * @compile -XD-stubs package-info.java
- * @run main/othervm T6257443 -no foo/package-info.class
- *
- * @compile -XD-printsource package-info.java
+ * @compile -printsource package-info.java
* @run main/othervm T6257443 -no foo/package-info.class
*/
diff --git a/langtools/test/tools/javac/6521805/T6521805a.java b/langtools/test/tools/javac/6521805/T6521805a.java
deleted file mode 100644
index d81fab6ddc5..00000000000
--- a/langtools/test/tools/javac/6521805/T6521805a.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * @test /nodynamiccopyright/
- * @bug 6521805
- * @summary Regression: JDK5/JDK6 javac allows write access to outer class reference
- * @author mcimadamore
- *
- * @compile/fail/ref=T6521805a_1.out T6521805a.java -XDrawDiagnostics
- * @compile/ref=T6521805a_2.out T6521805a.java -XDwarnOnSyntheticConflicts -XDrawDiagnostics
- */
-
-class T6521805a {
-
- static class Outer {
- T6521805a this$0 = null;
- }
-
- public class Inner extends Outer {
- public void foo() {
- this$0 = new T6521805a();
- }
- }
-}
diff --git a/langtools/test/tools/javac/6521805/T6521805a_1.out b/langtools/test/tools/javac/6521805/T6521805a_1.out
deleted file mode 100644
index 3c069c0a793..00000000000
--- a/langtools/test/tools/javac/6521805/T6521805a_1.out
+++ /dev/null
@@ -1,2 +0,0 @@
-T6521805a.java:17:12: compiler.err.synthetic.name.conflict: this$0, T6521805a.Outer
-1 error
diff --git a/langtools/test/tools/javac/6521805/T6521805a_2.out b/langtools/test/tools/javac/6521805/T6521805a_2.out
deleted file mode 100644
index 98d97813f36..00000000000
--- a/langtools/test/tools/javac/6521805/T6521805a_2.out
+++ /dev/null
@@ -1,2 +0,0 @@
-T6521805a.java:17:12: compiler.warn.synthetic.name.conflict: this$0, T6521805a.Outer
-1 warning
diff --git a/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java b/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java
index b9be7190088..62b92bcc15a 100644
--- a/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java
+++ b/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -61,8 +61,6 @@ public class EventsBalancedTest {
test(null, Arrays.asList(a, b));
test(null, Arrays.asList(b, a));
- test(Arrays.asList("-XD-relax"), Arrays.asList(a, b));
- test(Arrays.asList("-XD-relax"), Arrays.asList(b, a));
for (CompileState stop : CompileState.values()) {
test(Arrays.asList("-XDshouldStopPolicyIfNoError=" + stop,
diff --git a/langtools/test/tools/javac/diags/CheckResourceKeys.java b/langtools/test/tools/javac/diags/CheckResourceKeys.java
index 1c29a7240e0..9c1c0380fad 100644
--- a/langtools/test/tools/javac/diags/CheckResourceKeys.java
+++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java
@@ -231,22 +231,15 @@ public class CheckResourceKeys {
"compiler.err.type.var.more.than.once.in.result", // UNUSED
"compiler.misc.non.denotable.type", // UNUSED
"compiler.misc.unnamed.package", // should be required, CR 6964147
- "compiler.misc.verbose.retro", // UNUSED
- "compiler.misc.verbose.retro.with", // UNUSED
- "compiler.misc.verbose.retro.with.list", // UNUSED
"compiler.warn.proc.type.already.exists", // TODO in JavacFiler
"javac.err.invalid.arg", // UNUSED ??
"javac.opt.arg.class", // UNUSED ??
"javac.opt.arg.pathname", // UNUSED ??
"javac.opt.moreinfo", // option commented out
"javac.opt.nogj", // UNUSED
- "javac.opt.printflat", // option commented out
"javac.opt.printsearch", // option commented out
"javac.opt.prompt", // option commented out
- "javac.opt.retrofit", // UNUSED
- "javac.opt.s", // option commented out
- "javac.opt.scramble", // option commented out
- "javac.opt.scrambleall" // option commented out
+ "javac.opt.s" // option commented out
));
/**
diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt
index bd79b7940d0..806d471ea99 100644
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt
@@ -86,9 +86,6 @@ compiler.misc.unable.to.access.file # ClassFile
compiler.misc.undecl.type.var # ClassReader
compiler.misc.unicode.str.not.supported # ClassReader
compiler.misc.malformed.vararg.method # ClassReader
-compiler.misc.verbose.retro # UNUSED
-compiler.misc.verbose.retro.with # UNUSED
-compiler.misc.verbose.retro.with.list # UNUSED
compiler.misc.version.not.available # JavaCompiler; implies build error
compiler.misc.where.description.captured
compiler.misc.where.typevar.1
diff --git a/langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java b/langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java
deleted file mode 100644
index 508cfb4ceca..00000000000
--- a/langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010, 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.
- */
-
-// key: compiler.warn.synthetic.name.conflict
-// options: -XDwarnOnSyntheticConflicts
-
-class WarnSyntheticNameConflict {
-
- static class Outer {
- WarnSyntheticNameConflict this$0 = null;
- }
-
- public class Inner extends Outer { }
-}
From 0934254e0397496f7e271bea6fb803e96e529e11 Mon Sep 17 00:00:00 2001
From: Amy Lu
Date: Tue, 23 Feb 2016 09:52:56 +0800
Subject: [PATCH 070/311] 8149154: tools/pack200/Pack200Test.java failed with
NullPointerException
Reviewed-by: ksrini
---
jdk/test/tools/pack200/Pack200Test.java | 2 ++
jdk/test/tools/pack200/Utils.java | 5 ++++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/jdk/test/tools/pack200/Pack200Test.java b/jdk/test/tools/pack200/Pack200Test.java
index 9298e9723a8..fb6d9b1f83d 100644
--- a/jdk/test/tools/pack200/Pack200Test.java
+++ b/jdk/test/tools/pack200/Pack200Test.java
@@ -81,7 +81,9 @@ public class Pack200Test {
System.out.println("Packing [" + in.toString() + "]");
// Call the packer
Utils.pack(jarFile, packFile);
+ System.out.println("Done Packing [" + in.toString() + "]");
jarFile.close();
+ System.out.println("Start leak check");
leakCheck();
System.out.println(" Unpacking using java unpacker");
diff --git a/jdk/test/tools/pack200/Utils.java b/jdk/test/tools/pack200/Utils.java
index f0c29a597b5..60f2d0c50bc 100644
--- a/jdk/test/tools/pack200/Utils.java
+++ b/jdk/test/tools/pack200/Utils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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
@@ -324,6 +324,9 @@ class Utils {
private static void findFiles0(File startDir, List list,
FileFilter filter) throws IOException {
File[] foundFiles = startDir.listFiles(filter);
+ if (foundFiles == null) {
+ return;
+ }
list.addAll(Arrays.asList(foundFiles));
File[] dirs = startDir.listFiles(DIR_FILTER);
for (File dir : dirs) {
From a06164b8d9ce74075aa0a1b6c460e502f472ab97 Mon Sep 17 00:00:00 2001
From: Prasanta Sadhukhan
Date: Tue, 23 Feb 2016 10:22:40 +0530
Subject: [PATCH 071/311] 8150233: Missing copyright headers in
XSurfaceData/ExtendedKeyCodes
Reviewed-by: prr
---
.../classes/sun/awt/ExtendedKeyCodes.java | 24 +++++++++++++++++++
.../classes/sun/java2d/x11/XSurfaceData.java | 24 +++++++++++++++++++
2 files changed, 48 insertions(+)
diff --git a/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java b/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java
index 1e054b9de81..c034dbebd44 100644
--- a/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java
+++ b/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java
@@ -1,3 +1,27 @@
+/*
+ * Copyright (c) 2009, 2016, 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 sun.awt;
import java.util.Collections;
diff --git a/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java b/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java
index 8e71a80a0e9..dbae176dd7e 100644
--- a/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java
+++ b/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java
@@ -1,3 +1,27 @@
+/*
+ * Copyright (c) 2010, 2016, 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 sun.java2d.x11;
import java.awt.image.*;
From 43cef7fa52bf08269e2dbd60408f4b0f6d6547b1 Mon Sep 17 00:00:00 2001
From: Manajit Halder
Date: Tue, 23 Feb 2016 10:24:29 +0530
Subject: [PATCH 072/311] 8147834: [macosx] KeyEvents for function keys F17,
F18, F19 return keyCode 0
Reviewed-by: serb, aniyogi
---
.../macosx/native/libawt_lwawt/awt/AWTEvent.m | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m
index 07bb7fab938..9b8e370a938 100644
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m
@@ -134,7 +134,7 @@ const keyTable[] =
{0x3D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
{0x3E, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
{0x3F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, // the 'fn' key on PowerBooks
- {0x40, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
+ {0x40, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F17},
{0x41, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_DECIMAL},
{0x42, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
{0x43, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_MULTIPLY},
@@ -149,8 +149,8 @@ const keyTable[] =
{0x4C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ENTER},
{0x4D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
{0x4E, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_SUBTRACT},
- {0x4F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
- {0x50, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
+ {0x4F, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F18},
+ {0x50, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F19},
{0x51, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_EQUALS},
{0x52, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD0},
{0x53, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD1},
@@ -160,7 +160,7 @@ const keyTable[] =
{0x57, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD5},
{0x58, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD6},
{0x59, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD7},
- {0x5A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED},
+ {0x5A, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F20},
{0x5B, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD8},
{0x5C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD9},
{0x5D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SLASH}, // This is a combo yen/backslash on JIS keyboards.
From 5baf4fccc46aa4ebc274f85accdb3da5757603cb Mon Sep 17 00:00:00 2001
From: Michael Haupt
Date: Tue, 23 Feb 2016 07:17:54 +0100
Subject: [PATCH 073/311] 8150360: augment/correct MethodHandle API
documentation
Reviewed-by: psandoz
---
.../java/lang/invoke/MethodHandle.java | 15 ++++++++--
.../java/lang/invoke/MethodHandles.java | 28 +++++++++++++++++--
2 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java
index a3f6f47b00f..235ffe60f57 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, 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
@@ -1026,6 +1026,9 @@ MethodHandle longsToString = publicLookup()
.asCollector(long[].class, 1);
assertEquals("[123]", (String) longsToString.invokeExact((long)123));
* }
+ *
+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+ * variable-arity method handle}, even if the original target method handle was.
* @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
* @param arrayLength the number of arguments to collect into a new array argument
* @return a new method handle which collects some trailing argument
@@ -1067,6 +1070,9 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123));
swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1);
assertEquals("BCPQRSZ", swr.toString());
* }
+ *
+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+ * variable-arity method handle}, even if the original target method handle was.
* @param collectArgPos the zero-based position in the parameter list at which to start collecting.
* @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
* @param arrayLength the number of arguments to collect into a new array argument
@@ -1356,8 +1362,11 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
* The reference {@code x} must be convertible to the first parameter
* type of the target.
*
- * (Note: Because method handles are immutable, the target method handle
- * retains its original type and behavior.)
+ * Note: Because method handles are immutable, the target method handle
+ * retains its original type and behavior.
+ *
+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+ * variable-arity method handle}, even if the original target method handle was.
* @param x the value to bind to the first argument of the target
* @return a new method handle which prepends the given value to the incoming
* argument list, before calling the original method handle
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index fc9ac8e1518..c7389b63b05 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -2139,7 +2139,7 @@ return invoker;
* if its index does not appear in the array.
* As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
* incoming arguments which are not mentioned in the reordering array
- * are may be any type, as determined only by {@code newType}.
+ * may be of any type, as determined only by {@code newType}.
*
{@code
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
@@ -2157,6 +2157,9 @@ MethodHandle twice = permuteArguments(add, intfn1, 0, 0);
assert(twice.type().equals(intfn1));
assert((int)twice.invokeExact(21) == 42);
* }
+ *
+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+ * variable-arity method handle}, even if the original target method handle was.
* @param target the method handle to invoke after arguments are reordered
* @param newType the expected type of the new method handle
* @param reorder an index array which controls the reordering
@@ -2421,6 +2424,9 @@ assert((int)twice.invokeExact(21) == 42);
* It may range between zero and N-L (inclusively),
* where N is the arity of the target method handle
* and L is the length of the values array.
+ *
+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+ * variable-arity method handle}, even if the original target method handle was.
* @param target the method handle to invoke after the argument is inserted
* @param pos where to insert the argument (zero for the first)
* @param values the series of arguments to insert
@@ -2647,6 +2653,9 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
* return target(p..., f[i](v[i])..., b...);
* }
* }
+ *
+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+ * variable-arity method handle}, even if the original target method handle was.
*
* @param target the method handle to invoke after arguments are filtered
* @param pos the position of the first argument to filter
@@ -2791,6 +2800,9 @@ assertEquals("[top, [[up, down, strange], charm], bottom]",
* a non-void result, then {@code collectArguments(mh, N, coll)}
* is equivalent to {@code filterArguments(mh, N, coll)}.
* Other equivalences are possible but would require argument permutation.
+ *
+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+ * variable-arity method handle}, even if the original target method handle was.
*
* @param target the method handle to invoke after filtering the subsequence of arguments
* @param pos the position of the first adapter argument to pass to the filter,
@@ -2887,6 +2899,9 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
* filter3(v);
* }
* }
+ *
+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+ * variable-arity method handle}, even if the original target method handle was.
* @param target the method handle to invoke before filtering the return value
* @param filter method handle to call on the return value
* @return method handle which incorporates the specified return value filtering logic
@@ -2981,6 +2996,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* return target2(a..., b...);
* }
* }
+ *
+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+ * variable-arity method handle}, even if the original target method handle was.
* @param target the method handle to invoke after arguments are combined
* @param combiner method handle to call initially on the incoming arguments
* @return method handle which incorporates the specified argument folding logic
@@ -3828,8 +3846,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* (Note that, except for argument type conversions, combinators represent {@code void} values in parameter lists
* by omitting the corresponding paradoxical arguments, not by inserting {@code null} or zero values.)
*
- * The {@code target} and {@code cleanup} handles' return types must be the same. Their parameter type lists also
- * must be the same, but the {@code cleanup} handle must accept one or two more leading parameters:
+ * The {@code target} and {@code cleanup} handles must have the same corresponding argument and return types, except
+ * that the {@code cleanup} handle may omit trailing arguments. Also, the {@code cleanup} handle must have one or
+ * two extra leading parameters:
* a {@code Throwable}, which will carry the exception thrown by the {@code target} handle (if any); and
* a parameter of the same type as the return type of both {@code target} and {@code cleanup}, which will carry
* the result from the execution of the {@code target} handle.
@@ -3949,6 +3968,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* return target2(z..., a..., b...);
* }
* }
+ *
+ * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+ * variable-arity method handle}, even if the original target method handle was.
*
* @param target the method handle to invoke after arguments are combined
* @param pos the position at which to start folding and at which to insert the folding result; if this is {@code
From 28d990ee6fae99f1e35fca94fcb6d4a894efae64 Mon Sep 17 00:00:00 2001
From: Nishit Jain
Date: Tue, 23 Feb 2016 17:09:46 +0900
Subject: [PATCH 074/311] 8074411: Describe "minor unit" and/or "default
fraction digits" in Currency class' javadoc clearly
Reviewed-by: naoto, okutsu, peytoia
---
.../share/classes/java/util/Currency.java | 25 ++++++++++++-------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/jdk/src/java.base/share/classes/java/util/Currency.java b/jdk/src/java.base/share/classes/java/util/Currency.java
index 74c7b4bb3fc..8648147bcfe 100644
--- a/jdk/src/java.base/share/classes/java/util/Currency.java
+++ b/jdk/src/java.base/share/classes/java/util/Currency.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -92,7 +92,12 @@ import sun.util.logging.PlatformLogger;
* and the remainder of entries in file are processed. For instances where duplicate
* country code entries exist, the behavior of the Currency information for that
* {@code Currency} is undefined and the remainder of entries in file are processed.
+ *
+ * It is recommended to use {@link java.math.BigDecimal} class while dealing
+ * with {@code Currency} or monetary values as it provides better handling of floating
+ * point numbers and their operations.
*
+ * @see java.math.BigDecimal
* @since 1.4
*/
public final class Currency implements Serializable {
@@ -516,14 +521,16 @@ public final class Currency implements Serializable {
}
/**
- * Gets the default number of fraction digits used with this currency.
- * For example, the default number of fraction digits for the Euro is 2,
- * while for the Japanese Yen it's 0.
- * In the case of pseudo-currencies, such as IMF Special Drawing Rights,
- * -1 is returned.
- *
- * @return the default number of fraction digits used with this currency
- */
+ * Gets the default number of fraction digits used with this currency.
+ * Note that the number of fraction digits is the same as ISO 4217's
+ * minor unit for the currency.
+ * For example, the default number of fraction digits for the Euro is 2,
+ * while for the Japanese Yen it's 0.
+ * In the case of pseudo-currencies, such as IMF Special Drawing Rights,
+ * -1 is returned.
+ *
+ * @return the default number of fraction digits used with this currency
+ */
public int getDefaultFractionDigits() {
return defaultFractionDigits;
}
From 19a07cb7dbe771af578160533c7bd6ffca49b28a Mon Sep 17 00:00:00 2001
From: Michael Haupt
Date: Tue, 23 Feb 2016 09:49:04 +0100
Subject: [PATCH 075/311] 8143410: augment pseudo-code descriptions in
MethodHandles API
Reviewed-by: psandoz
---
.../java/lang/invoke/MethodHandles.java | 91 +++++++++++++++----
1 file changed, 71 insertions(+), 20 deletions(-)
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
index c7389b63b05..befe2520ec7 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
@@ -2645,12 +2645,20 @@ assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
* }
- * Here is pseudocode for the resulting adapter:
+ *
Here is pseudocode for the resulting adapter. In the code, {@code T}
+ * denotes the return type of both the {@code target} and resulting adapter.
+ * {@code P}/{@code p} and {@code B}/{@code b} represent the types and values
+ * of the parameters and arguments that precede and follow the filter position
+ * {@code pos}, respectively. {@code A[i]}/{@code a[i]} stand for the types and
+ * values of the filtered parameters and arguments; they also represent the
+ * return types of the {@code filter[i]} handles. The latter accept arguments
+ * {@code v[i]} of type {@code V[i]}, which also appear in the signature of
+ * the resulting adapter.
*
{@code
- * V target(P... p, A[i]... a[i], B... b);
+ * T target(P... p, A[i]... a[i], B... b);
* A[i] filter[i](V[i]);
* T adapter(P... p, V[i]... v[i], B... b) {
- * return target(p..., f[i](v[i])..., b...);
+ * return target(p..., filter[i](v[i])..., b...);
* }
* }
*
@@ -2762,7 +2770,17 @@ MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
assertEquals("[top, [[up, down, strange], charm], bottom]",
(String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
* }
- *
Here is pseudocode for the resulting adapter:
+ *
Here is pseudocode for the resulting adapter. In the code, {@code T}
+ * represents the return type of the {@code target} and resulting adapter.
+ * {@code V}/{@code v} stand for the return type and value of the
+ * {@code filter}, which are also found in the signature and arguments of
+ * the {@code target}, respectively, unless {@code V} is {@code void}.
+ * {@code A}/{@code a} and {@code C}/{@code c} represent the parameter types
+ * and values preceding and following the collection position, {@code pos},
+ * in the {@code target}'s signature. They also turn up in the resulting
+ * adapter's signature and arguments, where they surround
+ * {@code B}/{@code b}, which represent the parameter types and arguments
+ * to the {@code filter} (if any).
*
{@code
* T target(A...,V,C...);
* V filter(B...);
@@ -2780,7 +2798,7 @@ assertEquals("[top, [[up, down, strange], charm], bottom]",
* // and if the filter has a void return:
* T target3(A...,C...);
* void filter3(B...);
- * void adapter3(A... a,B... b,C... c) {
+ * T adapter3(A... a,B... b,C... c) {
* filter3(b...);
* return target3(a...,c...);
* }
@@ -2876,27 +2894,31 @@ System.out.println((String) cat.invokeExact("x", "y")); // xy
MethodHandle f0 = filterReturnValue(cat, length);
System.out.println((int) f0.invokeExact("x", "y")); // 2
* }
- * Here is pseudocode for the resulting adapter:
+ *
Here is pseudocode for the resulting adapter. In the code,
+ * {@code T}/{@code t} represent the result type and value of the
+ * {@code target}; {@code V}, the result type of the {@code filter}; and
+ * {@code A}/{@code a}, the types and values of the parameters and arguments
+ * of the {@code target} as well as the resulting adapter.
*
{@code
- * V target(A...);
- * T filter(V);
- * T adapter(A... a) {
- * V v = target(a...);
- * return filter(v);
+ * T target(A...);
+ * V filter(T);
+ * V adapter(A... a) {
+ * T t = target(a...);
+ * return filter(t);
* }
* // and if the target has a void return:
* void target2(A...);
- * T filter2();
- * T adapter2(A... a) {
+ * V filter2();
+ * V adapter2(A... a) {
* target2(a...);
* return filter2();
* }
* // and if the filter has a void return:
- * V target3(A...);
+ * T target3(A...);
* void filter3(V);
* void adapter3(A... a) {
- * V v = target3(a...);
- * filter3(v);
+ * T t = target3(a...);
+ * filter3(t);
* }
* }
*
@@ -2979,7 +3001,15 @@ MethodHandle catTrace = foldArguments(cat, trace);
// also prints "boo":
assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* }
- *
Here is pseudocode for the resulting adapter:
+ *
Here is pseudocode for the resulting adapter. In the code, {@code T}
+ * represents the result type of the {@code target} and resulting adapter.
+ * {@code V}/{@code v} represent the type and value of the parameter and argument
+ * of {@code target} that precedes the folding position; {@code V} also is
+ * the result type of the {@code combiner}. {@code A}/{@code a} denote the
+ * types and values of the {@code N} parameters and arguments at the folding
+ * position. {@code B}/{@code b} represent the types and values of the
+ * {@code target} parameters and arguments that follow the folded parameters
+ * and arguments.
*
{@code
* // there are N arguments in A...
* T target(V, A[N]..., B...);
@@ -3040,7 +3070,13 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* argument and return types, except that the return type
* of the test must be boolean, and the test is allowed
* to have fewer arguments than the other two method handles.
- * Here is pseudocode for the resulting adapter:
+ *
+ * Here is pseudocode for the resulting adapter. In the code, {@code T}
+ * represents the uniform result type of the three involved handles;
+ * {@code A}/{@code a}, the types and values of the {@code target}
+ * parameters and arguments that are consumed by the {@code test}; and
+ * {@code B}/{@code b}, those types and values of the {@code target}
+ * parameters and arguments that are not consumed by the {@code test}.
*
{@code
* boolean test(A...);
* T target(A...,B...);
@@ -3102,7 +3138,13 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* argument and return types, except that handler may omit trailing arguments
* (similarly to the predicate in {@link #guardWithTest guardWithTest}).
* Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
- * Here is pseudocode for the resulting adapter:
+ *
+ * Here is pseudocode for the resulting adapter. In the code, {@code T}
+ * represents the return type of the {@code target} and {@code handler},
+ * and correspondingly that of the resulting adapter; {@code A}/{@code a},
+ * the types and values of arguments to the resulting handle consumed by
+ * {@code handler}; and {@code B}/{@code b}, those of arguments to the
+ * resulting handle discarded by {@code handler}.
*
{@code
* T target(A..., B...);
* T handler(ExType, A...);
@@ -3951,7 +3993,16 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
// also prints "jum":
assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
* }
- * Here is pseudocode for the resulting adapter:
+ *
Here is pseudocode for the resulting adapter. In the code, {@code T}
+ * represents the result type of the {@code target} and resulting adapter.
+ * {@code V}/{@code v} represent the type and value of the parameter and argument
+ * of {@code target} that precedes the folding position; {@code V} also is
+ * the result type of the {@code combiner}. {@code A}/{@code a} denote the
+ * types and values of the {@code N} parameters and arguments at the folding
+ * position. {@code Z}/{@code z} and {@code B}/{@code b} represent the types
+ * and values of the {@code target} parameters and arguments that precede and
+ * follow the folded parameters and arguments starting at {@code pos},
+ * respectively.
*
{@code
* // there are N arguments in A...
* T target(Z..., V, A[N]..., B...);
From e020d2f477f39ef03d161f0f0123df315a3c5b40 Mon Sep 17 00:00:00 2001
From: Bengt Rutisson
Date: Tue, 23 Feb 2016 09:52:46 +0100
Subject: [PATCH 076/311] 8150367: Add back information about the number of GC
workers
Reviewed-by: sjohanss, tschatzl
---
hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp | 9 +++++----
hotspot/src/share/vm/gc/shared/workgroup.hpp | 2 ++
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
index d7546a121ff..f241d749045 100644
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp
@@ -3235,10 +3235,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
GCTraceCPUTime tcpu;
- uint active_workers = AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(),
- workers()->active_workers(),
- Threads::number_of_non_daemon_threads());
- workers()->set_active_workers(active_workers);
FormatBuffer<> gc_string("Pause ");
if (collector_state()->during_initial_mark_pause()) {
gc_string.append("Initial Mark");
@@ -3249,6 +3245,11 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) {
}
GCTraceTime(Info, gc) tm(gc_string, NULL, gc_cause(), true);
+ uint active_workers = AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(),
+ workers()->active_workers(),
+ Threads::number_of_non_daemon_threads());
+ workers()->set_active_workers(active_workers);
+
g1_policy()->note_gc_start(active_workers);
TraceCollectorStats tcs(g1mm()->incremental_collection_counters());
diff --git a/hotspot/src/share/vm/gc/shared/workgroup.hpp b/hotspot/src/share/vm/gc/shared/workgroup.hpp
index b2a48647cab..c28579ef471 100644
--- a/hotspot/src/share/vm/gc/shared/workgroup.hpp
+++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp
@@ -29,6 +29,7 @@
#include "runtime/globals.hpp"
#include "runtime/thread.hpp"
#include "gc/shared/gcId.hpp"
+#include "logging/log.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
@@ -151,6 +152,7 @@ class AbstractWorkGang : public CHeapObj {
_active_workers = MAX2(1U, _active_workers);
assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
"Unless dynamic should use total workers");
+ log_info(gc, task)("GC Workers: %d", _active_workers);
}
// Return the Ith worker.
From 861dc1364556f2b7f6c7d9e57ea16e588e76888e Mon Sep 17 00:00:00 2001
From: Antonios Printezis
Date: Tue, 23 Feb 2016 10:44:05 +0100
Subject: [PATCH 077/311] 8146989: Introduce per-worker preserved mark stacks
in ParNew
Unify and provide per-worker preserved mark stack handling in ParNew
Reviewed-by: tschatzl, ysr
---
.../src/share/vm/gc/cms/parNewGeneration.cpp | 26 ++--
.../src/share/vm/gc/cms/parNewGeneration.hpp | 9 +-
hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp | 15 +--
.../share/vm/gc/serial/defNewGeneration.cpp | 40 ++-----
.../share/vm/gc/serial/defNewGeneration.hpp | 12 +-
.../src/share/vm/gc/shared/preservedMarks.cpp | 93 +++++++++++++++
.../src/share/vm/gc/shared/preservedMarks.hpp | 111 ++++++++++++++++++
.../vm/gc/shared/preservedMarks.inline.hpp | 48 ++++++++
8 files changed, 284 insertions(+), 70 deletions(-)
create mode 100644 hotspot/src/share/vm/gc/shared/preservedMarks.cpp
create mode 100644 hotspot/src/share/vm/gc/shared/preservedMarks.hpp
create mode 100644 hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp
diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp
index 0f2f019e9d8..6962f158e5c 100644
--- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp
+++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp
@@ -39,6 +39,7 @@
#include "gc/shared/genOopClosures.inline.hpp"
#include "gc/shared/generation.hpp"
#include "gc/shared/plab.inline.hpp"
+#include "gc/shared/preservedMarks.inline.hpp"
#include "gc/shared/referencePolicy.hpp"
#include "gc/shared/space.hpp"
#include "gc/shared/spaceDecorator.hpp"
@@ -64,6 +65,7 @@ ParScanThreadState::ParScanThreadState(Space* to_space_,
int thread_num_,
ObjToScanQueueSet* work_queue_set_,
Stack* overflow_stacks_,
+ PreservedMarks* preserved_marks_,
size_t desired_plab_sz_,
ParallelTaskTerminator& term_) :
_to_space(to_space_),
@@ -73,6 +75,7 @@ ParScanThreadState::ParScanThreadState(Space* to_space_,
_work_queue(work_queue_set_->queue(thread_num_)),
_to_space_full(false),
_overflow_stack(overflow_stacks_ ? overflow_stacks_ + thread_num_ : NULL),
+ _preserved_marks(preserved_marks_),
_ageTable(false), // false ==> not the global age table, no perf data.
_to_space_alloc_buffer(desired_plab_sz_),
_to_space_closure(young_gen_, this),
@@ -286,6 +289,7 @@ public:
Generation& old_gen,
ObjToScanQueueSet& queue_set,
Stack* overflow_stacks_,
+ PreservedMarksSet& preserved_marks_set,
size_t desired_plab_sz,
ParallelTaskTerminator& term);
@@ -322,6 +326,7 @@ ParScanThreadStateSet::ParScanThreadStateSet(int num_threads,
Generation& old_gen,
ObjToScanQueueSet& queue_set,
Stack* overflow_stacks,
+ PreservedMarksSet& preserved_marks_set,
size_t desired_plab_sz,
ParallelTaskTerminator& term)
: ResourceArray(sizeof(ParScanThreadState), num_threads),
@@ -336,7 +341,8 @@ ParScanThreadStateSet::ParScanThreadStateSet(int num_threads,
for (int i = 0; i < num_threads; ++i) {
new ((ParScanThreadState*)_data + i)
ParScanThreadState(&to_space, &young_gen, &old_gen, i, &queue_set,
- overflow_stacks, desired_plab_sz, term);
+ overflow_stacks, preserved_marks_set.get(i),
+ desired_plab_sz, term);
}
}
@@ -905,12 +911,16 @@ void ParNewGeneration::collect(bool full,
// Set the correct parallelism (number of queues) in the reference processor
ref_processor()->set_active_mt_degree(active_workers);
+ // Need to initialize the preserved marks before the ThreadStateSet c'tor.
+ _preserved_marks_set.init(active_workers);
+
// Always set the terminator for the active number of workers
// because only those workers go through the termination protocol.
ParallelTaskTerminator _term(active_workers, task_queues());
ParScanThreadStateSet thread_state_set(active_workers,
*to(), *this, *_old_gen, *task_queues(),
- _overflow_stacks, desired_plab_sz(), _term);
+ _overflow_stacks, _preserved_marks_set,
+ desired_plab_sz(), _term);
thread_state_set.reset(active_workers, promotion_failed());
@@ -993,6 +1003,7 @@ void ParNewGeneration::collect(bool full,
} else {
handle_promotion_failed(gch, thread_state_set);
}
+ _preserved_marks_set.reclaim();
// set new iteration safe limit for the survivor spaces
from()->set_concurrent_iteration_safe_limit(from()->top());
to()->set_concurrent_iteration_safe_limit(to()->top());
@@ -1070,15 +1081,6 @@ oop ParNewGeneration::real_forwardee_slow(oop obj) {
return forward_ptr;
}
-void ParNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) {
- if (m->must_be_preserved_for_promotion_failure(obj)) {
- // We should really have separate per-worker stacks, rather
- // than use locking of a common pair of stacks.
- MutexLocker ml(ParGCRareEvent_lock);
- preserve_mark(obj, m);
- }
-}
-
// Multiple GC threads may try to promote an object. If the object
// is successfully promoted, a forwarding pointer will be installed in
// the object in the young generation. This method claims the right
@@ -1136,7 +1138,7 @@ oop ParNewGeneration::copy_to_survivor_space(ParScanThreadState* par_scan_state,
_promotion_failed = true;
new_obj = old;
- preserve_mark_if_necessary(old, m);
+ par_scan_state->preserved_marks()->push_if_necessary(old, m);
par_scan_state->register_promotion_failure(sz);
}
diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp
index 765ea72962e..94ec916357c 100644
--- a/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp
+++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp
@@ -30,6 +30,7 @@
#include "gc/shared/copyFailedInfo.hpp"
#include "gc/shared/gcTrace.hpp"
#include "gc/shared/plab.hpp"
+#include "gc/shared/preservedMarks.hpp"
#include "gc/shared/taskqueue.hpp"
#include "memory/padded.hpp"
@@ -65,6 +66,7 @@ class ParScanThreadState {
private:
ObjToScanQueue *_work_queue;
Stack* const _overflow_stack;
+ PreservedMarks* const _preserved_marks;
PLAB _to_space_alloc_buffer;
@@ -128,6 +130,7 @@ class ParScanThreadState {
Generation* old_gen_, int thread_num_,
ObjToScanQueueSet* work_queue_set_,
Stack* overflow_stacks_,
+ PreservedMarks* preserved_marks_,
size_t desired_plab_sz_,
ParallelTaskTerminator& term_);
@@ -136,6 +139,8 @@ class ParScanThreadState {
ObjToScanQueue* work_queue() { return _work_queue; }
+ PreservedMarks* preserved_marks() const { return _preserved_marks; }
+
PLAB* to_space_alloc_buffer() {
return &_to_space_alloc_buffer;
}
@@ -331,10 +336,6 @@ class ParNewGeneration: public DefNewGeneration {
static oop real_forwardee_slow(oop obj);
static void waste_some_time();
- // Preserve the mark of "obj", if necessary, in preparation for its mark
- // word being overwritten with a self-forwarding-pointer.
- void preserve_mark_if_necessary(oop obj, markOop m);
-
void handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set);
protected:
diff --git a/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp b/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp
index ca7643f59a8..eff37e8ae44 100644
--- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp
+++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp
@@ -27,25 +27,12 @@
#include "gc/g1/g1OopClosures.hpp"
#include "gc/g1/heapRegionManager.hpp"
+ #include "gc/shared/preservedMarks.hpp"
#include "gc/shared/workgroup.hpp"
#include "utilities/globalDefinitions.hpp"
class G1CollectedHeap;
-class OopAndMarkOop {
- oop _o;
- markOop _m;
- public:
- OopAndMarkOop(oop obj, markOop m) : _o(obj), _m(m) {
- }
-
- void set_mark() {
- _o->set_mark(_m);
- }
-};
-
-typedef Stack OopAndMarkOopStack;
-
// Task to fixup self-forwarding pointers
// installed as a result of an evacuation failure.
class G1ParRemoveSelfForwardPtrsTask: public AbstractGangTask {
diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp
index 9c00cd90383..08a21b2634f 100644
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp
@@ -36,6 +36,7 @@
#include "gc/shared/genCollectedHeap.hpp"
#include "gc/shared/genOopClosures.inline.hpp"
#include "gc/shared/generationSpec.hpp"
+#include "gc/shared/preservedMarks.inline.hpp"
#include "gc/shared/referencePolicy.hpp"
#include "gc/shared/space.inline.hpp"
#include "gc/shared/spaceDecorator.hpp"
@@ -184,6 +185,7 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs,
size_t initial_size,
const char* policy)
: Generation(rs, initial_size),
+ _preserved_marks_set(false /* in_c_heap */),
_promo_failure_drain_in_progress(false),
_should_allocate_from_space(false)
{
@@ -602,6 +604,8 @@ void DefNewGeneration::collect(bool full,
age_table()->clear();
to()->clear(SpaceDecorator::Mangle);
+ // The preserved marks should be empty at the start of the GC.
+ _preserved_marks_set.init(1);
gch->rem_set()->prepare_for_younger_refs_iterate(false);
@@ -704,6 +708,8 @@ void DefNewGeneration::collect(bool full,
// Reset the PromotionFailureALot counters.
NOT_PRODUCT(gch->reset_promotion_should_fail();)
}
+ // We should have processed and cleared all the preserved marks.
+ _preserved_marks_set.reclaim();
// set new iteration safe limit for the survivor spaces
from()->set_concurrent_iteration_safe_limit(from()->top());
to()->set_concurrent_iteration_safe_limit(to()->top());
@@ -721,13 +727,6 @@ void DefNewGeneration::collect(bool full,
gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions());
}
-class RemoveForwardPointerClosure: public ObjectClosure {
-public:
- void do_object(oop obj) {
- obj->init_mark();
- }
-};
-
void DefNewGeneration::init_assuming_no_promotion_failure() {
_promotion_failed = false;
_promotion_failed_info.reset();
@@ -735,33 +734,12 @@ void DefNewGeneration::init_assuming_no_promotion_failure() {
}
void DefNewGeneration::remove_forwarding_pointers() {
- RemoveForwardPointerClosure rspc;
+ RemoveForwardedPointerClosure rspc;
eden()->object_iterate(&rspc);
from()->object_iterate(&rspc);
// Now restore saved marks, if any.
- assert(_objs_with_preserved_marks.size() == _preserved_marks_of_objs.size(),
- "should be the same");
- while (!_objs_with_preserved_marks.is_empty()) {
- oop obj = _objs_with_preserved_marks.pop();
- markOop m = _preserved_marks_of_objs.pop();
- obj->set_mark(m);
- }
- _objs_with_preserved_marks.clear(true);
- _preserved_marks_of_objs.clear(true);
-}
-
-void DefNewGeneration::preserve_mark(oop obj, markOop m) {
- assert(_promotion_failed && m->must_be_preserved_for_promotion_failure(obj),
- "Oversaving!");
- _objs_with_preserved_marks.push(obj);
- _preserved_marks_of_objs.push(m);
-}
-
-void DefNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) {
- if (m->must_be_preserved_for_promotion_failure(obj)) {
- preserve_mark(obj, m);
- }
+ _preserved_marks_set.restore();
}
void DefNewGeneration::handle_promotion_failure(oop old) {
@@ -769,7 +747,7 @@ void DefNewGeneration::handle_promotion_failure(oop old) {
_promotion_failed = true;
_promotion_failed_info.register_copy_failure(old->size());
- preserve_mark_if_necessary(old, old->mark());
+ _preserved_marks_set.get()->push_if_necessary(old, old->mark());
// forward to self
old->forward_to(old);
diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp
index 484a6b6aa52..f258491ae32 100644
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp
@@ -30,6 +30,7 @@
#include "gc/shared/copyFailedInfo.hpp"
#include "gc/shared/generation.hpp"
#include "gc/shared/generationCounters.hpp"
+#include "gc/shared/preservedMarks.hpp"
#include "utilities/stack.hpp"
class ContiguousSpace;
@@ -87,15 +88,8 @@ protected:
// therefore we must remove their forwarding pointers.
void remove_forwarding_pointers();
- // Preserve the mark of "obj", if necessary, in preparation for its mark
- // word being overwritten with a self-forwarding-pointer.
- void preserve_mark_if_necessary(oop obj, markOop m);
- void preserve_mark(oop obj, markOop m); // work routine used by the above
-
- // Together, these keep pairs.
- // They should always contain the same number of elements.
- Stack _objs_with_preserved_marks;
- Stack _preserved_marks_of_objs;
+ // Preserved marks
+ PreservedMarksSet _preserved_marks_set;
// Promotion failure handling
ExtendedOopClosure *_promo_failure_scan_stack_closure;
diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.cpp b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp
new file mode 100644
index 00000000000..a82c8dd7bd4
--- /dev/null
+++ b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/preservedMarks.inline.hpp"
+#include "memory/allocation.inline.hpp"
+#include "oops/oop.inline.hpp"
+
+void PreservedMarks::restore() {
+ // First, iterate over the stack and restore all marks.
+ StackIterator iter(_stack);
+ while (!iter.is_empty()) {
+ OopAndMarkOop elem = iter.next();
+ elem.set_mark();
+ }
+
+ // Second, reclaim all the stack memory
+ _stack.clear(true /* clear_cache */);
+}
+
+void RemoveForwardedPointerClosure::do_object(oop obj) {
+ if (obj->is_forwarded()) {
+ obj->init_mark();
+ }
+}
+
+void PreservedMarksSet::init(uint num) {
+ assert(_stacks == NULL && _num == 0, "do not re-initialize");
+ assert(num > 0, "pre-condition");
+ if (_in_c_heap) {
+ _stacks = NEW_C_HEAP_ARRAY(Padded, num, mtGC);
+ } else {
+ _stacks = NEW_RESOURCE_ARRAY(Padded, num);
+ }
+ for (uint i = 0; i < num; i += 1) {
+ ::new (_stacks + i) PreservedMarks();
+ }
+ _num = num;
+
+ assert_empty();
+}
+
+void PreservedMarksSet::restore() {
+ for (uint i = 0; i < _num; i += 1) {
+ get(i)->restore();
+ }
+}
+
+void PreservedMarksSet::reclaim() {
+ assert_empty();
+
+ for (uint i = 0; i < _num; i += 1) {
+ _stacks[i].~Padded();
+ }
+
+ if (_in_c_heap) {
+ FREE_C_HEAP_ARRAY(Padded, _stacks);
+ } else {
+ // the array was resource-allocated, so nothing to do
+ }
+ _stacks = NULL;
+ _num = 0;
+}
+
+#ifndef PRODUCT
+void PreservedMarksSet::assert_empty() {
+ assert(_stacks != NULL && _num > 0, "should have been initialized");
+ for (uint i = 0; i < _num; i += 1) {
+ assert(get(i)->is_empty(), "stack should be empty");
+ }
+}
+#endif // ndef PRODUCT
diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.hpp b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp
new file mode 100644
index 00000000000..42576d18f38
--- /dev/null
+++ b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_SHARED_PRESERVEDMARKS_HPP
+#define SHARE_VM_GC_SHARED_PRESERVEDMARKS_HPP
+
+#include "memory/allocation.hpp"
+#include "memory/padded.hpp"
+#include "oops/oop.hpp"
+#include "utilities/stack.hpp"
+
+class OopAndMarkOop {
+private:
+ oop _o;
+ markOop _m;
+
+public:
+ OopAndMarkOop(oop obj, markOop m) : _o(obj), _m(m) { }
+
+ void set_mark() const {
+ _o->set_mark(_m);
+ }
+};
+typedef Stack OopAndMarkOopStack;
+
+class PreservedMarks VALUE_OBJ_CLASS_SPEC {
+private:
+ OopAndMarkOopStack _stack;
+
+ inline bool should_preserve_mark(oop obj, markOop m) const;
+ inline void push(oop obj, markOop m);
+
+public:
+ bool is_empty() const { return _stack.is_empty(); }
+ inline void push_if_necessary(oop obj, markOop m);
+ // Iterate over the stack, restore the preserved marks, then reclaim
+ // the memory taken up by stack chunks.
+ void restore();
+ ~PreservedMarks() { assert(is_empty(), "should have been cleared"); }
+};
+
+class RemoveForwardedPointerClosure: public ObjectClosure {
+public:
+ virtual void do_object(oop obj);
+};
+
+class PreservedMarksSet VALUE_OBJ_CLASS_SPEC {
+private:
+ // true -> _stacks will be allocated in the C heap
+ // false -> _stacks will be allocated in the resource arena
+ const bool _in_c_heap;
+
+ // Number of stacks we have allocated (typically, one stack per GC worker).
+ // This should be >= 1 if the stacks have been initialized,
+ // or == 0 if they have not.
+ uint _num;
+
+ // Stack array (typically, one stack per GC worker) of length _num.
+ // This should be != NULL if the stacks have been initialized,
+ // or == NULL if they have not.
+ Padded* _stacks;
+
+public:
+ // Return the i'th stack.
+ PreservedMarks* get(uint i = 0) const {
+ assert(_num > 0 && _stacks != NULL, "stacks should have been initialized");
+ assert(i < _num, "pre-condition");
+ return (_stacks + i);
+ }
+
+ // Allocate stack array.
+ void init(uint num);
+ // Iterate over all stacks, restore all preserved marks, then
+ // reclaim the memory taken up by stack chunks.
+ void restore();
+ // Reclaim stack array.
+ void reclaim();
+
+ // Assert all the stacks are empty.
+ void assert_empty() PRODUCT_RETURN;
+
+ PreservedMarksSet(bool in_c_heap)
+ : _in_c_heap(in_c_heap), _num(0), _stacks(NULL) { }
+
+ ~PreservedMarksSet() {
+ assert(_stacks == NULL && _num == 0, "stacks should have been reclaimed");
+ }
+};
+
+#endif // SHARE_VM_GC_SHARED_PRESERVEDMARKS_HPP
diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp b/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp
new file mode 100644
index 00000000000..32c83115a69
--- /dev/null
+++ b/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ */
+
+#include "gc/shared/preservedMarks.hpp"
+#include "oops/markOop.inline.hpp"
+#include "utilities/stack.inline.hpp"
+
+#ifndef SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP
+#define SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP
+
+inline bool PreservedMarks::should_preserve_mark(oop obj, markOop m) const {
+ return m->must_be_preserved_for_promotion_failure(obj);
+}
+
+inline void PreservedMarks::push(oop obj, markOop m) {
+ assert(should_preserve_mark(obj, m), "pre-condition");
+ OopAndMarkOop elem(obj, m);
+ _stack.push(elem);
+}
+
+inline void PreservedMarks::push_if_necessary(oop obj, markOop m) {
+ if (should_preserve_mark(obj, m)) {
+ push(obj, m);
+ }
+}
+
+#endif // SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP
From ef5eb42e40bfd979df5b4acd6a77e71134f71a15 Mon Sep 17 00:00:00 2001
From: Aleksey Shipilev
Date: Tue, 23 Feb 2016 17:55:28 +0300
Subject: [PATCH 078/311] 8150180: String.value contents should be trusted
Reviewed-by: vlivanov, redestad, jrose, twisti
---
.../share/classes/java/lang/String.java | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/jdk/src/java.base/share/classes/java/lang/String.java b/jdk/src/java.base/share/classes/java/lang/String.java
index 86ec043d5b1..85d22cbc1ec 100644
--- a/jdk/src/java.base/share/classes/java/lang/String.java
+++ b/jdk/src/java.base/share/classes/java/lang/String.java
@@ -42,6 +42,7 @@ import java.util.regex.PatternSyntaxException;
import java.util.stream.IntStream;
import java.util.stream.StreamSupport;
import jdk.internal.HotSpotIntrinsicCandidate;
+import jdk.internal.vm.annotation.Stable;
/**
* The {@code String} class represents character strings. All
@@ -119,7 +120,18 @@ import jdk.internal.HotSpotIntrinsicCandidate;
public final class String
implements java.io.Serializable, Comparable, CharSequence {
- /** The value is used for character storage. */
+ /**
+ * The value is used for character storage.
+ *
+ * @implNote This field is trusted by the VM, and is a subject to
+ * constant folding if String instance is constant. Overwriting this
+ * field after construction will cause problems.
+ *
+ * Additionally, it is marked with {@link Stable} to trust the contents
+ * of the array. No other facility in JDK provides this functionality (yet).
+ * {@link Stable} is safe here, because value is never null.
+ */
+ @Stable
private final byte[] value;
/**
@@ -129,6 +141,9 @@ public final class String
* LATIN1
* UTF16
*
+ * @implNote This field is trusted by the VM, and is a subject to
+ * constant folding if String instance is constant. Overwriting this
+ * field after construction will cause problems.
*/
private final byte coder;
From 4dfed6652630593769bf049be7ac2213ca47b69f Mon Sep 17 00:00:00 2001
From: Yingqi Lu
Date: Tue, 23 Feb 2016 17:41:00 +0000
Subject: [PATCH 079/311] 6432031: Add support for SO_REUSEPORT
Reviewed-by: alanb, simonis, chegar
---
jdk/make/mapfiles/libnet/mapfile-vers | 6 +-
jdk/make/mapfiles/libnio/mapfile-linux | 3 +-
jdk/make/mapfiles/libnio/mapfile-macosx | 3 +-
jdk/make/mapfiles/libnio/mapfile-solaris | 3 +-
.../genconstants/ch/genSocketOptionRegistry.c | 18 ++++-
.../net/AbstractPlainDatagramSocketImpl.java | 60 +++++++++++++-
.../java/net/AbstractPlainSocketImpl.java | 59 +++++++++++++-
.../classes/java/net/DatagramSocketImpl.java | 8 +-
.../classes/java/net/MulticastSocket.java | 14 +++-
.../share/classes/java/net/SocketImpl.java | 8 +-
.../share/classes/java/net/SocketOptions.java | 13 +++-
.../java/net/StandardSocketOptions.java | 25 +++++-
.../share/classes/jdk/net/Sockets.java | 32 +++++++-
.../AsynchronousServerSocketChannelImpl.java | 5 +-
.../nio/ch/AsynchronousSocketChannelImpl.java | 5 +-
.../sun/nio/ch/DatagramChannelImpl.java | 5 +-
.../share/classes/sun/nio/ch/Net.java | 17 +++-
.../sun/nio/ch/ServerSocketChannelImpl.java | 6 +-
.../classes/sun/nio/ch/SocketChannelImpl.java | 5 +-
.../java.base/share/native/libnet/net_util.c | 13 +++-
.../java.base/share/native/libnet/net_util.h | 4 +-
.../java/net/PlainDatagramSocketImpl.java | 25 +++++-
.../classes/java/net/PlainSocketImpl.java | 25 +++++-
.../native/libnet/PlainDatagramSocketImpl.c | 6 +-
.../java.base/unix/native/libnet/SdpSupport.c | 7 +-
.../java.base/unix/native/libnet/SocketImpl.c | 47 +++++++++++
.../unix/native/libnet/net_util_md.c | 22 +++++-
.../unix/native/libnet/net_util_md.h | 15 +++-
jdk/src/java.base/unix/native/libnio/ch/Net.c | 8 +-
.../unix/native/libnio/ch/nio_util.h | 14 +++-
.../net/DualStackPlainDatagramSocketImpl.java | 10 ++-
.../java/net/DualStackPlainSocketImpl.java | 10 ++-
.../classes/java/net/PlainSocketImpl.java | 23 +++++-
.../net/TwoStacksPlainDatagramSocketImpl.java | 8 +-
.../java/net/TwoStacksPlainSocketImpl.java | 9 ++-
.../windows/native/libnet/SocketImpl.c | 47 +++++++++++
.../windows/native/libnet/net_util_md.c | 7 +-
.../windows/native/libnet/net_util_md.h | 4 +
.../java.base/windows/native/libnio/ch/Net.c | 9 ++-
.../java/net/SocketOption/OptionsTest.java | 78 +++++++++++++------
.../Basic.java | 12 ++-
.../AsynchronousSocketChannel/Basic.java | 12 ++-
.../DatagramChannel/SocketOptionTests.java | 23 ++++--
.../SocketOptionTests.java | 11 ++-
44 files changed, 669 insertions(+), 75 deletions(-)
create mode 100644 jdk/src/java.base/unix/native/libnet/SocketImpl.c
create mode 100644 jdk/src/java.base/windows/native/libnet/SocketImpl.c
diff --git a/jdk/make/mapfiles/libnet/mapfile-vers b/jdk/make/mapfiles/libnet/mapfile-vers
index a37668a8418..82247780181 100644
--- a/jdk/make/mapfiles/libnet/mapfile-vers
+++ b/jdk/make/mapfiles/libnet/mapfile-vers
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2016, 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
@@ -87,6 +87,9 @@ SUNWprivate_1.1 {
Java_java_net_PlainSocketImpl_socketConnect;
Java_java_net_PlainDatagramSocketImpl_getTimeToLive;
Java_java_net_PlainDatagramSocketImpl_setTimeToLive;
+ Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0;
+ Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0;
+ Java_jdk_net_Sockets_isReusePortAvailable0;
Java_sun_net_PortConfig_getUpper0;
Java_sun_net_PortConfig_getLower0;
Java_sun_net_dns_ResolverConfigurationImpl_localDomain0;
@@ -112,6 +115,7 @@ SUNWprivate_1.1 {
NET_EnableFastTcpLoopback;
NET_ThrowNew;
ipv6_available;
+ reuseport_available;
initInetAddressIDs;
local:
diff --git a/jdk/make/mapfiles/libnio/mapfile-linux b/jdk/make/mapfiles/libnio/mapfile-linux
index b9b059a80c2..e4563b10c12 100644
--- a/jdk/make/mapfiles/libnio/mapfile-linux
+++ b/jdk/make/mapfiles/libnio/mapfile-linux
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 2016, 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
@@ -109,6 +109,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_Net_setIntOption0;
Java_sun_nio_ch_Net_initIDs;
Java_sun_nio_ch_Net_isIPv6Available0;
+ Java_sun_nio_ch_Net_isReusePortAvailable0;
Java_sun_nio_ch_Net_joinOrDrop4;
Java_sun_nio_ch_Net_blockOrUnblock4;
Java_sun_nio_ch_Net_joinOrDrop6;
diff --git a/jdk/make/mapfiles/libnio/mapfile-macosx b/jdk/make/mapfiles/libnio/mapfile-macosx
index 6e4a7fb594c..daee0371e3c 100644
--- a/jdk/make/mapfiles/libnio/mapfile-macosx
+++ b/jdk/make/mapfiles/libnio/mapfile-macosx
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 2016, 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
@@ -102,6 +102,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_Net_setIntOption0;
Java_sun_nio_ch_Net_initIDs;
Java_sun_nio_ch_Net_isIPv6Available0;
+ Java_sun_nio_ch_Net_isReusePortAvailable0;
Java_sun_nio_ch_Net_joinOrDrop4;
Java_sun_nio_ch_Net_blockOrUnblock4;
Java_sun_nio_ch_Net_joinOrDrop6;
diff --git a/jdk/make/mapfiles/libnio/mapfile-solaris b/jdk/make/mapfiles/libnio/mapfile-solaris
index 6834bd221d4..a1e0d99b0e6 100644
--- a/jdk/make/mapfiles/libnio/mapfile-solaris
+++ b/jdk/make/mapfiles/libnio/mapfile-solaris
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 2016, 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
@@ -97,6 +97,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_Net_setIntOption0;
Java_sun_nio_ch_Net_initIDs;
Java_sun_nio_ch_Net_isIPv6Available0;
+ Java_sun_nio_ch_Net_isReusePortAvailable0;
Java_sun_nio_ch_Net_joinOrDrop4;
Java_sun_nio_ch_Net_blockOrUnblock4;
Java_sun_nio_ch_Net_joinOrDrop6;
diff --git a/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c b/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c
index 41bd5484ab7..aab692f1f19 100644
--- a/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c
+++ b/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, 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,6 +34,21 @@
#include
#endif
+/* Defines SO_REUSEPORT */
+#if !defined(SO_REUSEPORT)
+#ifdef _WIN32
+#define SO_REUSEPORT 0
+#elif __linux__
+#define SO_REUSEPORT 15
+#elif __solaris__
+#define SO_REUSEPORT 0x100e
+#elif defined(AIX) || defined(MACOSX)
+#define SO_REUSEPORT 0x0200
+#else
+#define SO_REUSEPORT 0
+#endif
+#endif
+
/**
* Generates sun.nio.ch.SocketOptionRegistry, a class that maps Java-level
* socket options to the platform specific level and option.
@@ -102,6 +117,7 @@ int main(int argc, const char* argv[]) {
emit_unspec("StandardSocketOptions.SO_SNDBUF", SOL_SOCKET, SO_SNDBUF);
emit_unspec("StandardSocketOptions.SO_RCVBUF", SOL_SOCKET, SO_RCVBUF);
emit_unspec("StandardSocketOptions.SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR);
+ emit_unspec("StandardSocketOptions.SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT);
emit_unspec("StandardSocketOptions.TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY);
emit_inet("StandardSocketOptions.IP_TOS", IPPROTO_IP, IP_TOS);
diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
index 1f9eba1300e..7a9b7fc17ed 100644
--- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
+++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -28,6 +28,9 @@ import java.io.FileDescriptor;
import java.io.IOException;
import java.security.AccessController;
import sun.net.ResourceManager;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
/**
* Abstract datagram and multicast socket implementation base class.
@@ -70,6 +73,45 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
});
}
+ private static volatile boolean checkedReusePort;
+ private static volatile boolean isReusePortAvailable;
+
+ /**
+ * Tells whether SO_REUSEPORT is supported.
+ */
+ static boolean isReusePortAvailable() {
+ if (!checkedReusePort) {
+ isReusePortAvailable = isReusePortAvailable0();
+ checkedReusePort = true;
+ }
+ return isReusePortAvailable;
+ }
+
+ private static volatile Set> socketOptions;
+
+ /**
+ * Returns a set of SocketOptions supported by this impl
+ * and by this impl's socket (Socket or ServerSocket)
+ *
+ * @return a Set of SocketOptions
+ */
+ @Override
+ protected Set> supportedOptions() {
+ Set> options = socketOptions;
+ if (options == null) {
+ if (isReusePortAvailable()) {
+ options = new HashSet<>();
+ options.addAll(super.supportedOptions());
+ options.add(StandardSocketOptions.SO_REUSEPORT);
+ options = Collections.unmodifiableSet(options);
+ } else {
+ options = super.supportedOptions();
+ }
+ socketOptions = options;
+ }
+ return options;
+ }
+
/**
* Creates a datagram socket
*/
@@ -303,6 +345,14 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
if (o == null || !(o instanceof Boolean))
throw new SocketException("bad argument for IP_MULTICAST_LOOP");
break;
+ case SO_REUSEPORT:
+ if (o == null || !(o instanceof Boolean)) {
+ throw new SocketException("bad argument for SO_REUSEPORT");
+ }
+ if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+ throw new UnsupportedOperationException("unsupported option");
+ }
+ break;
default:
throw new SocketException("invalid option: " + optID);
}
@@ -343,6 +393,13 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
result = socketGetOption(optID);
break;
+ case SO_REUSEPORT:
+ if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+ throw new UnsupportedOperationException("unsupported option");
+ }
+ result = socketGetOption(optID);
+ break;
+
default:
throw new SocketException("invalid option: " + optID);
}
@@ -364,4 +421,5 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
}
abstract int dataAvailable();
+ private static native boolean isReusePortAvailable0();
}
diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
index 8841e4fe724..c9afa2657a2 100644
--- a/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
+++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, 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
@@ -33,6 +33,9 @@ import java.io.FileDescriptor;
import sun.net.ConnectionResetException;
import sun.net.NetHooks;
import sun.net.ResourceManager;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
/**
* Default Socket Implementation. This implementation does
@@ -87,6 +90,45 @@ abstract class AbstractPlainSocketImpl extends SocketImpl
});
}
+ private static volatile boolean checkedReusePort;
+ private static volatile boolean isReusePortAvailable;
+
+ /**
+ * Tells whether SO_REUSEPORT is supported.
+ */
+ static boolean isReusePortAvailable() {
+ if (!checkedReusePort) {
+ isReusePortAvailable = isReusePortAvailable0();
+ checkedReusePort = true;
+ }
+ return isReusePortAvailable;
+ }
+
+ private static volatile Set